Showing preview only (4,343K chars total). Download the full file or copy to clipboard to get everything.
Repository: mozilla/activity-stream
Branch: master
Commit: 15181967965c
Files: 426
Total size: 4.1 MB
Directory structure:
gitextract_p813z3cw/
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .mcignore
├── .nvmrc
├── .prettierrc
├── .sass-lint.yml
├── .taskcluster.yml
├── .travis.yml
├── AboutNewTabService.jsm
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── aboutlibrary/
│ ├── content/
│ │ └── aboutlibrary.xhtml
│ ├── jar.mn
│ └── moz.build
├── bin/
│ ├── bootstrap
│ ├── download-firefox-artifact
│ ├── prepare-mochitests-dev
│ ├── render-activity-stream-html.js
│ ├── try-runner.js
│ └── vendor.js
├── common/
│ ├── Actions.jsm
│ ├── Dedupe.jsm
│ ├── PerfService.jsm
│ └── Reducers.jsm
├── components.conf
├── content-src/
│ ├── .eslintrc.js
│ ├── aboutlibrary/
│ │ ├── aboutlibrary.jsx
│ │ └── aboutlibrary.scss
│ ├── activity-stream.jsx
│ ├── asrouter/
│ │ ├── README.md
│ │ ├── asrouter-content.jsx
│ │ ├── components/
│ │ │ ├── Button/
│ │ │ │ ├── Button.jsx
│ │ │ │ └── _Button.scss
│ │ │ ├── ConditionalWrapper/
│ │ │ │ └── ConditionalWrapper.jsx
│ │ │ ├── FxASignupForm/
│ │ │ │ ├── FxASignupForm.jsx
│ │ │ │ └── _FxASignupForm.scss
│ │ │ ├── ImpressionsWrapper/
│ │ │ │ └── ImpressionsWrapper.jsx
│ │ │ ├── ModalOverlay/
│ │ │ │ ├── ModalOverlay.jsx
│ │ │ │ └── _ModalOverlay.scss
│ │ │ ├── RichText/
│ │ │ │ └── RichText.jsx
│ │ │ └── SnippetBase/
│ │ │ ├── SnippetBase.jsx
│ │ │ └── _SnippetBase.scss
│ │ ├── docs/
│ │ │ ├── debugging-docs.md
│ │ │ ├── experiment-guide.md
│ │ │ ├── targeting-attributes.md
│ │ │ ├── targeting-guide.md
│ │ │ └── user-actions.md
│ │ ├── rich-text-strings.js
│ │ ├── schemas/
│ │ │ ├── message-format.md
│ │ │ ├── panel/
│ │ │ │ └── cfr-fxa-bookmark.schema.json
│ │ │ └── provider-response.schema.json
│ │ ├── template-utils.js
│ │ └── templates/
│ │ ├── CFR/
│ │ │ └── templates/
│ │ │ └── ExtensionDoorhanger.schema.json
│ │ ├── EOYSnippet/
│ │ │ ├── EOYSnippet.jsx
│ │ │ ├── EOYSnippet.schema.json
│ │ │ └── _EOYSnippet.scss
│ │ ├── FXASignupSnippet/
│ │ │ ├── FXASignupSnippet.jsx
│ │ │ └── FXASignupSnippet.schema.json
│ │ ├── FirstRun/
│ │ │ ├── FirstRun.jsx
│ │ │ ├── Interrupt.jsx
│ │ │ ├── Triplets.jsx
│ │ │ └── addUtmParams.js
│ │ ├── FullPageInterrupt/
│ │ │ ├── FullPageInterrupt.jsx
│ │ │ └── _FullPageInterrupt.scss
│ │ ├── NewsletterSnippet/
│ │ │ ├── NewsletterSnippet.jsx
│ │ │ └── NewsletterSnippet.schema.json
│ │ ├── OnboardingMessage/
│ │ │ ├── OnboardingMessage.jsx
│ │ │ ├── OnboardingMessage.schema.json
│ │ │ ├── ToolbarBadgeMessage.schema.json
│ │ │ ├── UpdateAction.schema.json
│ │ │ ├── WhatsNewMessage.schema.json
│ │ │ └── _OnboardingMessage.scss
│ │ ├── ReturnToAMO/
│ │ │ ├── ReturnToAMO.jsx
│ │ │ └── _ReturnToAMO.scss
│ │ ├── SendToDeviceSnippet/
│ │ │ ├── SendToDeviceSnippet.jsx
│ │ │ ├── SendToDeviceSnippet.schema.json
│ │ │ └── isEmailOrPhoneNumber.js
│ │ ├── SimpleBelowSearchSnippet/
│ │ │ ├── SimpleBelowSearchSnippet.jsx
│ │ │ ├── SimpleBelowSearchSnippet.schema.json
│ │ │ └── _SimpleBelowSearchSnippet.scss
│ │ ├── SimpleSnippet/
│ │ │ ├── SimpleSnippet.jsx
│ │ │ ├── SimpleSnippet.schema.json
│ │ │ └── _SimpleSnippet.scss
│ │ ├── SubmitFormSnippet/
│ │ │ ├── SubmitFormSnippet.jsx
│ │ │ ├── SubmitFormSnippet.schema.json
│ │ │ └── _SubmitFormSnippet.scss
│ │ ├── Trailhead/
│ │ │ ├── Trailhead.jsx
│ │ │ └── _Trailhead.scss
│ │ └── template-manifest.jsx
│ ├── components/
│ │ ├── A11yLinkButton/
│ │ │ ├── A11yLinkButton.jsx
│ │ │ └── _A11yLinkButton.scss
│ │ ├── ASRouterAdmin/
│ │ │ ├── ASRouterAdmin.jsx
│ │ │ ├── ASRouterAdmin.scss
│ │ │ └── SimpleHashRouter.jsx
│ │ ├── Base/
│ │ │ ├── Base.jsx
│ │ │ └── _Base.scss
│ │ ├── Card/
│ │ │ ├── Card.jsx
│ │ │ ├── _Card.scss
│ │ │ └── types.js
│ │ ├── CollapsibleSection/
│ │ │ ├── CollapsibleSection.jsx
│ │ │ └── _CollapsibleSection.scss
│ │ ├── ComponentPerfTimer/
│ │ │ └── ComponentPerfTimer.jsx
│ │ ├── ConfirmDialog/
│ │ │ ├── ConfirmDialog.jsx
│ │ │ └── _ConfirmDialog.scss
│ │ ├── ContextMenu/
│ │ │ ├── ContextMenu.jsx
│ │ │ ├── ContextMenuButton.jsx
│ │ │ └── _ContextMenu.scss
│ │ ├── DiscoveryStreamBase/
│ │ │ ├── DiscoveryStreamBase.jsx
│ │ │ └── _DiscoveryStreamBase.scss
│ │ ├── DiscoveryStreamComponents/
│ │ │ ├── CardGrid/
│ │ │ │ ├── CardGrid.jsx
│ │ │ │ └── _CardGrid.scss
│ │ │ ├── DSCard/
│ │ │ │ ├── DSCard.jsx
│ │ │ │ └── _DSCard.scss
│ │ │ ├── DSContextFooter/
│ │ │ │ ├── DSContextFooter.jsx
│ │ │ │ └── _DSContextFooter.scss
│ │ │ ├── DSDismiss/
│ │ │ │ ├── DSDismiss.jsx
│ │ │ │ └── _DSDismiss.scss
│ │ │ ├── DSEmptyState/
│ │ │ │ ├── DSEmptyState.jsx
│ │ │ │ └── _DSEmptyState.scss
│ │ │ ├── DSImage/
│ │ │ │ ├── DSImage.jsx
│ │ │ │ └── _DSImage.scss
│ │ │ ├── DSLinkMenu/
│ │ │ │ ├── DSLinkMenu.jsx
│ │ │ │ └── _DSLinkMenu.scss
│ │ │ ├── DSMessage/
│ │ │ │ ├── DSMessage.jsx
│ │ │ │ └── _DSMessage.scss
│ │ │ ├── DSPrivacyModal/
│ │ │ │ ├── DSPrivacyModal.jsx
│ │ │ │ └── _DSPrivacyModal.scss
│ │ │ ├── DSTextPromo/
│ │ │ │ ├── DSTextPromo.jsx
│ │ │ │ └── _DSTextPromo.scss
│ │ │ ├── Hero/
│ │ │ │ ├── Hero.jsx
│ │ │ │ └── _Hero.scss
│ │ │ ├── Highlights/
│ │ │ │ ├── Highlights.jsx
│ │ │ │ └── _Highlights.scss
│ │ │ ├── HorizontalRule/
│ │ │ │ ├── HorizontalRule.jsx
│ │ │ │ └── _HorizontalRule.scss
│ │ │ ├── List/
│ │ │ │ ├── List.jsx
│ │ │ │ └── _List.scss
│ │ │ ├── Navigation/
│ │ │ │ ├── Navigation.jsx
│ │ │ │ └── _Navigation.scss
│ │ │ ├── SafeAnchor/
│ │ │ │ └── SafeAnchor.jsx
│ │ │ ├── SectionTitle/
│ │ │ │ ├── SectionTitle.jsx
│ │ │ │ └── _SectionTitle.scss
│ │ │ └── TopSites/
│ │ │ ├── TopSites.jsx
│ │ │ └── _TopSites.scss
│ │ ├── DiscoveryStreamImpressionStats/
│ │ │ ├── ImpressionStats.jsx
│ │ │ └── _ImpressionStats.scss
│ │ ├── ErrorBoundary/
│ │ │ ├── ErrorBoundary.jsx
│ │ │ └── _ErrorBoundary.scss
│ │ ├── FluentOrText/
│ │ │ └── FluentOrText.jsx
│ │ ├── LinkMenu/
│ │ │ └── LinkMenu.jsx
│ │ ├── MoreRecommendations/
│ │ │ ├── MoreRecommendations.jsx
│ │ │ └── _MoreRecommendations.scss
│ │ ├── PocketLoggedInCta/
│ │ │ ├── PocketLoggedInCta.jsx
│ │ │ └── _PocketLoggedInCta.scss
│ │ ├── Search/
│ │ │ ├── Search.jsx
│ │ │ └── _Search.scss
│ │ ├── SectionMenu/
│ │ │ └── SectionMenu.jsx
│ │ ├── Sections/
│ │ │ ├── Sections.jsx
│ │ │ └── _Sections.scss
│ │ ├── TopSites/
│ │ │ ├── SearchShortcutsForm.jsx
│ │ │ ├── TopSite.jsx
│ │ │ ├── TopSiteForm.jsx
│ │ │ ├── TopSiteFormInput.jsx
│ │ │ ├── TopSites.jsx
│ │ │ ├── TopSitesConstants.js
│ │ │ └── _TopSites.scss
│ │ └── Topics/
│ │ ├── Topics.jsx
│ │ └── _Topics.scss
│ ├── lib/
│ │ ├── constants.js
│ │ ├── detect-user-session-start.js
│ │ ├── init-store.js
│ │ ├── link-menu-options.js
│ │ ├── screenshot-utils.js
│ │ ├── section-menu-options.js
│ │ └── selectLayoutRender.js
│ └── styles/
│ ├── _activity-stream.scss
│ ├── _icons.scss
│ ├── _mixins.scss
│ ├── _normalize.scss
│ ├── _theme.scss
│ ├── _variables.scss
│ ├── activity-stream-linux.scss
│ ├── activity-stream-mac.scss
│ └── activity-stream-windows.scss
├── contributing.md
├── data/
│ └── content/
│ └── tippytop/
│ └── top_sites.json
├── docs/
│ ├── ISSUE_TEMPLATE.md
│ ├── index.rst
│ └── v2-system-addon/
│ ├── 1.GETTING_STARTED.md
│ ├── data_dictionary.md
│ ├── data_events.md
│ ├── geo_locale.md
│ ├── mochitests.md
│ ├── preferences.md
│ ├── remote_cfr.md
│ ├── sections.md
│ ├── telemetry.md
│ ├── test-merges.md
│ ├── tippytop.md
│ └── unit_testing_guide.md
├── hooks/
│ ├── post-commit
│ └── pre-commit
├── jar.mn
├── karma.mc.config.js
├── lib/
│ ├── ASRouter.jsm
│ ├── ASRouterFeed.jsm
│ ├── ASRouterPreferences.jsm
│ ├── ASRouterTargeting.jsm
│ ├── ASRouterTriggerListeners.jsm
│ ├── AboutPreferences.jsm
│ ├── ActivityStream.jsm
│ ├── ActivityStreamMessageChannel.jsm
│ ├── ActivityStreamPrefs.jsm
│ ├── ActivityStreamStorage.jsm
│ ├── BookmarkPanelHub.jsm
│ ├── CFRMessageProvider.jsm
│ ├── CFRPageActions.jsm
│ ├── DiscoveryStreamFeed.jsm
│ ├── DownloadsManager.jsm
│ ├── FaviconFeed.jsm
│ ├── FilterAdult.jsm
│ ├── HighlightsFeed.jsm
│ ├── LinksCache.jsm
│ ├── NaiveBayesTextTagger.jsm
│ ├── NewTabInit.jsm
│ ├── NmfTextTagger.jsm
│ ├── OnboardingMessageProvider.jsm
│ ├── PanelTestProvider.jsm
│ ├── PersistentCache.jsm
│ ├── PersonalityProvider.jsm
│ ├── PlacesFeed.jsm
│ ├── PrefsFeed.jsm
│ ├── RecipeExecutor.jsm
│ ├── RemoteL10n.jsm
│ ├── Screenshots.jsm
│ ├── SearchShortcuts.jsm
│ ├── SectionsManager.jsm
│ ├── ShortURL.jsm
│ ├── SiteClassifier.jsm
│ ├── SnippetsTestMessageProvider.jsm
│ ├── Store.jsm
│ ├── SystemTickFeed.jsm
│ ├── TelemetryFeed.jsm
│ ├── TippyTopProvider.jsm
│ ├── Tokenize.jsm
│ ├── ToolbarBadgeHub.jsm
│ ├── ToolbarPanelHub.jsm
│ ├── TopSitesFeed.jsm
│ ├── TopStoriesFeed.jsm
│ ├── UTEventReporting.jsm
│ └── UserDomainAffinityProvider.jsm
├── loaders/
│ └── inject-loader.js
├── mochitest.sh
├── moz.build
├── nsIAboutNewTabService.idl
├── package.json
├── ping-centre/
│ └── PingCentre.jsm
├── test/
│ ├── .eslintrc.js
│ ├── browser/
│ │ ├── blue_page.html
│ │ ├── browser.ini
│ │ ├── browser_aboutwelcome.js
│ │ ├── browser_as_load_location.js
│ │ ├── browser_as_render.js
│ │ ├── browser_asrouter_bookmarkpanel.js
│ │ ├── browser_asrouter_cfr.js
│ │ ├── browser_asrouter_snippets.js
│ │ ├── browser_asrouter_targeting.js
│ │ ├── browser_asrouter_toolbarbadge.js
│ │ ├── browser_asrouter_trigger_listeners.js
│ │ ├── browser_asrouter_whatsnewpanel.js
│ │ ├── browser_discovery_render.js
│ │ ├── browser_discovery_styles.js
│ │ ├── browser_enabled_newtabpage.js
│ │ ├── browser_getScreenshots.js
│ │ ├── browser_highlights_section.js
│ │ ├── browser_newtab_overrides.js
│ │ ├── browser_onboarding_rtamo.js
│ │ ├── browser_topsites_contextMenu_options.js
│ │ ├── browser_topsites_section.js
│ │ ├── head.js
│ │ └── red_page.html
│ ├── schemas/
│ │ └── pings.js
│ ├── unit/
│ │ ├── asrouter/
│ │ │ ├── ASRouter.test.js
│ │ │ ├── ASRouterFeed.test.js
│ │ │ ├── ASRouterPreferences.test.js
│ │ │ ├── ASRouterTargeting.test.js
│ │ │ ├── ASRouterTriggerListeners.test.js
│ │ │ ├── CFRMessageProvider.test.js
│ │ │ ├── CFRPageActions.test.js
│ │ │ ├── MessageLoaderUtils.test.js
│ │ │ ├── ModalOverlay.test.jsx
│ │ │ ├── PanelTestProvider.test.js
│ │ │ ├── RemoteL10n.test.js
│ │ │ ├── RichText.test.jsx
│ │ │ ├── SnippetsTestMessageProvider.test.js
│ │ │ ├── TargetingDocs.test.js
│ │ │ ├── asrouter-content.test.jsx
│ │ │ ├── compatibility-reference/
│ │ │ │ ├── fx57-compat.test.js
│ │ │ │ └── snippets-fx57.js
│ │ │ ├── constants.js
│ │ │ ├── schemas/
│ │ │ │ └── panel/
│ │ │ │ └── cfr-fxa-bookmark.schema.test.js
│ │ │ ├── template-utils.test.js
│ │ │ └── templates/
│ │ │ ├── EOYSnippet.test.jsx
│ │ │ ├── ExtensionDoorhanger.test.jsx
│ │ │ ├── FXASignupSnippet.test.jsx
│ │ │ ├── FirstRun.test.jsx
│ │ │ ├── FullPageInterrupt.test.jsx
│ │ │ ├── FxASignupForm.test.jsx
│ │ │ ├── Interrupt.test.jsx
│ │ │ ├── NewsletterSnippet.test.jsx
│ │ │ ├── OnboardingMessage.test.jsx
│ │ │ ├── SendToDeviceSnippet.test.jsx
│ │ │ ├── SimpleBelowSearchSnippet.test.jsx
│ │ │ ├── SimpleSnippet.test.jsx
│ │ │ ├── SubmitFormSnippet.test.jsx
│ │ │ ├── Trailhead.test.jsx
│ │ │ ├── Triplets.test.jsx
│ │ │ └── isEmailOrPhoneNumber.test.js
│ │ ├── common/
│ │ │ ├── Actions.test.js
│ │ │ ├── Dedupe.test.js
│ │ │ ├── PerfService.test.js
│ │ │ └── Reducers.test.js
│ │ ├── content-src/
│ │ │ ├── components/
│ │ │ │ ├── ASRouterAdmin.test.jsx
│ │ │ │ ├── Base.test.jsx
│ │ │ │ ├── Card.test.jsx
│ │ │ │ ├── CollapsibleSection.test.jsx
│ │ │ │ ├── ComponentPerfTimer.test.jsx
│ │ │ │ ├── ConfirmDialog.test.jsx
│ │ │ │ ├── ContextMenu.test.jsx
│ │ │ │ ├── DiscoveryStreamBase.test.jsx
│ │ │ │ ├── DiscoveryStreamComponents/
│ │ │ │ │ ├── CardGrid.test.jsx
│ │ │ │ │ ├── DSCard.test.jsx
│ │ │ │ │ ├── DSContextFooter.test.jsx
│ │ │ │ │ ├── DSDismiss.test.jsx
│ │ │ │ │ ├── DSEmptyState.test.jsx
│ │ │ │ │ ├── DSImage.test.jsx
│ │ │ │ │ ├── DSLinkMenu.test.jsx
│ │ │ │ │ ├── DSMessage.test.jsx
│ │ │ │ │ ├── DSPrivacyModal.test.jsx
│ │ │ │ │ ├── DSTextPromo.test.jsx
│ │ │ │ │ ├── Hero.test.jsx
│ │ │ │ │ ├── Highlights.test.jsx
│ │ │ │ │ ├── HorizontalRule.test.jsx
│ │ │ │ │ ├── ImpressionStats.test.jsx
│ │ │ │ │ ├── List.test.jsx
│ │ │ │ │ ├── Navigation.test.jsx
│ │ │ │ │ ├── SafeAnchor.test.jsx
│ │ │ │ │ ├── SectionTitle.test.jsx
│ │ │ │ │ └── TopSites.test.jsx
│ │ │ │ ├── ErrorBoundary.test.jsx
│ │ │ │ ├── FluentOrText.test.jsx
│ │ │ │ ├── LinkMenu.test.jsx
│ │ │ │ ├── MoreRecommendations.test.jsx
│ │ │ │ ├── PocketLoggedInCta.test.jsx
│ │ │ │ ├── ReturnToAMO.test.jsx
│ │ │ │ ├── Search.test.jsx
│ │ │ │ ├── SectionMenu.test.jsx
│ │ │ │ ├── Sections.test.jsx
│ │ │ │ ├── TopSites/
│ │ │ │ │ └── SearchShortcutsForm.test.jsx
│ │ │ │ ├── TopSites.test.jsx
│ │ │ │ ├── Topics.test.jsx
│ │ │ │ └── addUtmParams.test.js
│ │ │ └── lib/
│ │ │ ├── detect-user-session-start.test.js
│ │ │ ├── init-store.test.js
│ │ │ ├── screenshot-utils.test.js
│ │ │ └── selectLayoutRender.test.js
│ │ ├── lib/
│ │ │ ├── AboutPreferences.test.js
│ │ │ ├── ActivityStream.test.js
│ │ │ ├── ActivityStreamMessageChannel.test.js
│ │ │ ├── ActivityStreamPrefs.test.js
│ │ │ ├── ActivityStreamStorage.test.js
│ │ │ ├── BookmarkPanelHub.test.js
│ │ │ ├── DiscoveryStreamFeed.test.js
│ │ │ ├── DownloadsManager.test.js
│ │ │ ├── FaviconFeed.test.js
│ │ │ ├── FilterAdult.test.js
│ │ │ ├── HighlightsFeed.test.js
│ │ │ ├── LinksCache.test.js
│ │ │ ├── NaiveBayesTextTagger.test.js
│ │ │ ├── NewTabInit.test.js
│ │ │ ├── NmfTextTagger.test.js
│ │ │ ├── PersistentCache.test.js
│ │ │ ├── PersonalityProvider.test.js
│ │ │ ├── PlacesFeed.test.js
│ │ │ ├── PrefsFeed.test.js
│ │ │ ├── RecipeExecutor.test.js
│ │ │ ├── Screenshots.test.js
│ │ │ ├── SectionsManager.test.js
│ │ │ ├── ShortUrl.test.js
│ │ │ ├── SiteClassifier.test.js
│ │ │ ├── Store.test.js
│ │ │ ├── SystemTickFeed.test.js
│ │ │ ├── TelemetryFeed.test.js
│ │ │ ├── TippyTopProvider.test.js
│ │ │ ├── Tokenize.test.js
│ │ │ ├── ToolbarBadgeHub.test.js
│ │ │ ├── ToolbarPanelHub.test.js
│ │ │ ├── TopSitesFeed.test.js
│ │ │ ├── TopStoriesFeed.test.js
│ │ │ ├── UTEventReporting.test.js
│ │ │ └── UserDomainAffinityProvider.test.js
│ │ ├── ping-centre/
│ │ │ └── PingCentre.test.js
│ │ ├── unit-entry.js
│ │ └── utils.js
│ └── xpcshell/
│ ├── test_ASRouterTargeting_attribution.js
│ ├── test_AboutNewTabService.js
│ └── xpcshell.ini
├── vendor/
│ ├── PROP_TYPES_LICENSE
│ ├── REACT_AND_REACT_DOM_LICENSE
│ ├── REACT_REDUX_LICENSE
│ ├── REACT_TRANSITION_GROUP_LICENSE
│ ├── REDUX_LICENSE
│ ├── Redux.jsm
│ ├── prop-types.js
│ ├── react-dev.js
│ ├── react-dom-dev.js
│ ├── react-dom.js
│ ├── react-redux.js
│ ├── react-transition-group.js
│ ├── react.js
│ └── redux.js
├── webpack.aboutlibrary.config.js
├── webpack.system-addon.config.js
└── yamscripts.yml
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintignore
================================================
data/
logs/
vendor/
================================================
FILE: .eslintrc.js
================================================
module.exports = {
// When adding items to this file please check for effects on sub-directories.
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 2018,
"ecmaFeatures": {
"jsx": true
},
"sourceType": "module"
},
"env": {
"node": true
},
"plugins": [
"import", // require("eslint-plugin-import")
"react", // require("eslint-plugin-react")
"jsx-a11y", // require("eslint-plugin-jsx-a11y")
// Temporarily disabled since they aren't vendored into in mozilla central yet
// "react-hooks", // require("react-hooks")
],
"settings": {
"react": {
"version": "16.2.0"
}
},
"extends": [
"eslint:recommended",
"plugin:jsx-a11y/recommended", // require("eslint-plugin-jsx-a11y")
"plugin:mozilla/recommended", // require("eslint-plugin-mozilla") require("eslint-plugin-fetch-options") require("eslint-plugin-html") require("eslint-plugin-no-unsanitized")
"plugin:mozilla/browser-test",
"plugin:mozilla/mochitest-test",
"plugin:mozilla/xpcshell-test",
"plugin:prettier/recommended", // require("eslint-plugin-prettier")
"prettier/react", // require("eslint-config-prettier")
],
"globals": {
// Remove this when m-c updates their eslint: See https://github.com/mozilla/activity-stream/pull/4219
"RPMSendAsyncMessage": true,
"NewTabPagePreloading": true,
},
"overrides": [
{
// These files use fluent-dom to insert content
"files": [
"content-src/asrouter/templates/OnboardingMessage/**",
"content-src/asrouter/templates/FirstRun/**",
"content-src/asrouter/templates/Trailhead/**",
"content-src/asrouter/templates/FullPageInterrupt/FullPageInterrupt.jsx",
"content-src/asrouter/components/FxASignupForm/FxASignupForm.jsx",
"content-src/components/TopSites/**",
"content-src/components/MoreRecommendations/MoreRecommendations.jsx",
"content-src/components/CollapsibleSection/CollapsibleSection.jsx",
"content-src/components/DiscoveryStreamComponents/DSEmptyState/DSEmptyState.jsx",
"content-src/components/DiscoveryStreamComponents/DSPrivacyModal/DSPrivacyModal.jsx"
],
"rules": {
"jsx-a11y/anchor-has-content": 0,
"jsx-a11y/heading-has-content": 0,
}
},
{
// Use a configuration that's more appropriate for JSMs
"files": "**/*.jsm",
"parserOptions": {
"sourceType": "script"
},
"env": {
"node": false
},
"rules": {
"no-implicit-globals": 0
}
}
],
"rules": {
// "react-hooks/rules-of-hooks": 2,
"fetch-options/no-fetch-credentials": 2,
"react/jsx-boolean-value": [2, "always"],
"react/jsx-key": 2,
"react/jsx-no-bind": 2,
"react/jsx-no-comment-textnodes": 2,
"react/jsx-no-duplicate-props": 2,
"react/jsx-no-target-blank": 2,
"react/jsx-no-undef": 2,
"react/jsx-pascal-case": 2,
"react/jsx-uses-react": 2,
"react/jsx-uses-vars": 2,
"react/no-access-state-in-setstate": 2,
"react/no-danger": 2,
"react/no-deprecated": 2,
"react/no-did-mount-set-state": 2,
"react/no-did-update-set-state": 2,
"react/no-direct-mutation-state": 2,
"react/no-is-mounted": 2,
"react/no-unknown-property": 2,
"react/require-render-return": 2,
"accessor-pairs": [2, {"setWithoutGet": true, "getWithoutSet": false}],
"array-callback-return": 2,
"block-scoped-var": 2,
"callback-return": 0,
"camelcase": 0,
"capitalized-comments": 0,
"class-methods-use-this": 0,
"consistent-this": [2, "use-bind"],
"default-case": 0,
"eqeqeq": 2,
"for-direction": 2,
"func-name-matching": 2,
"func-names": 0,
"func-style": 0,
"getter-return": 2,
"global-require": 0,
"guard-for-in": 2,
"handle-callback-err": 2,
"id-blacklist": 0,
"id-length": 0,
"id-match": 0,
"init-declarations": 0,
"line-comment-position": 0,
"lines-between-class-members": 2,
"max-depth": [2, 4],
"max-lines": 0,
"max-nested-callbacks": [2, 4],
"max-params": [2, 6],
"max-statements": [2, 50],
"max-statements-per-line": [2, {"max": 2}],
"multiline-comment-style": 0,
"new-cap": [2, {"newIsCap": true, "capIsNew": false}],
"newline-after-var": 0,
"newline-before-return": 0,
"no-alert": 2,
"no-await-in-loop": 0,
"no-bitwise": 0,
"no-buffer-constructor": 2,
"no-catch-shadow": 2,
"no-console": 1,
"no-continue": 0,
"no-div-regex": 2,
"no-duplicate-imports": 2,
"no-empty-function": 0,
"no-eq-null": 2,
"no-extend-native": 2,
"no-extra-label": 2,
"no-implicit-coercion": [2, {"allow": ["!!"]}],
"no-implicit-globals": 2,
"no-inline-comments": 0,
"no-invalid-this": 0,
"no-label-var": 2,
"no-loop-func": 2,
"no-magic-numbers": 0,
"no-mixed-requires": 2,
"no-multi-assign": 2,
"no-multi-str": 2,
"no-negated-condition": 0,
"no-negated-in-lhs": 2,
"no-new": 2,
"no-new-func": 2,
"no-new-require": 2,
"no-octal-escape": 2,
"no-param-reassign": 2,
"no-path-concat": 2,
"no-plusplus": 0,
"no-process-env": 0,
"no-process-exit": 2,
"no-proto": 2,
"no-prototype-builtins": 2,
"no-restricted-globals": 0,
"no-restricted-imports": 0,
"no-restricted-modules": 0,
"no-restricted-properties": 0,
"no-restricted-syntax": 0,
"no-return-assign": [2, "except-parens"],
"no-script-url": 2,
"no-shadow": 2,
"no-sync": 0,
"no-template-curly-in-string": 2,
"no-ternary": 0,
"no-undef-init": 2,
"no-undefined": 0,
"no-underscore-dangle": 0,
"no-unmodified-loop-condition": 2,
"no-unused-expressions": 2,
"no-use-before-define": 2,
"no-useless-computed-key": 2,
"no-useless-constructor": 2,
"no-useless-rename": 2,
"no-var": 2,
"no-void": 2,
"no-warning-comments": 0, // TODO: Change to `1`?
"one-var": [2, "never"],
"operator-assignment": [2, "always"],
"padding-line-between-statements": 0,
"prefer-const": 0, // TODO: Change to `1`?
"prefer-destructuring": [2, {"AssignmentExpression": {"array": true}, "VariableDeclarator": {"array": true, "object": true}}],
"prefer-numeric-literals": 2,
"prefer-promise-reject-errors": 2,
"prefer-reflect": 0,
"prefer-rest-params": 2,
"prefer-spread": 2,
"prefer-template": 2,
"radix": [2, "always"],
"require-await": 2,
"require-jsdoc": 0,
"sort-keys": 0,
"sort-vars": 2,
"strict": 0,
"symbol-description": 2,
"valid-jsdoc": [0, {"requireReturn": false, "requireParamDescription": false, "requireReturnDescription": false}],
"vars-on-top": 2,
"yoda": [2, "never"]
}
};
================================================
FILE: .gitignore
================================================
node_modules
npm-debug.log
.DS_Store
.eslintcache
*.sw[po]
*.xpi
*.pyc
logs/
dist/
firefox/
*.update.rdf
data/content/activity-stream.bundle.js
css/*.css
prerendered/
aboutlibrary/content/aboutlibrary.bundle.js
aboutlibrary/content/*.map
aboutlibrary/content/*.css
================================================
FILE: .mcignore
================================================
npm-debug.log
.DS_Store
*.sw[po]
*.xpi
*.pyc
*.update.rdf
.gitignore
.eslintcache
/.git/
/dist/
/logs/
/node_modules/
# ignore README since it's GitHub specific
/README.md
# also ignores ping centre tests
ping-centre/
# ignore things from about:library for now
aboutlibrary/
content-src/aboutlibrary/
================================================
FILE: .nvmrc
================================================
8.16
================================================
FILE: .prettierrc
================================================
{
"printWidth": 80,
"tabWidth": 2,
"trailingComma": "es5"
}
================================================
FILE: .sass-lint.yml
================================================
options:
merge-default-rules: true
max-warnings: 0
files:
include: 'content-src/**/*.scss'
rules:
class-name-format: 0
extends-before-declarations: 2
extends-before-mixins: 2
force-element-nesting: 0
force-pseudo-nesting: 0
hex-notation: [2, {style: uppercase}]
indentation: [2, {size: 2}]
leading-zero: [2, {include: true}]
mixins-before-declarations: [2, {exclude: [breakpoint, mq]}]
nesting-depth: [2, {max-depth: 4}]
no-debug: 1
no-disallowed-properties: [1, {properties: [margin-left, margin-right, text-transform]}]
no-duplicate-properties: 2
no-misspelled-properties: [2, {extra-properties: [-moz-context-properties]}]
no-url-domains: 0
no-vendor-prefixes: 0
no-warn: 1
placeholder-in-extend: 2
property-sort-order: 0
================================================
FILE: .taskcluster.yml
================================================
version: 1
policy:
pullRequests: public
tasks:
$if: 'tasks_for in ["github-push", "github-pull-request"]'
then:
$let:
repo_url:
$if: 'tasks_for == "github-push"'
then: ${event.repository.clone_url}
else: ${event.pull_request.head.repo.clone_url}
ref:
$if: 'tasks_for == "github-push"'
then: ${event.after}
else: ${event.pull_request.head.sha}
in:
- provisionerId: proj-misc
workerType: ci
deadline: ${fromNow('1 day')}
payload:
maxRunTime: 7200
image: piatra/asmochitests
command:
- /bin/bash
- '--login'
- '-c'
- >-
git clone ${repo_url} /activity-stream && cd /activity-stream &&
git checkout ${ref} && bash ./mochitest.sh
metadata:
name: activitystream
description: run mochitests for PRs
owner: noreply@mozilla.com
source: ${repo_url}
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
# when changing this, be sure to edit .nvrmc and package.json too
- 8
python:
- "2.7"
addons:
# Run unit tests in Nightly to be in line with what Firefox tests would run against
firefox: "latest-nightly"
cache:
directories:
- node_modules
before_install:
# see https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI
- "export DISPLAY=:99.0"
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 -extension RANDR"
- export PATH="$PATH:$HOME/.rvm/bin"
- export PATH="$PATH:./node_modules/.bin"
- sleep 3
install:
- npm config set spin false
- npm install
script:
- npm test
notifications:
email: false
================================================
FILE: AboutNewTabService.jsm
================================================
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
"use strict";
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { AppConstants } = ChromeUtils.import(
"resource://gre/modules/AppConstants.jsm"
);
const { E10SUtils } = ChromeUtils.import(
"resource://gre/modules/E10SUtils.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"AboutNewTab",
"resource:///modules/AboutNewTab.jsm"
);
const TOPIC_APP_QUIT = "quit-application-granted";
const TOPIC_CONTENT_DOCUMENT_INTERACTIVE = "content-document-interactive";
const ABOUT_URL = "about:newtab";
const BASE_URL = "resource://activity-stream/";
const ACTIVITY_STREAM_PAGES = new Set(["home", "newtab", "welcome"]);
const IS_MAIN_PROCESS =
Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_DEFAULT;
const IS_PRIVILEGED_PROCESS =
Services.appinfo.remoteType === E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE;
const IS_RELEASE_OR_BETA = AppConstants.RELEASE_OR_BETA;
const PREF_SEPARATE_PRIVILEGEDABOUT_CONTENT_PROCESS =
"browser.tabs.remote.separatePrivilegedContentProcess";
const PREF_ACTIVITY_STREAM_DEBUG = "browser.newtabpage.activity-stream.debug";
function AboutNewTabService() {
Services.obs.addObserver(this, TOPIC_APP_QUIT);
Services.prefs.addObserver(
PREF_SEPARATE_PRIVILEGEDABOUT_CONTENT_PROCESS,
this
);
if (!IS_RELEASE_OR_BETA) {
Services.prefs.addObserver(PREF_ACTIVITY_STREAM_DEBUG, this);
}
// More initialization happens here
this.toggleActivityStream(true);
this.initialized = true;
this.alreadyRecordedTopsitesPainted = false;
if (IS_MAIN_PROCESS) {
AboutNewTab.init();
} else if (IS_PRIVILEGED_PROCESS) {
Services.obs.addObserver(this, TOPIC_CONTENT_DOCUMENT_INTERACTIVE);
}
}
/*
* A service that allows for the overriding, at runtime, of the newtab page's url.
*
* There is tight coupling with browser/about/AboutRedirector.cpp.
*
* 1. Browser chrome access:
*
* When the user issues a command to open a new tab page, usually clicking a button
* in the browser chrome or using shortcut keys, the browser chrome code invokes the
* service to obtain the newtab URL. It then loads that URL in a new tab.
*
* When not overridden, the default URL emitted by the service is "about:newtab".
* When overridden, it returns the overriden URL.
*
* 2. Redirector Access:
*
* When the URL loaded is about:newtab, the default behavior, or when entered in the
* URL bar, the redirector is hit. The service is then called to return the
* appropriate activity stream url based on prefs.
*
* NOTE: "about:newtab" will always result in a default newtab page, and never an overridden URL.
*
* Access patterns:
*
* The behavior is different when accessing the service via browser chrome or via redirector
* largely to maintain compatibility with expectations of add-on developers.
*
* Loading a chrome resource, or an about: URL in the redirector with either the
* LOAD_NORMAL or LOAD_REPLACE flags yield unexpected behaviors, so a roundtrip
* to the redirector from browser chrome is avoided.
*/
AboutNewTabService.prototype = {
_newTabURL: ABOUT_URL,
_activityStreamEnabled: false,
_activityStreamDebug: false,
_privilegedAboutContentProcess: false,
_overridden: false,
willNotifyUser: false,
classID: Components.ID("{dfcd2adc-7867-4d3a-ba70-17501f208142}"),
QueryInterface: ChromeUtils.generateQI([
Ci.nsIAboutNewTabService,
Ci.nsIObserver,
]),
observe(subject, topic, data) {
switch (topic) {
case "nsPref:changed":
if (data === PREF_SEPARATE_PRIVILEGEDABOUT_CONTENT_PROCESS) {
this._privilegedAboutContentProcess = Services.prefs.getBoolPref(
PREF_SEPARATE_PRIVILEGEDABOUT_CONTENT_PROCESS
);
this.notifyChange();
} else if (!IS_RELEASE_OR_BETA && data === PREF_ACTIVITY_STREAM_DEBUG) {
this._activityStreamDebug = Services.prefs.getBoolPref(
PREF_ACTIVITY_STREAM_DEBUG,
false
);
this.notifyChange();
}
break;
case TOPIC_CONTENT_DOCUMENT_INTERACTIVE: {
const win = subject.defaultView;
// It seems like "content-document-interactive" is triggered multiple
// times for a single window. The first event always seems to be an
// HTMLDocument object that contains a non-null window reference
// whereas the remaining ones seem to be proxied objects.
// https://searchfox.org/mozilla-central/rev/d2966246905102b36ef5221b0e3cbccf7ea15a86/devtools/server/actors/object.js#100-102
if (win === null) {
break;
}
// We use win.location.pathname instead of win.location.toString()
// because we want to account for URLs that contain the location hash
// property or query strings (e.g. about:newtab#foo, about:home?bar).
// Asserting here would be ideal, but this code path is also taken
// by the view-source:// scheme, so we should probably just bail out
// and do nothing.
if (!ACTIVITY_STREAM_PAGES.has(win.location.pathname)) {
break;
}
const onLoaded = () => {
const debugString = this._activityStreamDebug ? "-dev" : "";
// This list must match any similar ones in render-activity-stream-html.js.
const scripts = [
"chrome://browser/content/contentSearchUI.js",
"chrome://browser/content/contentTheme.js",
`${BASE_URL}vendor/react${debugString}.js`,
`${BASE_URL}vendor/react-dom${debugString}.js`,
`${BASE_URL}vendor/prop-types.js`,
`${BASE_URL}vendor/react-transition-group.js`,
`${BASE_URL}vendor/redux.js`,
`${BASE_URL}vendor/react-redux.js`,
`${BASE_URL}data/content/activity-stream.bundle.js`,
];
for (let script of scripts) {
Services.scriptloader.loadSubScript(script, win); // Synchronous call
}
};
subject.addEventListener("DOMContentLoaded", onLoaded, { once: true });
// There is a possibility that DOMContentLoaded won't be fired. This
// unload event (which cannot be cancelled) will attempt to remove
// the listener for the DOMContentLoaded event.
const onUnloaded = () => {
subject.removeEventListener("DOMContentLoaded", onLoaded);
};
subject.addEventListener("unload", onUnloaded, { once: true });
break;
}
case TOPIC_APP_QUIT:
this.uninit();
if (IS_MAIN_PROCESS) {
AboutNewTab.uninit();
} else if (IS_PRIVILEGED_PROCESS) {
Services.obs.removeObserver(this, TOPIC_CONTENT_DOCUMENT_INTERACTIVE);
}
break;
}
},
notifyChange() {
Services.obs.notifyObservers(null, "newtab-url-changed", this._newTabURL);
},
/**
* React to changes to the activity stream being enabled or not.
*
* This will only act if there is a change of state and if not overridden.
*
* @returns {Boolean} Returns if there has been a state change
*
* @param {Boolean} stateEnabled activity stream enabled state to set to
* @param {Boolean} forceState force state change
*/
toggleActivityStream(stateEnabled, forceState = false) {
if (
!forceState &&
(this.overridden || stateEnabled === this.activityStreamEnabled)
) {
// exit there is no change of state
return false;
}
if (stateEnabled) {
this._activityStreamEnabled = true;
} else {
this._activityStreamEnabled = false;
}
this._privilegedAboutContentProcess = Services.prefs.getBoolPref(
PREF_SEPARATE_PRIVILEGEDABOUT_CONTENT_PROCESS
);
if (!IS_RELEASE_OR_BETA) {
this._activityStreamDebug = Services.prefs.getBoolPref(
PREF_ACTIVITY_STREAM_DEBUG,
false
);
}
this._newtabURL = ABOUT_URL;
return true;
},
/*
* Returns the default URL.
*
* This URL depends on various activity stream prefs. Overriding
* the newtab page has no effect on the result of this function.
*/
get defaultURL() {
// Generate the desired activity stream resource depending on state, e.g.,
// "resource://activity-stream/prerendered/activity-stream.html"
// "resource://activity-stream/prerendered/activity-stream-debug.html"
// "resource://activity-stream/prerendered/activity-stream-noscripts.html"
return [
"resource://activity-stream/prerendered/",
"activity-stream",
// Debug version loads dev scripts but noscripts separately loads scripts
this._activityStreamDebug && !this._privilegedAboutContentProcess
? "-debug"
: "",
this._privilegedAboutContentProcess ? "-noscripts" : "",
".html",
].join("");
},
/*
* Returns the about:welcome URL
*
* This is calculated in the same way the default URL is.
*/
get welcomeURL() {
return this.defaultURL;
},
get newTabURL() {
return this._newTabURL;
},
set newTabURL(aNewTabURL) {
let newTabURL = aNewTabURL.trim();
if (newTabURL === ABOUT_URL) {
// avoid infinite redirects in case one sets the URL to about:newtab
this.resetNewTabURL();
return;
} else if (newTabURL === "") {
newTabURL = "about:blank";
}
this.toggleActivityStream(false);
this._newTabURL = newTabURL;
this._overridden = true;
this.notifyChange();
},
get overridden() {
return this._overridden;
},
get activityStreamEnabled() {
return this._activityStreamEnabled;
},
get activityStreamDebug() {
return this._activityStreamDebug;
},
resetNewTabURL() {
this._overridden = false;
this._newTabURL = ABOUT_URL;
this.toggleActivityStream(true, true);
this.notifyChange();
},
maybeRecordTopsitesPainted(timestamp) {
if (this.alreadyRecordedTopsitesPainted) {
return;
}
const SCALAR_KEY = "timestamps.about_home_topsites_first_paint";
let startupInfo = Services.startup.getStartupInfo();
let processStartTs = startupInfo.process.getTime();
let delta = Math.round(timestamp - processStartTs);
Services.telemetry.scalarSet(SCALAR_KEY, delta);
this.alreadyRecordedTopsitesPainted = true;
},
uninit() {
if (!this.initialized) {
return;
}
Services.obs.removeObserver(this, TOPIC_APP_QUIT);
Services.prefs.removeObserver(
PREF_SEPARATE_PRIVILEGEDABOUT_CONTENT_PROCESS,
this
);
if (!IS_RELEASE_OR_BETA) {
Services.prefs.removeObserver(PREF_ACTIVITY_STREAM_DEBUG, this);
}
this.initialized = false;
},
};
const EXPORTED_SYMBOLS = ["AboutNewTabService"];
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Community Participation Guidelines
This repository is governed by Mozilla's code of conduct and etiquette guidelines.
For more details, please read the
[Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/).
## How to Report
For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page.
<!--
## Project Specific Etiquette
In some cases, there will be additional project etiquette i.e.: (https://bugzilla.mozilla.org/page.cgi?id=etiquette.html).
Please update for your project.
-->
================================================
FILE: LICENSE
================================================
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
================================================
FILE: README.md
================================================
# Firefox Home (New Tab) [Deprecated Version]
This repository is no longer updated or used. We're keeping it around for
those few occasions when it's useful for doing code & bugfix archaeology by
looking at issues and PRs.
Please do not file new issues or PRs; they will not be triaged. Issues are now
tracked on Bugzilla, in `Firefox: New Tab Page` and `Firefox: Messaging
System`.
More current links:
* Docs for [Firefox Home (New Tab)](https://firefox-source-docs.mozilla.org/browser/components/newtab/docs/index.html)
* Docs for [Messaging System](https://firefox-source-docs.mozilla.org/browser/components/newtab/content-src/asrouter/docs/index.html)
* [Code](https://searchfox.org/mozilla-central/source/browser/components/newtab)
--------------
The files in this directory, including vendor dependencies, are exported to the
browser/components/newtab/ directory in mozilla central.
Read [docs/v2-system-addon](https://github.com/mozilla/activity-stream/tree/master/docs/v2-system-addon/1.GETTING_STARTED.md) for more detail on how to develop on and use this repository.
## Where should I file bugs?
We regularly check the ActivityStream:NewTab component on Bugzilla.
## For Developers
If you are interested in contributing, take a look at [this guide](contributing.md) on where to find us and how to contribute,
and [this guide](docs/v2-system-addon/1.GETTING_STARTED.md) for getting your development environment set up.
## For Localizers
Firefox Home localization is managed via [Pontoon](https://pontoon.mozilla.org/projects/activity-stream-new-tab/), not direct pull requests to the repository. If you want to fix a typo, add a new language, or simply know more about localization, please get in touch with the [existing localization team](https://pontoon.mozilla.org/teams/) for your language, or Mozilla’s [l10n-drivers](https://wiki.mozilla.org/L10n:Mozilla_Team#Mozilla_Corporation) for guidance.
================================================
FILE: aboutlibrary/content/aboutlibrary.xhtml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!--
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Security-Policy" content="default-src data: chrome: resource:" />
<title>Library</title>
<link rel="stylesheet" href="chrome://browser/content/aboutlibrary.css" type="text/css" media="all"/>
<link rel="icon" type="image/png" href="chrome://branding/content/icon32.png"/>
</head>
<body>
<script src="resource://activity-stream/vendor/react.js"> </script>
<script src="resource://activity-stream/vendor/react-dom.js"> </script>
<script src="resource://activity-stream/vendor/prop-types.js"> </script>
<script src="resource://activity-stream/vendor/react-intl.js"> </script>
<script src="resource://activity-stream/vendor/redux.js"> </script>
<script src="resource://activity-stream/vendor/react-redux.js"> </script>
<script src="chrome://browser/content/aboutlibrary.bundle.js"></script>
</body>
</html>
================================================
FILE: aboutlibrary/jar.mn
================================================
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
browser.jar:
content/browser/ (content/*)
================================================
FILE: aboutlibrary/moz.build
================================================
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
JAR_MANIFESTS += ['jar.mn']
FINAL_LIBRARY = 'browsercomps'
with Files('**'):
BUG_COMPONENT = ('Firefox', 'Library')
================================================
FILE: bin/bootstrap
================================================
#!/bin/sh -x
# bootstrap an activity-stream repo
ln -s ../../hooks/pre-commit .git/hooks/pre-commit
ln -s ../../hooks/post-commit .git/hooks/post-commit
================================================
FILE: bin/download-firefox-artifact
================================================
#!/usr/bin/env bash -x
# Forked from https://github.com/devtools-html/debugger.html/blob/master/bin/download-firefox-artifact
#
# This looks for a mozilla-central artifact build as a sibling of the
# activity-stream tree. If it's not there, it creates it. If it is there, it
# updates it.
# If AS_GIT_BIN_REPO (the git repo from which prepare-mochitests-dev and
# friends will be executed) isn't set in the environment, just use the repo
# we're running from.
if [ -z ${AS_GIT_BIN_REPO+x} ]; then
ROOT=`dirname $0`
AS_GIT_BIN_REPO="../../../../activity-stream"
else
ROOT=${AS_GIT_BIN_REPO}/bin
fi
# Compute the mozilla-central path based on whether AS_PINE_TEST_DIR is set
# (i.e. whether this script has been called from test-merges.js)
if [ -z ${AS_PINE_TEST_DIR+x} ]; then
FIREFOX_PATH="$ROOT/../../mozilla-central"
else
FIREFOX_PATH=${AS_PINE_TEST_DIR}/mozilla-central
fi
# check that mercurial is installed
if [ -z "`command -v hg`" ]; then
echo >&2 "mercurial is required for mochitests, use 'brew install mercurial' on MacOS";
exit 1;
fi
if [ -d "$FIREFOX_PATH" ]; then
# convert path to absolute path
FIREFOX_PATH=$(cd "$FIREFOX_PATH"; pwd)
# If we already have Firefox locally, just update it
cd "$FIREFOX_PATH";
if [ -n "`hg status`" ]; then
read -p "There are local changes to Firefox which will be overwritten. Are you sure? [Y/n] " -r
if [[ $REPLY == "n" ]]; then
exit 0;
fi
hg revert -a
fi
hg pull
hg update -C
else
echo "Downloading Firefox source code, requires about 10-30min depending on connection"
hg clone https://hg.mozilla.org/mozilla-central/ "$FIREFOX_PATH"
# if somebody cancels (ctrl-c) out of the long download don't continue
exit_code=$?
if [ $exit_code -ne 0 ]; then
exit $exit_code
fi
cd "$FIREFOX_PATH"
# Make an artifact build so it builds much faster
echo "
ac_add_options --enable-artifact-builds
mk_add_options AUTOCLOBBER=1
mk_add_options MOZ_OBJDIR=./objdir-frontend
" > .mozconfig
fi
================================================
FILE: bin/prepare-mochitests-dev
================================================
#!/usr/bin/env bash -x -e
#
# -e means "exit on error", so that we don't have to constantly
# check exit codes
#
# Forked from https://github.com/devtools-html/debugger.html/blob/master/bin/prepare-mochitests-dev
#
# This sets up a mozilla-central build for local mochitest development with an
# exported activity-stream tree and test directory.
# If AS_GIT_BIN_REPO (the git repo from which prepare-mochitests-dev and
# friends will be executed) isn't set in the environment, just use the repo
# we're running from.
if [ -z ${AS_GIT_BIN_REPO+x} ]; then
ROOT=`dirname $0`
AS_GIT_BIN_REPO="../activity-stream" # as seen from mozilla-central
else
ROOT=${AS_GIT_BIN_REPO}/bin
fi
# Compute the mozilla-central path based on whether AS_PINE_TEST_DIR is set
# (i.e. whether this script has been called from test-merges.js)
if [ -z ${AS_PINE_TEST_DIR+x} ]; then
FIREFOX_PATH="$ROOT/../../mozilla-central"
else
FIREFOX_PATH=${AS_PINE_TEST_DIR}/mozilla-central
fi
MC_MODULE_PATH="$FIREFOX_PATH/browser/components/newtab"
# By default, just use mozilla-central + the export. If ENABLE_MC_AS is set to
# 1, patch on top of mozilla-central + the export to turn on the AS pref and
# turn on the tests. Once AS is on by default in mozilla-central, stuff
# related to ENABLE_MC_AS can go away entirely.
ENABLE_MC_AS=${ENABLE_MC_AS-0}
# This will either download or update the local Firefox repo
"$ROOT/download-firefox-artifact"
# blow away any old bits in order to workaround bug 1335976 for users
# who are using the default objdir-frontend
rm -f ${FIREFOX_PATH}/objdir-frontend/dist/bin/browser/features/@activity-streams/*
# Clean, package, and copy the activity stream files.
npm run buildmc
# Patch mozilla-central (on top of the export) so that AS is preffed on, and
# the mochitests are turned on.
shopt -s nullglob # don't explode if there are no patches right now
if [ $ENABLE_MC_AS ]; then
PATCHES=$AS_GIT_BIN_REPO/mozilla-central-patches/*.diff
for p in $PATCHES
do
patch --directory="$FIREFOX_PATH" -p1 --force --no-backup-if-mismatch \
--input=$p
done
fi
shopt -u nullglob
# Be sure that we've built, and that the test glop in the objdir has been
# created.
#
cd "$FIREFOX_PATH"
./mach build
exit $?
================================================
FILE: bin/render-activity-stream-html.js
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-disable no-console */
const fs = require("fs");
const { mkdir } = require("shelljs");
const path = require("path");
// Note: DEFAULT_OPTIONS.baseUrl should match BASE_URL in aboutNewTabService.js
// in mozilla-central.
const DEFAULT_OPTIONS = {
addonPath: "..",
baseUrl: "resource://activity-stream/",
};
/**
* templateHTML - Generates HTML for activity stream, given some options and
* prerendered HTML if necessary.
*
* @param {obj} options
* {str} options.baseUrl The base URL for all local assets
* {bool} options.debug Should we use dev versions of JS libraries?
* {bool} options.noscripts Should we include scripts in the prerendered files?
* @return {str} An HTML document as a string
*/
function templateHTML(options) {
const debugString = options.debug ? "-dev" : "";
const scripts = [
"chrome://browser/content/contentSearchUI.js",
"chrome://browser/content/contentTheme.js",
`${options.baseUrl}vendor/react${debugString}.js`,
`${options.baseUrl}vendor/react-dom${debugString}.js`,
`${options.baseUrl}vendor/prop-types.js`,
`${options.baseUrl}vendor/redux.js`,
`${options.baseUrl}vendor/react-redux.js`,
`${options.baseUrl}vendor/react-transition-group.js`,
`${options.baseUrl}data/content/activity-stream.bundle.js`,
];
// Add spacing and script tags
const scriptRender = `\n${scripts
.map(script => ` <script src="${script}"></script>`)
.join("\n")}`;
return `
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';">
<title data-l10n-id="newtab-page-title"></title>
<link rel="icon" type="image/png" href="chrome://branding/content/icon32.png"/>
<link rel="localization" href="branding/brand.ftl" />
<link rel="localization" href="browser/branding/brandings.ftl" />
<link rel="localization" href="browser/newtab/newtab.ftl" />
<link rel="stylesheet" href="chrome://browser/content/contentSearchUI.css" />
<link rel="stylesheet" href="${options.baseUrl}css/activity-stream.css" />
</head>
<body class="activity-stream">
<div id="header-asrouter-container" role="presentation"></div>
<div id="root"></div>
<div id="footer-asrouter-container" role="presentation"></div>${
options.noscripts ? "" : scriptRender
}
</body>
</html>
`.trimLeft();
}
/**
* writeFiles - Writes to the desired files the result of a template given
* various prerendered data and options.
*
* @param {string} destPath Path to write the files to
* @param {Map} filesMap Mapping of a string file name to templater
* @param {Object} options Various options for the templater
*/
function writeFiles(destPath, filesMap, options) {
for (const [file, templater] of filesMap) {
console.log("\x1b[32m", `✓ ${file}`, "\x1b[0m");
fs.writeFileSync(path.join(destPath, file), templater({ options }));
}
}
const STATIC_FILES = new Map([
["activity-stream.html", ({ options }) => templateHTML(options)],
[
"activity-stream-debug.html",
({ options }) => templateHTML(Object.assign({}, options, { debug: true })),
],
[
"activity-stream-noscripts.html",
({ options }) =>
templateHTML(Object.assign({}, options, { noscripts: true })),
],
]);
/**
* main - Parses command line arguments, generates html and js with templates,
* and writes files to their specified locations.
*/
function main() {
// eslint-disable-line max-statements
// This code parses command line arguments passed to this script.
// Note: process.argv.slice(2) is necessary because the first two items in
// process.argv are paths
const args = require("minimist")(process.argv.slice(2), {
alias: {
addonPath: "a",
baseUrl: "b",
},
});
const options = Object.assign({ debug: false }, DEFAULT_OPTIONS, args || {});
const addonPath = path.resolve(__dirname, options.addonPath);
const prerenderedPath = path.join(addonPath, "prerendered");
console.log(`Writing prerendered files to ${prerenderedPath}:`);
mkdir("-p", prerenderedPath);
writeFiles(prerenderedPath, STATIC_FILES, options);
}
main();
================================================
FILE: bin/try-runner.js
================================================
/* eslint-disable no-console */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
/*
* A small test runner/reporter for node-based tests,
* which are run via taskcluster node(debugger).
*
* Forked from
* https://searchfox.org/mozilla-central/source/devtools/client/debugger/bin/try-runner.js
*/
const { execFileSync } = require("child_process");
const { readFileSync } = require("fs");
const path = require("path");
function logErrors(tool, errors) {
for (const error of errors) {
console.log(`TEST-UNEXPECTED-FAIL ${tool} | ${error}`);
}
return errors;
}
function execOut(...args) {
let out;
let err;
try {
out = execFileSync(...args, {
silent: false,
});
} catch (e) {
// For debugging on (eg) try server...
//
// if (e) {
// logErrors("execOut", ["execFileSync returned exception: ", e]);
// }
out = e && e.stdout;
err = e && e.stderr;
}
return { out: out && out.toString(), err: err && err.toString() };
}
function logStart(name) {
console.log(`TEST START | ${name}`);
}
function karma() {
logStart("karma");
const { out } = execOut("npm", [
"run",
"testmc:unit",
// , "--", "--log-level", "--verbose",
// to debug the karma integration, uncomment the above line
]);
// karma spits everything to stdout, not stderr, so if nothing came back on
// stdout, give up now.
if (!out) {
return false;
}
let jsonContent;
try {
// Note that this will be overwritten at each run, but that shouldn't
// matter.
jsonContent = readFileSync(path.join("logs", "karma-run-results.json"));
} catch (ex) {
console.error("exception reading karma-run-results.json: ", ex);
return false;
}
const results = JSON.parse(jsonContent);
const failed = results.summary.failed === 0;
let errors = [];
// eslint-disable-next-line guard-for-in
for (let testArray in results.result) {
let failedTests = Array.from(results.result[testArray]).filter(
test => !test.success && !test.skipped
);
let errs = failedTests.map(test => {
return `${test.suite.join(":")} ${test.description}: ${test.log[0]}`;
});
errors = errors.concat(errs);
}
logErrors("karma", errors);
return failed;
}
function sasslint() {
logStart("sasslint");
const { out } = execOut("npm", [
"run",
"--silent",
"lint:sasslint",
"--",
"--format",
"json",
]);
if (!out.length) {
return true;
}
let fileObjects = JSON.parse(out);
let filesWithIssues = fileObjects.filter(
file => file.warningCount || file.errorCount
);
let errs = [];
let errorString;
filesWithIssues.forEach(file => {
file.messages.forEach(messageObj => {
errorString = `${file.filePath}(${messageObj.line}, ${
messageObj.column
}): ${messageObj.message} (${messageObj.ruleId})`;
errs.push(errorString);
});
});
const errors = logErrors("sasslint", errs);
return errors.length === 0;
}
const karmaPassed = karma();
const sasslintPassed = sasslint();
const success = karmaPassed && sasslintPassed;
console.log({
karmaPassed,
sasslintPassed,
});
process.exitCode = success ? 0 : 1;
console.log("CODE", process.exitCode);
================================================
FILE: bin/vendor.js
================================================
#!/usr/bin/env node
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-disable no-console */
const { cp, set } = require("shelljs");
const path = require("path");
const filesToVendor = {
// XXX currently these two licenses are identical. Perhaps we should check
// in case that changes at some point in the future.
"react/LICENSE": "REACT_AND_REACT_DOM_LICENSE",
"react/umd/react.production.min.js": "react.js",
"react/umd/react.development.js": "react-dev.js",
"react-dom/umd/react-dom.production.min.js": "react-dom.js",
"react-dom/umd/react-dom.development.js": "react-dom-dev.js",
"react-redux/LICENSE.md": "REACT_REDUX_LICENSE",
"react-redux/dist/react-redux.min.js": "react-redux.js",
"react-transition-group/dist/react-transition-group.min.js":
"react-transition-group.js",
"react-transition-group/LICENSE": "REACT_TRANSITION_GROUP_LICENSE",
};
set("-v"); // Echo all the copy commands so the user can see what's going on
for (let srcPath of Object.keys(filesToVendor)) {
cp(
path.join("node_modules", srcPath),
path.join("vendor", filesToVendor[srcPath])
);
}
console.log(`
Check to see if any license files have changed, and, if so, be sure to update
https://searchfox.org/mozilla-central/source/toolkit/content/license.html`);
================================================
FILE: common/Actions.jsm
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.MAIN_MESSAGE_TYPE = "ActivityStream:Main";
this.CONTENT_MESSAGE_TYPE = "ActivityStream:Content";
this.PRELOAD_MESSAGE_TYPE = "ActivityStream:PreloadedBrowser";
this.UI_CODE = 1;
this.BACKGROUND_PROCESS = 2;
/**
* globalImportContext - Are we in UI code (i.e. react, a dom) or some kind of background process?
* Use this in action creators if you need different logic
* for ui/background processes.
*/
const globalImportContext =
typeof Window === "undefined" ? BACKGROUND_PROCESS : UI_CODE;
// Export for tests
this.globalImportContext = globalImportContext;
// Create an object that avoids accidental differing key/value pairs:
// {
// INIT: "INIT",
// UNINIT: "UNINIT"
// }
const actionTypes = {};
for (const type of [
"ADDONS_INFO_REQUEST",
"ADDONS_INFO_RESPONSE",
"ARCHIVE_FROM_POCKET",
"AS_ROUTER_INITIALIZED",
"AS_ROUTER_PREF_CHANGED",
"AS_ROUTER_TARGETING_UPDATE",
"AS_ROUTER_TELEMETRY_USER_EVENT",
"BLOCK_URL",
"BOOKMARK_URL",
"CLEAR_PREF",
"COPY_DOWNLOAD_LINK",
"DELETE_BOOKMARK_BY_ID",
"DELETE_FROM_POCKET",
"DELETE_HISTORY_URL",
"DIALOG_CANCEL",
"DIALOG_OPEN",
"DISCOVERY_STREAM_CONFIG_CHANGE",
"DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS",
"DISCOVERY_STREAM_CONFIG_SETUP",
"DISCOVERY_STREAM_CONFIG_SET_VALUE",
"DISCOVERY_STREAM_FEEDS_UPDATE",
"DISCOVERY_STREAM_FEED_UPDATE",
"DISCOVERY_STREAM_IMPRESSION_STATS",
"DISCOVERY_STREAM_LAYOUT_RESET",
"DISCOVERY_STREAM_LAYOUT_UPDATE",
"DISCOVERY_STREAM_LINK_BLOCKED",
"DISCOVERY_STREAM_LOADED_CONTENT",
"DISCOVERY_STREAM_RETRY_FEED",
"DISCOVERY_STREAM_SPOCS_CAPS",
"DISCOVERY_STREAM_SPOCS_ENDPOINT",
"DISCOVERY_STREAM_SPOCS_FILL",
"DISCOVERY_STREAM_SPOCS_PLACEMENTS",
"DISCOVERY_STREAM_SPOCS_UPDATE",
"DISCOVERY_STREAM_SPOC_BLOCKED",
"DISCOVERY_STREAM_SPOC_IMPRESSION",
"DOWNLOAD_CHANGED",
"FAKE_FOCUS_SEARCH",
"FILL_SEARCH_TERM",
"HANDOFF_SEARCH_TO_AWESOMEBAR",
"HIDE_PRIVACY_INFO",
"HIDE_SEARCH",
"INIT",
"NEW_TAB_INIT",
"NEW_TAB_INITIAL_STATE",
"NEW_TAB_LOAD",
"NEW_TAB_REHYDRATED",
"NEW_TAB_STATE_REQUEST",
"NEW_TAB_UNLOAD",
"OPEN_DOWNLOAD_FILE",
"OPEN_LINK",
"OPEN_NEW_WINDOW",
"OPEN_PRIVATE_WINDOW",
"OPEN_WEBEXT_SETTINGS",
"PLACES_BOOKMARK_ADDED",
"PLACES_BOOKMARK_REMOVED",
"PLACES_HISTORY_CLEARED",
"PLACES_LINKS_CHANGED",
"PLACES_LINK_BLOCKED",
"PLACES_LINK_DELETED",
"PLACES_SAVED_TO_POCKET",
"POCKET_CTA",
"POCKET_LINK_DELETED_OR_ARCHIVED",
"POCKET_LOGGED_IN",
"POCKET_WAITING_FOR_SPOC",
"PREFS_INITIAL_VALUES",
"PREF_CHANGED",
"PREVIEW_REQUEST",
"PREVIEW_REQUEST_CANCEL",
"PREVIEW_RESPONSE",
"REMOVE_DOWNLOAD_FILE",
"RICH_ICON_MISSING",
"SAVE_SESSION_PERF_DATA",
"SAVE_TO_POCKET",
"SCREENSHOT_UPDATED",
"SECTION_DEREGISTER",
"SECTION_DISABLE",
"SECTION_ENABLE",
"SECTION_MOVE",
"SECTION_OPTIONS_CHANGED",
"SECTION_REGISTER",
"SECTION_UPDATE",
"SECTION_UPDATE_CARD",
"SETTINGS_CLOSE",
"SETTINGS_OPEN",
"SET_PREF",
"SHOW_DOWNLOAD_FILE",
"SHOW_FIREFOX_ACCOUNTS",
"SHOW_PRIVACY_INFO",
"SHOW_SEARCH",
"SKIPPED_SIGNIN",
"SNIPPETS_BLOCKLIST_CLEARED",
"SNIPPETS_BLOCKLIST_UPDATED",
"SNIPPETS_DATA",
"SNIPPETS_PREVIEW_MODE",
"SNIPPETS_RESET",
"SNIPPET_BLOCKED",
"SUBMIT_EMAIL",
"SUBMIT_SIGNIN",
"SYSTEM_TICK",
"TELEMETRY_IMPRESSION_STATS",
"TELEMETRY_PERFORMANCE_EVENT",
"TELEMETRY_UNDESIRED_EVENT",
"TELEMETRY_USER_EVENT",
"TOP_SITES_CANCEL_EDIT",
"TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL",
"TOP_SITES_EDIT",
"TOP_SITES_INSERT",
"TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL",
"TOP_SITES_PIN",
"TOP_SITES_PREFS_UPDATED",
"TOP_SITES_UNPIN",
"TOP_SITES_UPDATED",
"TOTAL_BOOKMARKS_REQUEST",
"TOTAL_BOOKMARKS_RESPONSE",
"TRAILHEAD_ENROLL_EVENT",
"UNINIT",
"UPDATE_PINNED_SEARCH_SHORTCUTS",
"UPDATE_SEARCH_SHORTCUTS",
"UPDATE_SECTION_PREFS",
"WEBEXT_CLICK",
"WEBEXT_DISMISS",
]) {
actionTypes[type] = type;
}
// These are acceptable actions for AS Router messages to have. They can show up
// as call-to-action buttons in snippets, onboarding tour, etc.
const ASRouterActions = {};
for (const type of [
"HIGHLIGHT_FEATURE",
"INSTALL_ADDON_FROM_URL",
"OPEN_APPLICATIONS_MENU",
"OPEN_PRIVATE_BROWSER_WINDOW",
"OPEN_URL",
"OPEN_ABOUT_PAGE",
"OPEN_PREFERENCES_PAGE",
"SHOW_FIREFOX_ACCOUNTS",
"PIN_CURRENT_TAB",
"ENABLE_FIREFOX_MONITOR",
"OPEN_PROTECTION_PANEL",
"OPEN_PROTECTION_REPORT",
"DISABLE_STP_DOORHANGERS",
"SHOW_MIGRATION_WIZARD",
]) {
ASRouterActions[type] = type;
}
// Helper function for creating routed actions between content and main
// Not intended to be used by consumers
function _RouteMessage(action, options) {
const meta = action.meta ? { ...action.meta } : {};
if (!options || !options.from || !options.to) {
throw new Error(
"Routed Messages must have options as the second parameter, and must at least include a .from and .to property."
);
}
// For each of these fields, if they are passed as an option,
// add them to the action. If they are not defined, remove them.
["from", "to", "toTarget", "fromTarget", "skipMain", "skipLocal"].forEach(
o => {
if (typeof options[o] !== "undefined") {
meta[o] = options[o];
} else if (meta[o]) {
delete meta[o];
}
}
);
return { ...action, meta };
}
/**
* AlsoToMain - Creates a message that will be dispatched locally and also sent to the Main process.
*
* @param {object} action Any redux action (required)
* @param {object} options
* @param {bool} skipLocal Used by OnlyToMain to skip the main reducer
* @param {string} fromTarget The id of the content port from which the action originated. (optional)
* @return {object} An action with added .meta properties
*/
function AlsoToMain(action, fromTarget, skipLocal) {
return _RouteMessage(action, {
from: CONTENT_MESSAGE_TYPE,
to: MAIN_MESSAGE_TYPE,
fromTarget,
skipLocal,
});
}
/**
* OnlyToMain - Creates a message that will be sent to the Main process and skip the local reducer.
*
* @param {object} action Any redux action (required)
* @param {object} options
* @param {string} fromTarget The id of the content port from which the action originated. (optional)
* @return {object} An action with added .meta properties
*/
function OnlyToMain(action, fromTarget) {
return AlsoToMain(action, fromTarget, true);
}
/**
* BroadcastToContent - Creates a message that will be dispatched to main and sent to ALL content processes.
*
* @param {object} action Any redux action (required)
* @return {object} An action with added .meta properties
*/
function BroadcastToContent(action) {
return _RouteMessage(action, {
from: MAIN_MESSAGE_TYPE,
to: CONTENT_MESSAGE_TYPE,
});
}
/**
* AlsoToOneContent - Creates a message that will be will be dispatched to the main store
* and also sent to a particular Content process.
*
* @param {object} action Any redux action (required)
* @param {string} target The id of a content port
* @param {bool} skipMain Used by OnlyToOneContent to skip the main process
* @return {object} An action with added .meta properties
*/
function AlsoToOneContent(action, target, skipMain) {
if (!target) {
throw new Error(
"You must provide a target ID as the second parameter of AlsoToOneContent. If you want to send to all content processes, use BroadcastToContent"
);
}
return _RouteMessage(action, {
from: MAIN_MESSAGE_TYPE,
to: CONTENT_MESSAGE_TYPE,
toTarget: target,
skipMain,
});
}
/**
* OnlyToOneContent - Creates a message that will be sent to a particular Content process
* and skip the main reducer.
*
* @param {object} action Any redux action (required)
* @param {string} target The id of a content port
* @return {object} An action with added .meta properties
*/
function OnlyToOneContent(action, target) {
return AlsoToOneContent(action, target, true);
}
/**
* AlsoToPreloaded - Creates a message that dispatched to the main reducer and also sent to the preloaded tab.
*
* @param {object} action Any redux action (required)
* @return {object} An action with added .meta properties
*/
function AlsoToPreloaded(action) {
return _RouteMessage(action, {
from: MAIN_MESSAGE_TYPE,
to: PRELOAD_MESSAGE_TYPE,
});
}
/**
* UserEvent - A telemetry ping indicating a user action. This should only
* be sent from the UI during a user session.
*
* @param {object} data Fields to include in the ping (source, etc.)
* @return {object} An AlsoToMain action
*/
function UserEvent(data) {
return AlsoToMain({
type: actionTypes.TELEMETRY_USER_EVENT,
data,
});
}
/**
* ASRouterUserEvent - A telemetry ping indicating a user action from AS router. This should only
* be sent from the UI during a user session.
*
* @param {object} data Fields to include in the ping (source, etc.)
* @return {object} An AlsoToMain action
*/
function ASRouterUserEvent(data) {
return AlsoToMain({
type: actionTypes.AS_ROUTER_TELEMETRY_USER_EVENT,
data,
});
}
/**
* DiscoveryStreamSpocsFill - A telemetry ping indicating a SPOCS Fill event.
*
* @param {object} data Fields to include in the ping (spoc_fills, etc.)
* @param {int} importContext (For testing) Override the import context for testing.
* @return {object} An AlsoToMain action
*/
function DiscoveryStreamSpocsFill(data, importContext = globalImportContext) {
const action = {
type: actionTypes.DISCOVERY_STREAM_SPOCS_FILL,
data,
};
return importContext === UI_CODE ? AlsoToMain(action) : action;
}
/**
* UndesiredEvent - A telemetry ping indicating an undesired state.
*
* @param {object} data Fields to include in the ping (value, etc.)
* @param {int} importContext (For testing) Override the import context for testing.
* @return {object} An action. For UI code, a AlsoToMain action.
*/
function UndesiredEvent(data, importContext = globalImportContext) {
const action = {
type: actionTypes.TELEMETRY_UNDESIRED_EVENT,
data,
};
return importContext === UI_CODE ? AlsoToMain(action) : action;
}
/**
* PerfEvent - A telemetry ping indicating a performance-related event.
*
* @param {object} data Fields to include in the ping (value, etc.)
* @param {int} importContext (For testing) Override the import context for testing.
* @return {object} An action. For UI code, a AlsoToMain action.
*/
function PerfEvent(data, importContext = globalImportContext) {
const action = {
type: actionTypes.TELEMETRY_PERFORMANCE_EVENT,
data,
};
return importContext === UI_CODE ? AlsoToMain(action) : action;
}
/**
* ImpressionStats - A telemetry ping indicating an impression stats.
*
* @param {object} data Fields to include in the ping
* @param {int} importContext (For testing) Override the import context for testing.
* #return {object} An action. For UI code, a AlsoToMain action.
*/
function ImpressionStats(data, importContext = globalImportContext) {
const action = {
type: actionTypes.TELEMETRY_IMPRESSION_STATS,
data,
};
return importContext === UI_CODE ? AlsoToMain(action) : action;
}
/**
* DiscoveryStreamImpressionStats - A telemetry ping indicating an impression stats in Discovery Stream.
*
* @param {object} data Fields to include in the ping
* @param {int} importContext (For testing) Override the import context for testing.
* #return {object} An action. For UI code, a AlsoToMain action.
*/
function DiscoveryStreamImpressionStats(
data,
importContext = globalImportContext
) {
const action = {
type: actionTypes.DISCOVERY_STREAM_IMPRESSION_STATS,
data,
};
return importContext === UI_CODE ? AlsoToMain(action) : action;
}
/**
* DiscoveryStreamLoadedContent - A telemetry ping indicating a content gets loaded in Discovery Stream.
*
* @param {object} data Fields to include in the ping
* @param {int} importContext (For testing) Override the import context for testing.
* #return {object} An action. For UI code, a AlsoToMain action.
*/
function DiscoveryStreamLoadedContent(
data,
importContext = globalImportContext
) {
const action = {
type: actionTypes.DISCOVERY_STREAM_LOADED_CONTENT,
data,
};
return importContext === UI_CODE ? AlsoToMain(action) : action;
}
function SetPref(name, value, importContext = globalImportContext) {
const action = { type: actionTypes.SET_PREF, data: { name, value } };
return importContext === UI_CODE ? AlsoToMain(action) : action;
}
function WebExtEvent(type, data, importContext = globalImportContext) {
if (!data || !data.source) {
throw new Error(
'WebExtEvent actions should include a property "source", the id of the webextension that should receive the event.'
);
}
const action = { type, data };
return importContext === UI_CODE ? AlsoToMain(action) : action;
}
this.actionTypes = actionTypes;
this.ASRouterActions = ASRouterActions;
this.actionCreators = {
BroadcastToContent,
UserEvent,
ASRouterUserEvent,
UndesiredEvent,
PerfEvent,
ImpressionStats,
AlsoToOneContent,
OnlyToOneContent,
AlsoToMain,
OnlyToMain,
AlsoToPreloaded,
SetPref,
WebExtEvent,
DiscoveryStreamImpressionStats,
DiscoveryStreamLoadedContent,
DiscoveryStreamSpocsFill,
};
// These are helpers to test for certain kinds of actions
this.actionUtils = {
isSendToMain(action) {
if (!action.meta) {
return false;
}
return (
action.meta.to === MAIN_MESSAGE_TYPE &&
action.meta.from === CONTENT_MESSAGE_TYPE
);
},
isBroadcastToContent(action) {
if (!action.meta) {
return false;
}
if (action.meta.to === CONTENT_MESSAGE_TYPE && !action.meta.toTarget) {
return true;
}
return false;
},
isSendToOneContent(action) {
if (!action.meta) {
return false;
}
if (action.meta.to === CONTENT_MESSAGE_TYPE && action.meta.toTarget) {
return true;
}
return false;
},
isSendToPreloaded(action) {
if (!action.meta) {
return false;
}
return (
action.meta.to === PRELOAD_MESSAGE_TYPE &&
action.meta.from === MAIN_MESSAGE_TYPE
);
},
isFromMain(action) {
if (!action.meta) {
return false;
}
return (
action.meta.from === MAIN_MESSAGE_TYPE &&
action.meta.to === CONTENT_MESSAGE_TYPE
);
},
getPortIdOfSender(action) {
return (action.meta && action.meta.fromTarget) || null;
},
_RouteMessage,
};
const EXPORTED_SYMBOLS = [
"actionTypes",
"actionCreators",
"actionUtils",
"ASRouterActions",
"globalImportContext",
"UI_CODE",
"BACKGROUND_PROCESS",
"MAIN_MESSAGE_TYPE",
"CONTENT_MESSAGE_TYPE",
"PRELOAD_MESSAGE_TYPE",
];
================================================
FILE: common/Dedupe.jsm
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
this.Dedupe = class Dedupe {
constructor(createKey) {
this.createKey = createKey || this.defaultCreateKey;
}
defaultCreateKey(item) {
return item;
}
/**
* Dedupe any number of grouped elements favoring those from earlier groups.
*
* @param {Array} groups Contains an arbitrary number of arrays of elements.
* @returns {Array} A matching array of each provided group deduped.
*/
group(...groups) {
const globalKeys = new Set();
const result = [];
for (const values of groups) {
const valueMap = new Map();
for (const value of values) {
const key = this.createKey(value);
if (!globalKeys.has(key) && !valueMap.has(key)) {
valueMap.set(key, value);
}
}
result.push(valueMap);
valueMap.forEach((value, key) => globalKeys.add(key));
}
return result.map(m => Array.from(m.values()));
}
};
const EXPORTED_SYMBOLS = ["Dedupe"];
================================================
FILE: common/PerfService.jsm
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
if (typeof ChromeUtils !== "undefined") {
// Use a var here instead of let outside to avoid creating a locally scoped
// variable that hides the global, which we modify for testing.
// eslint-disable-next-line no-var, vars-on-top
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
}
let usablePerfObj;
/* istanbul ignore else */
// eslint-disable-next-line block-scoped-var
if (typeof Services !== "undefined") {
// Borrow the high-resolution timer from the hidden window....
// eslint-disable-next-line block-scoped-var
usablePerfObj = Services.appShell.hiddenDOMWindow.performance;
} else {
// we must be running in content space
// eslint-disable-next-line no-undef
usablePerfObj = performance;
}
function _PerfService(options) {
// For testing, so that we can use a fake Window.performance object with
// known state.
if (options && options.performanceObj) {
this._perf = options.performanceObj;
} else {
this._perf = usablePerfObj;
}
}
_PerfService.prototype = {
/**
* Calls the underlying mark() method on the appropriate Window.performance
* object to add a mark with the given name to the appropriate performance
* timeline.
*
* @param {String} name the name to give the current mark
* @return {void}
*/
mark: function mark(str) {
this._perf.mark(str);
},
/**
* Calls the underlying getEntriesByName on the appropriate Window.performance
* object.
*
* @param {String} name
* @param {String} type eg "mark"
* @return {Array} Performance* objects
*/
getEntriesByName: function getEntriesByName(name, type) {
return this._perf.getEntriesByName(name, type);
},
/**
* The timeOrigin property from the appropriate performance object.
* Used to ensure that timestamps from the add-on code and the content code
* are comparable.
*
* @note If this is called from a context without a window
* (eg a JSM in chrome), it will return the timeOrigin of the XUL hidden
* window, which appears to be the first created window (and thus
* timeOrigin) in the browser. Note also, however, there is also a private
* hidden window, presumably for private browsing, which appears to be
* created dynamically later. Exactly how/when that shows up needs to be
* investigated.
*
* @return {Number} A double of milliseconds with a precision of 0.5us.
*/
get timeOrigin() {
return this._perf.timeOrigin;
},
/**
* Returns the "absolute" version of performance.now(), i.e. one that
* should ([bug 1401406](https://bugzilla.mozilla.org/show_bug.cgi?id=1401406)
* be comparable across both chrome and content.
*
* @return {Number}
*/
absNow: function absNow() {
return this.timeOrigin + this._perf.now();
},
/**
* This returns the absolute startTime from the most recent performance.mark()
* with the given name.
*
* @param {String} name the name to lookup the start time for
*
* @return {Number} the returned start time, as a DOMHighResTimeStamp
*
* @throws {Error} "No Marks with the name ..." if none are available
*
* @note Always surround calls to this by try/catch. Otherwise your code
* may fail when the `privacy.resistFingerprinting` pref is true. When
* this pref is set, all attempts to get marks will likely fail, which will
* cause this method to throw.
*
* See [bug 1369303](https://bugzilla.mozilla.org/show_bug.cgi?id=1369303)
* for more info.
*/
getMostRecentAbsMarkStartByName(name) {
let entries = this.getEntriesByName(name, "mark");
if (!entries.length) {
throw new Error(`No marks with the name ${name}`);
}
let mostRecentEntry = entries[entries.length - 1];
return this._perf.timeOrigin + mostRecentEntry.startTime;
},
};
this.perfService = new _PerfService();
const EXPORTED_SYMBOLS = ["_PerfService", "perfService"];
================================================
FILE: common/Reducers.jsm
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { actionTypes: at } = ChromeUtils.import(
"resource://activity-stream/common/Actions.jsm"
);
const { Dedupe } = ChromeUtils.import(
"resource://activity-stream/common/Dedupe.jsm"
);
const TOP_SITES_DEFAULT_ROWS = 1;
const TOP_SITES_MAX_SITES_PER_ROW = 8;
const dedupe = new Dedupe(site => site && site.url);
const INITIAL_STATE = {
App: {
// Have we received real data from the app yet?
initialized: false,
},
ASRouter: { initialized: false },
Snippets: { initialized: false },
TopSites: {
// Have we received real data from history yet?
initialized: false,
// The history (and possibly default) links
rows: [],
// Used in content only to dispatch action to TopSiteForm.
editForm: null,
// Used in content only to open the SearchShortcutsForm modal.
showSearchShortcutsForm: false,
// The list of available search shortcuts.
searchShortcuts: [],
},
Prefs: {
initialized: false,
values: {},
},
Dialog: {
visible: false,
data: {},
},
Sections: [],
Pocket: {
isUserLoggedIn: null,
pocketCta: {},
waitingForSpoc: true,
},
// This is the new pocket configurable layout state.
DiscoveryStream: {
// This is a JSON-parsed copy of the discoverystream.config pref value.
config: { enabled: false, layout_endpoint: "" },
layout: [],
lastUpdated: null,
isPrivacyInfoModalVisible: false,
feeds: {
data: {
// "https://foo.com/feed1": {lastUpdated: 123, data: []}
},
loaded: false,
},
spocs: {
spocs_endpoint: "",
spocs_per_domain: 1,
lastUpdated: null,
data: {}, // {spocs: []}
loaded: false,
frequency_caps: [],
blocked: [],
placements: [],
},
},
Search: {
// When search hand-off is enabled, we render a big button that is styled to
// look like a search textbox. If the button is clicked, we style
// the button as if it was a focused search box and show a fake cursor but
// really focus the awesomebar without the focus styles ("hidden focus").
fakeFocus: false,
// Hide the search box after handing off to AwesomeBar and user starts typing.
hide: false,
},
};
function App(prevState = INITIAL_STATE.App, action) {
switch (action.type) {
case at.INIT:
return Object.assign({}, prevState, action.data || {}, {
initialized: true,
});
default:
return prevState;
}
}
function ASRouter(prevState = INITIAL_STATE.ASRouter, action) {
switch (action.type) {
case at.AS_ROUTER_INITIALIZED:
return { ...action.data, initialized: true };
default:
return prevState;
}
}
/**
* insertPinned - Inserts pinned links in their specified slots
*
* @param {array} a list of links
* @param {array} a list of pinned links
* @return {array} resulting list of links with pinned links inserted
*/
function insertPinned(links, pinned) {
// Remove any pinned links
const pinnedUrls = pinned.map(link => link && link.url);
let newLinks = links.filter(link =>
link ? !pinnedUrls.includes(link.url) : false
);
newLinks = newLinks.map(link => {
if (link && link.isPinned) {
delete link.isPinned;
delete link.pinIndex;
}
return link;
});
// Then insert them in their specified location
pinned.forEach((val, index) => {
if (!val) {
return;
}
let link = Object.assign({}, val, { isPinned: true, pinIndex: index });
if (index > newLinks.length) {
newLinks[index] = link;
} else {
newLinks.splice(index, 0, link);
}
});
return newLinks;
}
function TopSites(prevState = INITIAL_STATE.TopSites, action) {
let hasMatch;
let newRows;
switch (action.type) {
case at.TOP_SITES_UPDATED:
if (!action.data || !action.data.links) {
return prevState;
}
return Object.assign(
{},
prevState,
{ initialized: true, rows: action.data.links },
action.data.pref ? { pref: action.data.pref } : {}
);
case at.TOP_SITES_PREFS_UPDATED:
return Object.assign({}, prevState, { pref: action.data.pref });
case at.TOP_SITES_EDIT:
return Object.assign({}, prevState, {
editForm: {
index: action.data.index,
previewResponse: null,
},
});
case at.TOP_SITES_CANCEL_EDIT:
return Object.assign({}, prevState, { editForm: null });
case at.TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL:
return Object.assign({}, prevState, { showSearchShortcutsForm: true });
case at.TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL:
return Object.assign({}, prevState, { showSearchShortcutsForm: false });
case at.PREVIEW_RESPONSE:
if (
!prevState.editForm ||
action.data.url !== prevState.editForm.previewUrl
) {
return prevState;
}
return Object.assign({}, prevState, {
editForm: {
index: prevState.editForm.index,
previewResponse: action.data.preview,
previewUrl: action.data.url,
},
});
case at.PREVIEW_REQUEST:
if (!prevState.editForm) {
return prevState;
}
return Object.assign({}, prevState, {
editForm: {
index: prevState.editForm.index,
previewResponse: null,
previewUrl: action.data.url,
},
});
case at.PREVIEW_REQUEST_CANCEL:
if (!prevState.editForm) {
return prevState;
}
return Object.assign({}, prevState, {
editForm: {
index: prevState.editForm.index,
previewResponse: null,
},
});
case at.SCREENSHOT_UPDATED:
newRows = prevState.rows.map(row => {
if (row && row.url === action.data.url) {
hasMatch = true;
return Object.assign({}, row, { screenshot: action.data.screenshot });
}
return row;
});
return hasMatch
? Object.assign({}, prevState, { rows: newRows })
: prevState;
case at.PLACES_BOOKMARK_ADDED:
if (!action.data) {
return prevState;
}
newRows = prevState.rows.map(site => {
if (site && site.url === action.data.url) {
const { bookmarkGuid, bookmarkTitle, dateAdded } = action.data;
return Object.assign({}, site, {
bookmarkGuid,
bookmarkTitle,
bookmarkDateCreated: dateAdded,
});
}
return site;
});
return Object.assign({}, prevState, { rows: newRows });
case at.PLACES_BOOKMARK_REMOVED:
if (!action.data) {
return prevState;
}
newRows = prevState.rows.map(site => {
if (site && site.url === action.data.url) {
const newSite = Object.assign({}, site);
delete newSite.bookmarkGuid;
delete newSite.bookmarkTitle;
delete newSite.bookmarkDateCreated;
return newSite;
}
return site;
});
return Object.assign({}, prevState, { rows: newRows });
case at.PLACES_LINK_DELETED:
if (!action.data) {
return prevState;
}
newRows = prevState.rows.filter(site => action.data.url !== site.url);
return Object.assign({}, prevState, { rows: newRows });
case at.UPDATE_SEARCH_SHORTCUTS:
return { ...prevState, searchShortcuts: action.data.searchShortcuts };
case at.SNIPPETS_PREVIEW_MODE:
return { ...prevState, rows: [] };
default:
return prevState;
}
}
function Dialog(prevState = INITIAL_STATE.Dialog, action) {
switch (action.type) {
case at.DIALOG_OPEN:
return Object.assign({}, prevState, { visible: true, data: action.data });
case at.DIALOG_CANCEL:
return Object.assign({}, prevState, { visible: false });
case at.DELETE_HISTORY_URL:
return Object.assign({}, INITIAL_STATE.Dialog);
default:
return prevState;
}
}
function Prefs(prevState = INITIAL_STATE.Prefs, action) {
let newValues;
switch (action.type) {
case at.PREFS_INITIAL_VALUES:
return Object.assign({}, prevState, {
initialized: true,
values: action.data,
});
case at.PREF_CHANGED:
newValues = Object.assign({}, prevState.values);
newValues[action.data.name] = action.data.value;
return Object.assign({}, prevState, { values: newValues });
default:
return prevState;
}
}
function Sections(prevState = INITIAL_STATE.Sections, action) {
let hasMatch;
let newState;
switch (action.type) {
case at.SECTION_DEREGISTER:
return prevState.filter(section => section.id !== action.data);
case at.SECTION_REGISTER:
// If section exists in prevState, update it
newState = prevState.map(section => {
if (section && section.id === action.data.id) {
hasMatch = true;
return Object.assign({}, section, action.data);
}
return section;
});
// Otherwise, append it
if (!hasMatch) {
const initialized = !!(action.data.rows && !!action.data.rows.length);
const section = Object.assign(
{ title: "", rows: [], enabled: false },
action.data,
{ initialized }
);
newState.push(section);
}
return newState;
case at.SECTION_UPDATE:
newState = prevState.map(section => {
if (section && section.id === action.data.id) {
// If the action is updating rows, we should consider initialized to be true.
// This can be overridden if initialized is defined in the action.data
const initialized = action.data.rows ? { initialized: true } : {};
// Make sure pinned cards stay at their current position when rows are updated.
// Disabling a section (SECTION_UPDATE with empty rows) does not retain pinned cards.
if (
action.data.rows &&
!!action.data.rows.length &&
section.rows.find(card => card.pinned)
) {
const rows = Array.from(action.data.rows);
section.rows.forEach((card, index) => {
if (card.pinned) {
// Only add it if it's not already there.
if (rows[index].guid !== card.guid) {
rows.splice(index, 0, card);
}
}
});
return Object.assign(
{},
section,
initialized,
Object.assign({}, action.data, { rows })
);
}
return Object.assign({}, section, initialized, action.data);
}
return section;
});
if (!action.data.dedupeConfigurations) {
return newState;
}
action.data.dedupeConfigurations.forEach(dedupeConf => {
newState = newState.map(section => {
if (section.id === dedupeConf.id) {
const dedupedRows = dedupeConf.dedupeFrom.reduce(
(rows, dedupeSectionId) => {
const dedupeSection = newState.find(
s => s.id === dedupeSectionId
);
const [, newRows] = dedupe.group(dedupeSection.rows, rows);
return newRows;
},
section.rows
);
return Object.assign({}, section, { rows: dedupedRows });
}
return section;
});
});
return newState;
case at.SECTION_UPDATE_CARD:
return prevState.map(section => {
if (section && section.id === action.data.id && section.rows) {
const newRows = section.rows.map(card => {
if (card.url === action.data.url) {
return Object.assign({}, card, action.data.options);
}
return card;
});
return Object.assign({}, section, { rows: newRows });
}
return section;
});
case at.PLACES_BOOKMARK_ADDED:
if (!action.data) {
return prevState;
}
return prevState.map(section =>
Object.assign({}, section, {
rows: section.rows.map(item => {
// find the item within the rows that is attempted to be bookmarked
if (item.url === action.data.url) {
const { bookmarkGuid, bookmarkTitle, dateAdded } = action.data;
return Object.assign({}, item, {
bookmarkGuid,
bookmarkTitle,
bookmarkDateCreated: dateAdded,
type: "bookmark",
});
}
return item;
}),
})
);
case at.PLACES_SAVED_TO_POCKET:
if (!action.data) {
return prevState;
}
return prevState.map(section =>
Object.assign({}, section, {
rows: section.rows.map(item => {
if (item.url === action.data.url) {
return Object.assign({}, item, {
open_url: action.data.open_url,
pocket_id: action.data.pocket_id,
title: action.data.title,
type: "pocket",
});
}
return item;
}),
})
);
case at.PLACES_BOOKMARK_REMOVED:
if (!action.data) {
return prevState;
}
return prevState.map(section =>
Object.assign({}, section, {
rows: section.rows.map(item => {
// find the bookmark within the rows that is attempted to be removed
if (item.url === action.data.url) {
const newSite = Object.assign({}, item);
delete newSite.bookmarkGuid;
delete newSite.bookmarkTitle;
delete newSite.bookmarkDateCreated;
if (!newSite.type || newSite.type === "bookmark") {
newSite.type = "history";
}
return newSite;
}
return item;
}),
})
);
case at.PLACES_LINK_DELETED:
case at.PLACES_LINK_BLOCKED:
if (!action.data) {
return prevState;
}
return prevState.map(section =>
Object.assign({}, section, {
rows: section.rows.filter(site => site.url !== action.data.url),
})
);
case at.DELETE_FROM_POCKET:
case at.ARCHIVE_FROM_POCKET:
return prevState.map(section =>
Object.assign({}, section, {
rows: section.rows.filter(
site => site.pocket_id !== action.data.pocket_id
),
})
);
case at.SNIPPETS_PREVIEW_MODE:
return prevState.map(section => ({ ...section, rows: [] }));
default:
return prevState;
}
}
function Snippets(prevState = INITIAL_STATE.Snippets, action) {
switch (action.type) {
case at.SNIPPETS_DATA:
return Object.assign({}, prevState, { initialized: true }, action.data);
case at.SNIPPET_BLOCKED:
return Object.assign({}, prevState, {
blockList: prevState.blockList.concat(action.data),
});
case at.SNIPPETS_BLOCKLIST_CLEARED:
return Object.assign({}, prevState, { blockList: [] });
case at.SNIPPETS_RESET:
return INITIAL_STATE.Snippets;
default:
return prevState;
}
}
function Pocket(prevState = INITIAL_STATE.Pocket, action) {
switch (action.type) {
case at.POCKET_WAITING_FOR_SPOC:
return { ...prevState, waitingForSpoc: action.data };
case at.POCKET_LOGGED_IN:
return { ...prevState, isUserLoggedIn: !!action.data };
case at.POCKET_CTA:
return {
...prevState,
pocketCta: {
ctaButton: action.data.cta_button,
ctaText: action.data.cta_text,
ctaUrl: action.data.cta_url,
useCta: action.data.use_cta,
},
};
default:
return prevState;
}
}
function DiscoveryStream(prevState = INITIAL_STATE.DiscoveryStream, action) {
// Return if action data is empty, or spocs or feeds data is not loaded
const isNotReady = () =>
!action.data || !prevState.spocs.loaded || !prevState.feeds.loaded;
const handlePlacements = handleSites => {
const { data, placements } = prevState.spocs;
const result = {};
const forPlacement = placement => {
const placementSpocs = data[placement.name];
if (!placementSpocs || !placementSpocs.length) {
return;
}
result[placement.name] = handleSites(placementSpocs);
};
if (!placements || !placements.length) {
[{ name: "spocs" }].forEach(forPlacement);
} else {
placements.forEach(forPlacement);
}
return result;
};
const nextState = handleSites => ({
...prevState,
spocs: {
...prevState.spocs,
data: handlePlacements(handleSites),
},
feeds: {
...prevState.feeds,
data: Object.keys(prevState.feeds.data).reduce(
(accumulator, feed_url) => {
accumulator[feed_url] = {
data: {
...prevState.feeds.data[feed_url].data,
recommendations: handleSites(
prevState.feeds.data[feed_url].data.recommendations
),
},
};
return accumulator;
},
{}
),
},
});
switch (action.type) {
case at.DISCOVERY_STREAM_CONFIG_CHANGE:
// Fall through to a separate action is so it doesn't trigger a listener update on init
case at.DISCOVERY_STREAM_CONFIG_SETUP:
return { ...prevState, config: action.data || {} };
case at.DISCOVERY_STREAM_LAYOUT_UPDATE:
return {
...prevState,
lastUpdated: action.data.lastUpdated || null,
layout: action.data.layout || [],
};
case at.HIDE_PRIVACY_INFO:
return {
...prevState,
isPrivacyInfoModalVisible: false,
};
case at.SHOW_PRIVACY_INFO:
return {
...prevState,
isPrivacyInfoModalVisible: true,
};
case at.DISCOVERY_STREAM_LAYOUT_RESET:
return { ...INITIAL_STATE.DiscoveryStream, config: prevState.config };
case at.DISCOVERY_STREAM_FEEDS_UPDATE:
return {
...prevState,
feeds: {
...prevState.feeds,
loaded: true,
},
};
case at.DISCOVERY_STREAM_FEED_UPDATE:
const newData = {};
newData[action.data.url] = action.data.feed;
return {
...prevState,
feeds: {
...prevState.feeds,
data: {
...prevState.feeds.data,
...newData,
},
},
};
case at.DISCOVERY_STREAM_SPOCS_CAPS:
return {
...prevState,
spocs: {
...prevState.spocs,
frequency_caps: [...prevState.spocs.frequency_caps, ...action.data],
},
};
case at.DISCOVERY_STREAM_SPOCS_ENDPOINT:
return {
...prevState,
spocs: {
...INITIAL_STATE.DiscoveryStream.spocs,
spocs_endpoint:
action.data.url ||
INITIAL_STATE.DiscoveryStream.spocs.spocs_endpoint,
spocs_per_domain:
action.data.spocs_per_domain ||
INITIAL_STATE.DiscoveryStream.spocs.spocs_per_domain,
},
};
case at.DISCOVERY_STREAM_SPOCS_PLACEMENTS:
return {
...prevState,
spocs: {
...prevState.spocs,
placements:
action.data.placements ||
INITIAL_STATE.DiscoveryStream.spocs.placements,
},
};
case at.DISCOVERY_STREAM_SPOCS_UPDATE:
if (action.data) {
return {
...prevState,
spocs: {
...prevState.spocs,
lastUpdated: action.data.lastUpdated,
data: action.data.spocs,
loaded: true,
},
};
}
return prevState;
case at.DISCOVERY_STREAM_SPOC_BLOCKED:
return {
...prevState,
spocs: {
...prevState.spocs,
blocked: [...prevState.spocs.blocked, action.data.url],
},
};
case at.DISCOVERY_STREAM_LINK_BLOCKED:
return isNotReady()
? prevState
: nextState(items =>
items.filter(item => item.url !== action.data.url)
);
case at.PLACES_SAVED_TO_POCKET:
const addPocketInfo = item => {
if (item.url === action.data.url) {
return Object.assign({}, item, {
open_url: action.data.open_url,
pocket_id: action.data.pocket_id,
context_type: "pocket",
});
}
return item;
};
return isNotReady()
? prevState
: nextState(items => items.map(addPocketInfo));
case at.DELETE_FROM_POCKET:
case at.ARCHIVE_FROM_POCKET:
return isNotReady()
? prevState
: nextState(items =>
items.filter(item => item.pocket_id !== action.data.pocket_id)
);
case at.PLACES_BOOKMARK_ADDED:
const updateBookmarkInfo = item => {
if (item.url === action.data.url) {
const { bookmarkGuid, bookmarkTitle, dateAdded } = action.data;
return Object.assign({}, item, {
bookmarkGuid,
bookmarkTitle,
bookmarkDateCreated: dateAdded,
context_type: "bookmark",
});
}
return item;
};
return isNotReady()
? prevState
: nextState(items => items.map(updateBookmarkInfo));
case at.PLACES_BOOKMARK_REMOVED:
const removeBookmarkInfo = item => {
if (item.url === action.data.url) {
const newSite = Object.assign({}, item);
delete newSite.bookmarkGuid;
delete newSite.bookmarkTitle;
delete newSite.bookmarkDateCreated;
if (!newSite.context_type || newSite.context_type === "bookmark") {
newSite.context_type = "removedBookmark";
}
return newSite;
}
return item;
};
return isNotReady()
? prevState
: nextState(items => items.map(removeBookmarkInfo));
default:
return prevState;
}
}
function Search(prevState = INITIAL_STATE.Search, action) {
switch (action.type) {
case at.HIDE_SEARCH:
return Object.assign({ ...prevState, hide: true });
case at.FAKE_FOCUS_SEARCH:
return Object.assign({ ...prevState, fakeFocus: true });
case at.SHOW_SEARCH:
return Object.assign({ ...prevState, hide: false, fakeFocus: false });
default:
return prevState;
}
}
this.INITIAL_STATE = INITIAL_STATE;
this.TOP_SITES_DEFAULT_ROWS = TOP_SITES_DEFAULT_ROWS;
this.TOP_SITES_MAX_SITES_PER_ROW = TOP_SITES_MAX_SITES_PER_ROW;
this.reducers = {
TopSites,
App,
ASRouter,
Snippets,
Prefs,
Dialog,
Sections,
Pocket,
DiscoveryStream,
Search,
};
const EXPORTED_SYMBOLS = [
"reducers",
"INITIAL_STATE",
"insertPinned",
"TOP_SITES_DEFAULT_ROWS",
"TOP_SITES_MAX_SITES_PER_ROW",
];
================================================
FILE: components.conf
================================================
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
Classes = [
{
'cid': '{dfcd2adc-7867-4d3a-ba70-17501f208142}',
'contract_ids': ['@mozilla.org/browser/aboutnewtab-service;1'],
'jsm': 'resource:///modules/AboutNewTabService.jsm',
'constructor': 'AboutNewTabService',
},
]
================================================
FILE: content-src/.eslintrc.js
================================================
module.exports = {
rules: {
"import/no-commonjs": 2
}
}
================================================
FILE: content-src/aboutlibrary/aboutlibrary.jsx
================================================
import React from "react";
import ReactDOM from "react-dom";
class LibraryRouter extends React.PureComponent {
render() {
return <div className="under-construction" />;
}
}
ReactDOM.render(<LibraryRouter />, document.body);
================================================
FILE: content-src/aboutlibrary/aboutlibrary.scss
================================================
.under-construction {
background-image: url('chrome://browser/content/illustrations/under-construction.svg');
background-repeat: no-repeat;
background-position: center;
min-height: 300px;
min-width: 300px;
margin-top: 10%;
}
================================================
FILE: content-src/activity-stream.jsx
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import { actionCreators as ac, actionTypes as at } from "common/Actions.jsm";
import { Base } from "content-src/components/Base/Base";
import { DetectUserSessionStart } from "content-src/lib/detect-user-session-start";
import { initStore } from "content-src/lib/init-store";
import { Provider } from "react-redux";
import React from "react";
import ReactDOM from "react-dom";
import { reducers } from "common/Reducers.jsm";
const store = initStore(reducers);
new DetectUserSessionStart(store).sendEventOrAddListener();
store.dispatch(ac.AlsoToMain({ type: at.NEW_TAB_STATE_REQUEST }));
ReactDOM.hydrate(
<Provider store={store}>
<Base
isFirstrun={global.document.location.href === "about:welcome"}
locale={global.document.documentElement.lang}
strings={global.gActivityStreamStrings}
/>
</Provider>,
document.getElementById("root")
);
================================================
FILE: content-src/asrouter/README.md
================================================
# Activity Stream Router
## Preferences `browser.newtab.activity-stream.asrouter.*`
Name | Used for | Type | Example value
--- | --- | --- | ---
`whitelistHosts` | Whitelist a host in order to fetch messages from its endpoint | `[String]` | `["gist.github.com", "gist.githubusercontent.com", "localhost:8000"]`
`providers.snippets` | Message provider options for snippets | `Object` | [see below](#message-providers)
`providers.cfr` | Message provider options for cfr | `Object` | [see below](#message-providers)
`providers.onboarding` | Message provider options for onboarding | `Object` | [see below](#message-providers)
`useRemoteL10n` | Controls whether to use the remote Fluent files for l10n, default as `true` | `Boolean` | `[true|false]`
### Message providers examples
```json
{
"id" : "snippets",
"type" : "remote",
"enabled": true,
"url" : "https://snippets.cdn.mozilla.net/us-west/bundles/bundle_d6d90fb9098ce8b45e60acf601bcb91b68322309.json",
"updateCycleInMs" : 14400000
}
```
```json
{
"id" : "onboarding",
"enabled": true,
"type" : "local",
"localProvider" : "OnboardingMessageProvider"
}
```
### [Snippet message format documentation](https://github.com/mozilla/activity-stream/blob/master/content-src/asrouter/schemas/message-format.md)
================================================
FILE: content-src/asrouter/asrouter-content.jsx
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import {
actionCreators as ac,
actionTypes as at,
ASRouterActions as ra,
} from "common/Actions.jsm";
import { OUTGOING_MESSAGE_NAME as AS_GENERAL_OUTGOING_MESSAGE_NAME } from "content-src/lib/init-store";
import { generateBundles } from "./rich-text-strings";
import { ImpressionsWrapper } from "./components/ImpressionsWrapper/ImpressionsWrapper";
import { LocalizationProvider } from "fluent-react";
import { NEWTAB_DARK_THEME } from "content-src/lib/constants";
import React from "react";
import ReactDOM from "react-dom";
import { SnippetsTemplates } from "./templates/template-manifest";
import { FirstRun } from "./templates/FirstRun/FirstRun";
const INCOMING_MESSAGE_NAME = "ASRouter:parent-to-child";
const OUTGOING_MESSAGE_NAME = "ASRouter:child-to-parent";
const TEMPLATES_ABOVE_PAGE = [
"trailhead",
"full_page_interrupt",
"return_to_amo_overlay",
"extended_triplets",
];
const FIRST_RUN_TEMPLATES = TEMPLATES_ABOVE_PAGE;
const TEMPLATES_BELOW_SEARCH = ["simple_below_search_snippet"];
export const ASRouterUtils = {
addListener(listener) {
if (global.RPMAddMessageListener) {
global.RPMAddMessageListener(INCOMING_MESSAGE_NAME, listener);
}
},
removeListener(listener) {
if (global.RPMRemoveMessageListener) {
global.RPMRemoveMessageListener(INCOMING_MESSAGE_NAME, listener);
}
},
sendMessage(action) {
if (global.RPMSendAsyncMessage) {
global.RPMSendAsyncMessage(OUTGOING_MESSAGE_NAME, action);
}
},
blockById(id, options) {
ASRouterUtils.sendMessage({
type: "BLOCK_MESSAGE_BY_ID",
data: { id, ...options },
});
},
dismissById(id) {
ASRouterUtils.sendMessage({ type: "DISMISS_MESSAGE_BY_ID", data: { id } });
},
executeAction(button_action) {
ASRouterUtils.sendMessage({
type: "USER_ACTION",
data: button_action,
});
},
unblockById(id) {
ASRouterUtils.sendMessage({ type: "UNBLOCK_MESSAGE_BY_ID", data: { id } });
},
unblockBundle(bundle) {
ASRouterUtils.sendMessage({ type: "UNBLOCK_BUNDLE", data: { bundle } });
},
overrideMessage(id) {
ASRouterUtils.sendMessage({ type: "OVERRIDE_MESSAGE", data: { id } });
},
sendTelemetry(ping) {
if (global.RPMSendAsyncMessage) {
const payload = ac.ASRouterUserEvent(ping);
global.RPMSendAsyncMessage(AS_GENERAL_OUTGOING_MESSAGE_NAME, payload);
}
},
getPreviewEndpoint() {
if (global.location && global.location.href.includes("endpoint")) {
const params = new URLSearchParams(
global.location.href.slice(global.location.href.indexOf("endpoint"))
);
try {
const endpoint = new URL(params.get("endpoint"));
return {
url: endpoint.href,
snippetId: params.get("snippetId"),
theme: this.getPreviewTheme(),
};
} catch (e) {}
}
return null;
},
getPreviewTheme() {
return new URLSearchParams(
global.location.href.slice(global.location.href.indexOf("theme"))
).get("theme");
},
};
// Note: nextProps/prevProps refer to props passed to <ImpressionsWrapper />, not <ASRouterUISurface />
function shouldSendImpressionOnUpdate(nextProps, prevProps) {
return (
nextProps.message.id &&
(!prevProps.message || prevProps.message.id !== nextProps.message.id)
);
}
export class ASRouterUISurface extends React.PureComponent {
constructor(props) {
super(props);
this.onMessageFromParent = this.onMessageFromParent.bind(this);
this.sendClick = this.sendClick.bind(this);
this.sendImpression = this.sendImpression.bind(this);
this.sendUserActionTelemetry = this.sendUserActionTelemetry.bind(this);
this.onUserAction = this.onUserAction.bind(this);
this.fetchFlowParams = this.fetchFlowParams.bind(this);
this.state = { message: {}, interruptCleared: false };
if (props.document) {
this.headerPortal = props.document.getElementById(
"header-asrouter-container"
);
this.footerPortal = props.document.getElementById(
"footer-asrouter-container"
);
}
}
async fetchFlowParams(params = {}) {
let result = {};
const { fxaEndpoint, dispatch } = this.props;
if (!fxaEndpoint) {
const err =
"Tried to fetch flow params before fxaEndpoint pref was ready";
console.error(err); // eslint-disable-line no-console
}
try {
const urlObj = new URL(fxaEndpoint);
urlObj.pathname = "metrics-flow";
Object.keys(params).forEach(key => {
urlObj.searchParams.append(key, params[key]);
});
const response = await fetch(urlObj.toString(), { credentials: "omit" });
if (response.status === 200) {
const { deviceId, flowId, flowBeginTime } = await response.json();
result = { deviceId, flowId, flowBeginTime };
} else {
console.error("Non-200 response", response); // eslint-disable-line no-console
dispatch(
ac.OnlyToMain({
type: at.TELEMETRY_UNDESIRED_EVENT,
data: {
event: "FXA_METRICS_FETCH_ERROR",
value: response.status,
},
})
);
}
} catch (error) {
console.error(error); // eslint-disable-line no-console
dispatch(
ac.OnlyToMain({
type: at.TELEMETRY_UNDESIRED_EVENT,
data: { event: "FXA_METRICS_ERROR" },
})
);
}
return result;
}
sendUserActionTelemetry(extraProps = {}) {
const { message } = this.state;
const eventType = `${message.provider}_user_event`;
ASRouterUtils.sendTelemetry({
message_id: message.id,
source: extraProps.id,
action: eventType,
...extraProps,
});
}
sendImpression(extraProps) {
if (this.state.message.provider === "preview") {
return;
}
ASRouterUtils.sendMessage({ type: "IMPRESSION", data: this.state.message });
this.sendUserActionTelemetry({ event: "IMPRESSION", ...extraProps });
}
// If link has a `metric` data attribute send it as part of the `event_context`
// telemetry field which can have arbitrary values.
// Used for router messages with links as part of the content.
sendClick(event) {
const metric = {
event_context: event.target.dataset.metric,
// Used for the `source` of the event. Needed to differentiate
// from other snippet or onboarding events that may occur.
id: "NEWTAB_FOOTER_BAR_CONTENT",
};
const action = {
type: event.target.dataset.action,
data: { args: event.target.dataset.args },
};
if (action.type) {
ASRouterUtils.executeAction(action);
}
if (
!this.state.message.content.do_not_autoblock &&
!event.target.dataset.do_not_autoblock
) {
ASRouterUtils.blockById(this.state.message.id);
}
if (this.state.message.provider !== "preview") {
this.sendUserActionTelemetry({ event: "CLICK_BUTTON", ...metric });
}
}
onBlockById(id) {
return options => ASRouterUtils.blockById(id, options);
}
onDismissById(id) {
return () => ASRouterUtils.dismissById(id);
}
clearMessage(id) {
// Request new set of dynamic triplet cards when click on a card CTA clear
// message and 'id' matches one of the cards in message bundle
if (
this.state.message &&
this.state.message.bundle &&
this.state.message.bundle.find(card => card.id === id)
) {
this.requestMessage();
}
if (id === this.state.message.id) {
this.setState({ message: {} });
// Remove any styles related to the RTAMO message
document.body.classList.remove("welcome", "hide-main", "amo");
}
}
onMessageFromParent({ data: action }) {
switch (action.type) {
case "SET_MESSAGE":
this.setState({ message: action.data });
break;
case "CLEAR_INTERRUPT":
this.setState({ interruptCleared: true });
break;
case "CLEAR_MESSAGE":
this.clearMessage(action.data.id);
break;
case "CLEAR_PROVIDER":
if (action.data.id === this.state.message.provider) {
this.setState({ message: {} });
}
break;
case "CLEAR_ALL":
this.setState({ message: {} });
break;
case "AS_ROUTER_TARGETING_UPDATE":
action.data.forEach(id => this.clearMessage(id));
break;
}
}
requestMessage(endpoint) {
// If we are loading about:welcome we want to trigger the onboarding messages
if (
this.props.document &&
this.props.document.location.href === "about:welcome"
) {
ASRouterUtils.sendMessage({
type: "TRIGGER",
data: { trigger: { id: "firstRun" } },
});
} else {
ASRouterUtils.sendMessage({
type: "NEWTAB_MESSAGE_REQUEST",
data: { endpoint },
});
}
}
componentWillMount() {
const endpoint = ASRouterUtils.getPreviewEndpoint();
if (endpoint && endpoint.theme === "dark") {
global.window.dispatchEvent(
new CustomEvent("LightweightTheme:Set", {
detail: { data: NEWTAB_DARK_THEME },
})
);
}
ASRouterUtils.addListener(this.onMessageFromParent);
this.requestMessage(endpoint);
}
componentWillUnmount() {
ASRouterUtils.removeListener(this.onMessageFromParent);
}
async getMonitorUrl({ url, flowRequestParams = {} }) {
const flowValues = await this.fetchFlowParams(flowRequestParams);
// Note that flowParams are actually added dynamically on the page
const urlObj = new URL(url);
["deviceId", "flowId", "flowBeginTime"].forEach(key => {
if (key in flowValues) {
urlObj.searchParams.append(key, flowValues[key]);
}
});
return urlObj.toString();
}
async onUserAction(action) {
switch (action.type) {
// This needs to be handled locally because its
case ra.ENABLE_FIREFOX_MONITOR:
const url = await this.getMonitorUrl(action.data.args);
ASRouterUtils.executeAction({ type: ra.OPEN_URL, data: { args: url } });
break;
default:
ASRouterUtils.executeAction(action);
}
}
renderSnippets() {
const { message } = this.state;
if (!SnippetsTemplates[message.template]) {
return null;
}
const SnippetComponent = SnippetsTemplates[message.template];
const { content } = this.state.message;
return (
<ImpressionsWrapper
id="NEWTAB_FOOTER_BAR"
message={this.state.message}
sendImpression={this.sendImpression}
shouldSendImpressionOnUpdate={shouldSendImpressionOnUpdate}
// This helps with testing
document={this.props.document}
>
<LocalizationProvider bundles={generateBundles(content)}>
<SnippetComponent
{...this.state.message}
UISurface="NEWTAB_FOOTER_BAR"
onBlock={this.onBlockById(this.state.message.id)}
onDismiss={this.onDismissById(this.state.message.id)}
onAction={this.onUserAction}
sendClick={this.sendClick}
sendUserActionTelemetry={this.sendUserActionTelemetry}
/>
</LocalizationProvider>
</ImpressionsWrapper>
);
}
renderPreviewBanner() {
if (this.state.message.provider !== "preview") {
return null;
}
return (
<div className="snippets-preview-banner">
<span className="icon icon-small-spacer icon-info" />
<span>Preview Purposes Only</span>
</div>
);
}
renderFirstRun() {
const { message } = this.state;
if (FIRST_RUN_TEMPLATES.includes(message.template)) {
return (
<ImpressionsWrapper
id="FIRST_RUN"
message={this.state.message}
sendImpression={this.sendImpression}
shouldSendImpressionOnUpdate={shouldSendImpressionOnUpdate}
// This helps with testing
document={this.props.document}
>
<FirstRun
document={this.props.document}
interruptCleared={this.state.interruptCleared}
message={message}
sendUserActionTelemetry={this.sendUserActionTelemetry}
executeAction={ASRouterUtils.executeAction}
dispatch={this.props.dispatch}
onBlockById={ASRouterUtils.blockById}
onDismiss={this.onDismissById(this.state.message.id)}
fxaEndpoint={this.props.fxaEndpoint}
appUpdateChannel={this.props.appUpdateChannel}
fetchFlowParams={this.fetchFlowParams}
/>
</ImpressionsWrapper>
);
}
return null;
}
render() {
const { message } = this.state;
if (!message.id) {
return null;
}
const shouldRenderBelowSearch = TEMPLATES_BELOW_SEARCH.includes(
message.template
);
const shouldRenderInHeader = TEMPLATES_ABOVE_PAGE.includes(
message.template
);
return shouldRenderBelowSearch ? (
// Render special below search snippets in place;
<div className="below-search-snippet-wrapper">
{this.renderSnippets()}
</div>
) : (
// For onboarding, regular snippets etc. we should render
// everything in our footer container.
ReactDOM.createPortal(
<>
{this.renderPreviewBanner()}
{this.renderFirstRun()}
{this.renderSnippets()}
</>,
shouldRenderInHeader ? this.headerPortal : this.footerPortal
)
);
}
}
ASRouterUISurface.defaultProps = { document: global.document };
================================================
FILE: content-src/asrouter/components/Button/Button.jsx
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
const ALLOWED_STYLE_TAGS = ["color", "backgroundColor"];
export const Button = props => {
const style = {};
// Add allowed style tags from props, e.g. props.color becomes style={color: props.color}
for (const tag of ALLOWED_STYLE_TAGS) {
if (typeof props[tag] !== "undefined") {
style[tag] = props[tag];
}
}
// remove border if bg is set to something custom
if (style.backgroundColor) {
style.border = "0";
}
return (
<button
onClick={props.onClick}
className={props.className || "ASRouterButton secondary"}
style={style}
>
{props.children}
</button>
);
};
================================================
FILE: content-src/asrouter/components/Button/_Button.scss
================================================
.ASRouterButton {
font-weight: 600;
font-size: 14px;
white-space: nowrap;
border-radius: 2px;
border: 0;
font-family: inherit;
padding: 8px 15px;
margin-inline-start: 12px;
color: inherit;
cursor: pointer;
.tall & {
margin-inline-start: 20px;
}
&.primary {
border: 1px solid var(--newtab-button-primary-color);
background-color: var(--newtab-button-primary-color);
color: $grey-10;
&:hover {
background-color: $blue-70;
}
&:active {
background-color: $blue-80;
}
}
&.secondary {
background-color: $grey-90-10;
&:hover {
background-color: $grey-90-20;
}
&:active {
background-color: $grey-90-30;
}
&:focus {
box-shadow: 0 0 0 1px $blue-50 inset, 0 0 0 1px $blue-50, 0 0 0 4px $blue-50-30;
}
}
}
[lwt-newtab-brighttext] {
.secondary {
background-color: $grey-10-10;
&:hover {
background-color: $grey-10-20;
}
&:active {
background-color: $grey-10-30;
}
}
// Snippets scene 2 footer
.footer {
.secondary {
background-color: $grey-10-30;
&:hover {
background-color: $grey-10-40;
}
&:active {
background-color: $grey-10-50;
}
}
}
}
================================================
FILE: content-src/asrouter/components/ConditionalWrapper/ConditionalWrapper.jsx
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// lifted from https://gist.github.com/kitze/23d82bb9eb0baabfd03a6a720b1d637f
const ConditionalWrapper = ({ condition, wrap, children }) =>
condition ? wrap(children) : children;
export default ConditionalWrapper;
================================================
FILE: content-src/asrouter/components/FxASignupForm/FxASignupForm.jsx
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import { actionCreators as ac } from "common/Actions.jsm";
import {
addUtmParams,
BASE_PARAMS,
} from "../../templates/FirstRun/addUtmParams";
import React from "react";
export class FxASignupForm extends React.PureComponent {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
this.onInputChange = this.onInputChange.bind(this);
this.onInputInvalid = this.onInputInvalid.bind(this);
this.handleSignIn = this.handleSignIn.bind(this);
this.state = {
emailInput: "",
};
}
get email() {
return this.props.document
.getElementById("fxaSignupForm")
.querySelector("input[name=email]");
}
onSubmit(event) {
let userEvent = "SUBMIT_EMAIL";
const { email } = event.target.elements;
if (email.disabled) {
userEvent = "SUBMIT_SIGNIN";
} else if (!email.value.length) {
email.required = true;
email.checkValidity();
event.preventDefault();
return;
}
// Report to telemetry additional information about the form submission.
const value = { has_flow_params: !!this.props.flowParams.flowId.length };
this.props.dispatch(ac.UserEvent({ event: userEvent, value }));
global.addEventListener("visibilitychange", this.props.onClose);
}
handleSignIn(event) {
// Set disabled to prevent email from appearing in url resulting in the wrong page
this.email.disabled = true;
}
componentDidMount() {
// Start with focus in the email input box
if (this.email) {
this.email.focus();
}
}
onInputChange(e) {
let error = e.target.previousSibling;
this.setState({ emailInput: e.target.value });
error.classList.remove("active");
e.target.classList.remove("invalid");
}
onInputInvalid(e) {
let error = e.target.previousSibling;
error.classList.add("active");
e.target.classList.add("invalid");
e.preventDefault(); // Override built-in form validation popup
e.target.focus();
}
render() {
const { content, UTMTerm } = this.props;
return (
<div
id="fxaSignupForm"
role="group"
aria-labelledby="joinFormHeader"
aria-describedby="joinFormBody"
className="fxaSignupForm"
>
<h3 id="joinFormHeader" data-l10n-id={content.form.title.string_id} />
<p id="joinFormBody" data-l10n-id={content.form.text.string_id} />
<form
method="get"
action={this.props.fxaEndpoint}
target="_blank"
rel="noopener noreferrer"
onSubmit={this.onSubmit}
>
<input name="action" type="hidden" value="email" />
<input name="context" type="hidden" value="fx_desktop_v3" />
<input
name="entrypoint"
type="hidden"
value="activity-stream-firstrun"
/>
<input name="utm_source" type="hidden" value="activity-stream" />
<input
name="utm_campaign"
type="hidden"
value={BASE_PARAMS.utm_campaign}
/>
<input name="utm_term" type="hidden" value={UTMTerm} />
<input
name="device_id"
type="hidden"
value={this.props.flowParams.deviceId}
/>
<input
name="flow_id"
type="hidden"
value={this.props.flowParams.flowId}
/>
<input
name="flow_begin_time"
type="hidden"
value={this.props.flowParams.flowBeginTime}
/>
<input name="style" type="hidden" value="trailhead" />
<p
data-l10n-id="onboarding-join-form-email-error"
className="error"
/>
<input
data-l10n-id={content.form.email.string_id}
name="email"
type="email"
onInvalid={this.onInputInvalid}
onChange={this.onInputChange}
/>
<p className="fxa-terms" data-l10n-id="onboarding-join-form-legal">
<a
data-l10n-name="terms"
target="_blank"
rel="noopener noreferrer"
href={addUtmParams(
"https://accounts.firefox.com/legal/terms",
UTMTerm
)}
/>
<a
data-l10n-name="privacy"
target="_blank"
rel="noopener noreferrer"
href={addUtmParams(
"https://accounts.firefox.com/legal/privacy",
UTMTerm
)}
/>
</p>
<button data-l10n-id={content.form.button.string_id} type="submit" />
{this.props.showSignInLink && (
<div className="fxa-signin">
<span data-l10n-id="onboarding-join-form-signin-label" />
<button
data-l10n-id="onboarding-join-form-signin"
onClick={this.handleSignIn}
/>
</div>
)}
</form>
</div>
);
}
}
FxASignupForm.defaultProps = { document: global.document };
================================================
FILE: content-src/asrouter/components/FxASignupForm/_FxASignupForm.scss
================================================
.fxaSignupForm {
min-width: 260px;
text-align: center;
a {
color: $white;
text-decoration: underline;
}
input,
button {
border-radius: 4px;
padding: 10px;
}
h3 {
font-size: 36px;
font-weight: 200;
line-height: 46px;
margin: 12px 0 4px;
}
p {
font-size: 15px;
line-height: 22px;
margin: 0 0 20px;
}
.fxa-terms {
margin: 4px 30px 20px;
a,
& {
color: $white-70;
font-size: 12px;
line-height: 20px;
}
}
.fxa-signin {
font-size: 16px;
margin-top: 19px;
span {
margin-inline-end: 5px;
}
button {
background-color: initial;
text-decoration: underline;
color: $white;
display: inline;
padding: 0;
width: auto;
&:hover,
&:focus,
&:active {
background-color: initial;
}
}
}
form {
position: relative;
.error.active {
inset-inline-start: 0;
z-index: 0;
}
}
button,
input {
width: 100%;
}
input {
background-color: $white;
border: 1px solid $grey-50;
box-shadow: none;
color: $grey-70;
font-size: 15px;
transition: border-color 150ms, box-shadow 150ms;
&:hover {
border-color: $grey-90;
}
&:focus {
border-color: $blue-50;
box-shadow: 0 0 0 3px $email-input-focus;
}
&.invalid {
border-color: $red-60;
}
&.invalid:focus {
box-shadow: 0 0 0 3px $email-input-invalid;
}
}
button {
background-color: $blue-60;
border: 0;
cursor: pointer;
display: block;
font-size: 15px;
font-weight: 400;
padding: 14px;
&:hover,
&:focus {
background-color: $trailhead-blue-60;
}
&:focus {
outline: dotted 1px;
}
&:active {
background-color: $trailhead-blue-70;
}
}
}
================================================
FILE: content-src/asrouter/components/ImpressionsWrapper/ImpressionsWrapper.jsx
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
export const VISIBLE = "visible";
export const VISIBILITY_CHANGE_EVENT = "visibilitychange";
/**
* Component wrapper used to send telemetry pings on every impression.
*/
export class ImpressionsWrapper extends React.PureComponent {
// This sends an event when a user sees a set of new content. If content
// changes while the page is hidden (i.e. preloaded or on a hidden tab),
// only send the event if the page becomes visible again.
sendImpressionOrAddListener() {
if (this.props.document.visibilityState === VISIBLE) {
this.props.sendImpression({ id: this.props.id });
} else {
// We should only ever send the latest impression stats ping, so remove any
// older listeners.
if (this._onVisibilityChange) {
this.props.document.removeEventListener(
VISIBILITY_CHANGE_EVENT,
this._onVisibilityChange
);
}
// When the page becomes visible, send the impression stats ping if the section isn't collapsed.
this._onVisibilityChange = () => {
if (this.props.document.visibilityState === VISIBLE) {
this.props.sendImpression({ id: this.props.id });
this.props.document.removeEventListener(
VISIBILITY_CHANGE_EVENT,
this._onVisibilityChange
);
}
};
this.props.document.addEventListener(
VISIBILITY_CHANGE_EVENT,
this._onVisibilityChange
);
}
}
componentWillUnmount() {
if (this._onVisibilityChange) {
this.props.document.removeEventListener(
VISIBILITY_CHANGE_EVENT,
this._onVisibilityChange
);
}
}
componentDidMount() {
if (this.props.sendOnMount) {
this.sendImpressionOrAddListener();
}
}
componentDidUpdate(prevProps) {
if (this.props.shouldSendImpressionOnUpdate(this.props, prevProps)) {
this.sendImpressionOrAddListener();
}
}
render() {
return this.props.children;
}
}
ImpressionsWrapper.defaultProps = {
document: global.document,
sendOnMount: true,
};
================================================
FILE: content-src/asrouter/components/ModalOverlay/ModalOverlay.jsx
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
export class ModalOverlayWrapper extends React.PureComponent {
constructor(props) {
super(props);
this.onKeyDown = this.onKeyDown.bind(this);
}
// The intended behaviour is to listen for an escape key
// but not for a click; see Bug 1582242
onKeyDown(event) {
if (event.key === "Escape") {
this.props.onClose(event);
}
}
componentWillMount() {
this.props.document.addEventListener("keydown", this.onKeyDown);
this.props.document.body.classList.add("modal-open");
this.header = this.props.document.getElementById(
"header-asrouter-container"
);
if (this.header) {
this.header.classList.add("modal-scroll");
this.props.document.getElementById("root").classList.add("modal-height");
}
}
componentWillUnmount() {
this.props.document.removeEventListener("keydown", this.onKeyDown);
this.props.document.body.classList.remove("modal-open");
if (this.header) {
this.header.classList.remove("modal-scroll");
this.props.document
.getElementById("root")
.classList.remove("modal-height");
}
}
render() {
const { props } = this;
let className = props.unstyled ? "" : "modalOverlayInner active";
if (props.innerClassName) {
className += ` ${props.innerClassName}`;
}
return (
<React.Fragment>
<div
className="modalOverlayOuter active"
onKeyDown={this.onKeyDown}
role="presentation"
/>
<div
className={className}
aria-labelledby={props.headerId}
id={props.id}
role="dialog"
>
{props.hasDismissIcon && (
<button
className="icon icon-dismiss"
onClick={props.onClose}
data-l10n-id="onboarding-cards-dismiss"
/>
)}
{props.children}
</div>
</React.Fragment>
);
}
}
ModalOverlayWrapper.defaultProps = { document: global.document };
export class ModalOverlay extends React.PureComponent {
render() {
const { title, button_label } = this.props;
return (
<ModalOverlayWrapper onClose={this.props.onDismissBundle}>
<h2> {title} </h2>
{this.props.children}
<div className="footer">
<button
className="button primary modalButton"
onClick={this.props.onDismissBundle}
>
{" "}
{button_label}{" "}
</button>
</div>
</ModalOverlayWrapper>
);
}
}
================================================
FILE: content-src/asrouter/components/ModalOverlay/_ModalOverlay.scss
================================================
.activity-stream {
&.modal-open {
overflow: hidden;
}
}
.modalOverlayOuter {
background: var(--newtab-overlay-color);
height: 100%;
position: fixed;
top: 0;
left: 0;
width: 100%;
display: none;
z-index: 1100;
&.active {
display: block;
}
}
.modal-scroll {
position: absolute;
width: 100%;
height: 100%;
overflow: auto;
}
.modal-height {
// "Welcome header" has 40px of padding and 36px font size that get neglected using position absolute
// causing this to visually collide with the newtab searchbar
padding-top: 80px;
}
.modalOverlayInner {
width: 960px;
position: fixed;
top: 15%;
left: calc(50% - 480px); // halfway across minus half the width of the modal
background: var(--newtab-modal-color);
box-shadow: 0 1px 15px 0 $black-30;
border-radius: 4px;
display: none;
z-index: 1101;
// modal takes over entire screen
@media(max-width: 960px) {
width: 100%;
height: 100%;
top: 0;
left: 0;
box-shadow: none;
border-radius: 0;
}
// if modal is short enough, reduce the top margin
@media(max-height: 730px) {
top: 5%;
}
&.active {
display: block;
}
.icon-dismiss {
border: 0;
cursor: pointer;
inset-inline-end: 0;
padding: 20px;
fill: $white;
position: absolute;
&:focus {
border: 1px dotted;
}
}
h2 {
color: $grey-60;
text-align: center;
font-weight: 200;
margin-top: 30px;
font-size: 28px;
line-height: 37px;
letter-spacing: -0.13px;
@media(max-width: 960px) {
margin-top: 100px;
}
@media(max-width: 850px) {
margin-top: 30px;
}
}
.footer {
border-top: 1px solid $grey-30;
border-radius: 4px;
height: 70px;
width: 100%;
position: absolute;
bottom: 0;
text-align: center;
background-color: $white;
// if modal is short enough, footer becomes sticky
@media(max-width: 850px) and (max-height: 730px) {
position: sticky;
}
// if modal is narrow enough, footer becomes sticky
@media(max-width: 650px) and (max-height: 600px) {
position: sticky;
}
.modalButton {
margin-top: 20px;
min-width: 150px;
height: 30px;
padding: 4px 30px 6px;
font-size: 15px;
&:focus,
&.active,
&:hover {
box-shadow: 0 0 0 5px $grey-30;
transition: box-shadow 150ms;
}
}
}
}
================================================
FILE: content-src/asrouter/components/RichText/RichText.jsx
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import { Localized } from "fluent-react";
import React from "react";
import { RICH_TEXT_KEYS } from "../../rich-text-strings";
import { safeURI } from "../../template-utils";
// Elements allowed in snippet content
const ALLOWED_TAGS = {
b: <b />,
i: <i />,
u: <u />,
strong: <strong />,
em: <em />,
br: <br />,
};
/**
* Transform an object (tag name: {url}) into (tag name: anchor) where the url
* is used as href, in order to render links inside a Fluent.Localized component.
*/
export function convertLinks(
links,
sendClick,
doNotAutoBlock,
openNewWindow = false
) {
if (links) {
return Object.keys(links).reduce((acc, linkTag) => {
const { action } = links[linkTag];
// Setting the value to false will not include the attribute in the anchor
const url = action ? false : safeURI(links[linkTag].url);
acc[linkTag] = (
// eslint was getting a false positive caused by the dynamic injection
// of content.
// eslint-disable-next-line jsx-a11y/anchor-has-content
<a
href={url}
target={openNewWindow ? "_blank" : ""}
data-metric={links[linkTag].metric}
data-action={action}
data-args={links[linkTag].args}
data-do_not_autoblock={doNotAutoBlock}
onClick={sendClick}
/>
);
return acc;
}, {});
}
return null;
}
/**
* Message wrapper used to sanitize markup and render HTML.
*/
export function RichText(props) {
if (!RICH_TEXT_KEYS.includes(props.localization_id)) {
throw new Error(
`ASRouter: ${
props.localization_id
} is not a valid rich text property. If you want it to be processed, you need to add it to asrouter/rich-text-strings.js`
);
}
return (
<Localized
id={props.localization_id}
{...ALLOWED_TAGS}
{...props.customElements}
{...convertLinks(
props.links,
props.sendClick,
props.doNotAutoBlock,
props.openNewWindow
)}
>
<span>{props.text}</span>
</Localized>
);
}
================================================
FILE: content-src/asrouter/components/SnippetBase/SnippetBase.jsx
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
import schema from "../../templates/SimpleSnippet/SimpleSnippet.schema.json";
export class SnippetBase extends React.PureComponent {
constructor(props) {
super(props);
this.onBlockClicked = this.onBlockClicked.bind(this);
this.onDismissClicked = this.onDismissClicked.bind(this);
this.setBlockButtonRef = this.setBlockButtonRef.bind(this);
this.onBlockButtonMouseEnter = this.onBlockButtonMouseEnter.bind(this);
this.onBlockButtonMouseLeave = this.onBlockButtonMouseLeave.bind(this);
this.state = { blockButtonHover: false };
}
componentDidMount() {
if (this.blockButtonRef) {
this.blockButtonRef.addEventListener(
"mouseenter",
this.onBlockButtonMouseEnter
);
this.blockButtonRef.addEventListener(
"mouseleave",
this.onBlockButtonMouseLeave
);
}
}
componentWillUnmount() {
if (this.blockButtonRef) {
this.blockButtonRef.removeEventListener(
"mouseenter",
this.onBlockButtonMouseEnter
);
this.blockButtonRef.removeEventListener(
"mouseleave",
this.onBlockButtonMouseLeave
);
}
}
setBlockButtonRef(element) {
this.blockButtonRef = element;
}
onBlockButtonMouseEnter() {
this.setState({ blockButtonHover: true });
}
onBlockButtonMouseLeave() {
this.setState({ blockButtonHover: false });
}
onBlockClicked() {
if (this.props.provider !== "preview") {
this.props.sendUserActionTelemetry({
event: "BLOCK",
id: this.props.UISurface,
});
}
this.props.onBlock();
}
onDismissClicked() {
if (this.props.provider !== "preview") {
this.props.sendUserActionTelemetry({
event: "DISMISS",
id: this.props.UISurface,
});
}
this.props.onDismiss();
}
renderDismissButton() {
if (this.props.footerDismiss) {
return (
<div className="footer">
<div className="footer-content">
<button
className="ASRouterButton secondary"
onClick={this.onDismissClicked}
>
{this.props.content.scene2_dismiss_button_text}
</button>
</div>
</div>
);
}
const label =
this.props.content.block_button_text ||
schema.properties.block_button_text.default;
return (
<button
className="blockButton"
title={label}
aria-label={label}
onClick={this.onBlockClicked}
ref={this.setBlockButtonRef}
/>
);
}
render() {
const { props } = this;
const { blockButtonHover } = this.state;
const containerClassName = `SnippetBaseContainer${
props.className ? ` ${props.className}` : ""
}${blockButtonHover ? " active" : ""}`;
return (
<div className={containerClassName} style={this.props.textStyle}>
<div className="innerWrapper">{props.children}</div>
{this.renderDismissButton()}
</div>
);
}
}
================================================
FILE: content-src/asrouter/components/SnippetBase/_SnippetBase.scss
================================================
.SnippetBaseContainer {
position: fixed;
z-index: 2;
bottom: 0;
left: 0;
right: 0;
background-color: var(--newtab-snippets-background-color);
color: var(--newtab-text-primary-color);
font-size: 14px;
line-height: 20px;
border-top: 1px solid var(--newtab-snippets-hairline-color);
box-shadow: $shadow-secondary;
display: flex;
align-items: center;
a {
cursor: pointer;
color: var(--newtab-link-primary-color);
&:hover {
text-decoration: underline;
}
[lwt-newtab-brighttext] & {
font-weight: bold;
}
}
input {
&[type='checkbox'] {
margin-inline-start: 0;
}
}
.innerWrapper {
margin: 0 auto;
display: flex;
align-items: center;
padding: 12px $section-horizontal-padding;
// This is to account for the block button on smaller screens
padding-inline-end: 36px;
@media (min-width: $break-point-large) {
padding-inline-end: $section-horizontal-padding;
}
max-width: $wrapper-max-width-large + ($section-horizontal-padding * 2);
@media (min-width: $break-point-widest) {
max-width: $wrapper-max-width-widest + ($section-horizontal-padding * 2);
}
}
.blockButton {
display: none;
background: none;
border: 0;
position: absolute;
top: 50%;
inset-inline-end: 12px;
height: 16px;
width: 16px;
background-image: url('resource://activity-stream/data/content/assets/glyph-dismiss-16.svg');
-moz-context-properties: fill;
fill: var(--newtab-icon-primary-color);
opacity: 0.5;
margin-top: -8px;
padding: 0;
cursor: pointer;
@media (min-width: 766px) {
inset-inline-end: 24px;
}
}
&:hover .blockButton {
display: block;
}
.icon {
height: 42px;
width: 42px;
margin-inline-end: 12px;
flex-shrink: 0;
}
}
.snippets-preview-banner {
font-size: 15px;
line-height: 42px;
color: $grey-60-70;
background: $grey-30-60;
text-align: center;
position: absolute;
top: 0;
width: 100%;
span {
vertical-align: middle;
}
}
// We show snippet icons for both themes and conditionally hide
// based on which theme is currently active
body {
&:not([lwt-newtab-brighttext]) {
.icon-dark-theme,
.icon.icon-dark-theme,
.scene2Icon .icon-dark-theme {
display: none;
}
}
&[lwt-newtab-brighttext] {
.icon-light-theme,
.icon.icon-light-theme,
.scene2Icon .icon-light-theme {
display: none;
}
}
}
================================================
FILE: content-src/asrouter/docs/debugging-docs.md
================================================
# Using ASRouter Devtools
## How to enable ASRouter devtools
- In `about:config`, set `browser.newtabpage.activity-stream.asrouter.devtoolsEnabled` to `true`
- Visit `about:newtab#asrouter` to see the devtools.
## Overview of ASRouter devtools

## How to enable/disable a provider
To enable a provider such as `snippets`, Look at the list of "Message Providers" at the top of the page. Make sure the checkbox is checked next to the provider you want to enable.
To disable it, uncheck the checkbox. You should see a red label indicating the provider is now disabled.
## How to see all messages from a provider
(Only available in Firefox 65+)
In order to see all active messages for a current provider such as `snippets`, use the drop down selector under the "Messages" section. Select the name of the provider you are interested in.
The messages on the page should now be filtered to include only the provider you selected.
## How to test telemetry pings
To test telemetry pings, complete the the following steps:
- In about:config, set:
- `browser.newtabpage.activity-stream.telemetry` to `true`
- `browser.ping-centre.log` to `true`
- Open the Browser Toolbox devtools (Tools > Web Developer > Browser Toolbox) and switch to the console tab. Add a filter for for `activity-stream` to only display relevant pings:

You should now see pings show up as you view/interact with ASR messages/templates.
## Snippets debugging
### How to view preview URLs
Follow these steps to view preview URLs (e.g. `about:newtab?endpoint=https://gist.githubusercontent.com/piatra/d193ca7e0f513cc19fc6a1d396c214f7/raw/8bcaf9548212e4c613577e839198cc14e7317630/newsletter_snippet.json&theme=dark`)
You can preview in the two different themes (light and dark) by adding `&theme=dark` or `&theme=light` at the end of the url.
#### IMPORTANT NOTES
- Links to URLs starting with `about:newtab` cannot be clicked on directly. They must be copy and pasted into the address bar.
- Previews should only be tested in `Firefox 64` and later.
- The endpoint must be HTTPS, the host must be whitelisted (see testing instructions below)
- Errors are surfaced in the `Console` tab of the `Browser Toolbox`
#### Testing instructions
- If your endpoint URL has a host name of `snippets-admin.mozilla.org`, you can paste the URL into the address bar view it without any further steps.
- If your endpoint URL starts with some other host name, it must be **whitelisted**. Open the Browser Toolbox devtools (Tools > Developer > Browser Toolbox) and paste the following code (where `gist.githubusercontent.com` is the hostname of your endpoint URL):
```js
Services.prefs.setStringPref(
"browser.newtab.activity-stream.asrouter.whitelistHosts",
"[\"gist.githubusercontent.com\"]"
);
```
- Restart the browser
- You should now be able to paste the URL into the address bar and view it.
================================================
FILE: content-src/asrouter/docs/experiment-guide.md
================================================
# How to run experiments with ASRouter
This guide will tell you how to run an experiment with ASRouter messages.
Note that the actual experiment process and infrastructure is handled by
the experiments team (#ask-experimenter).
## Why run an experiment
* To measure the effect of a message on a Firefox metric (e.g. retention)
* To test a potentially risky message on a smaller group of users
* To compare the performance of multiple variants of messages in a controlled way
## Choose cohort IDs and request an experiment
First you should decide on a cohort ID (this can be any arbitrary unique string) for each
individual group you need to segment for your experiment.
For example, if I want to test two variants of an FXA Snippet, I might have two cohort IDs,
`FXA_SNIPPET_V1` and `FXA_SNIPPET_V2`.
You will then [request](https://experimenter.services.mozilla.com/) a new "pref-flip" study with the Firefox Experiments team.
The preferences you will submit will be based on the cohort IDs you chose.
For the FXA Snippet example, your preference name would be `browser.newtabpage.activity-stream.asrouter.providers.snippets` and values would be:
Control (default value)
```json
{"id":"snippets","enabled":true,"type":"remote","url":"https://snippets.cdn.mozilla.net/%STARTPAGE_VERSION%/%NAME%/%VERSION%/%APPBUILDID%/%BUILD_TARGET%/%LOCALE%/release/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/","updateCycleInMs":14400000}
```
Variant 1:
```json
{"id":"snippets", "cohort": "FXA_SNIPPET_V1", "enabled":true,"type":"remote","url":"https://snippets.cdn.mozilla.net/%STARTPAGE_VERSION%/%NAME%/%VERSION%/%APPBUILDID%/%BUILD_TARGET%/%LOCALE%/release/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/","updateCycleInMs":14400000}
```
Variant 2:
```json
{"id":"snippets", "cohort": "FXA_SNIPPET_V1", "enabled":true,"type":"remote","url":"https://snippets.cdn.mozilla.net/%STARTPAGE_VERSION%/%NAME%/%VERSION%/%APPBUILDID%/%BUILD_TARGET%/%LOCALE%/release/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/","updateCycleInMs":14400000}
```
## Add targeting to your messages
You must now check for the cohort ID in the `targeting` expression of the messages you want to include in your experiments.
For the previous example, you wold include the following to target the first cohort:
```json
{
"targeting": "providerCohorts.snippets == \"FXA_SNIPPET_V1\""
}
```
================================================
FILE: content-src/asrouter/docs/targeting-attributes.md
================================================
# Targeting attributes
When you create ASRouter messages such as snippets, contextual feature recommendations, or onboarding cards, you may choose to include **targeting information** with those messages.
Targeting information must be captured in [an expression](./targeting-guide.md) that has access to the following attributes. You may combine and compare any of these attributes as needed.
Please note that some targeting attributes require stricter controls on the telemetry than can be colleted, so when in doubt, ask for review.
## Available attributes
* [addonsInfo](#addonsinfo)
* [attributionData](#attributiondata)
* [browserSettings](#browsersettings)
* [currentDate](#currentdate)
* [devToolsOpenedCount](#devtoolsopenedcount)
* [isDefaultBrowser](#isdefaultbrowser)
* [firefoxVersion](#firefoxversion)
* [locale](#locale)
* [localeLanguageCode](#localelanguagecode)
* [needsUpdate](#needsupdate)
* [pinnedSites](#pinnedsites)
* [previousSessionEnd](#previoussessionend)
* [profileAgeCreated](#profileagecreated)
* [profileAgeReset](#profileagereset)
* [providerCohorts](#providercohorts)
* [region](#region)
* [searchEngines](#searchengines)
* [sync](#sync)
* [topFrecentSites](#topfrecentsites)
* [totalBookmarksCount](#totalbookmarkscount)
* [trailheadInterrupt](#trailheadinterrupt)
* [trailheadTriplet](#trailheadtriplet)
* [usesFirefoxSync](#usesfirefoxsync)
* [isFxAEnabled](#isFxAEnabled)
* [xpinstallEnabled](#xpinstallEnabled)
* [hasPinnedTabs](#haspinnedtabs)
* [hasAccessedFxAPanel](#hasaccessedfxapanel)
* [isWhatsNewPanelEnabled](#iswhatsnewpanelenabled)
* [isFxABadgeEnabled](#isfxabadgeenabled)
* [totalBlockedCount](#totalblockedcount)
* [recentBookmarks](#recentbookmarks)
* [userPrefs](#userprefs)
* [attachedFxAOAuthClients](#attachedfxaoauthclients)
* [platformName](#platformname)
* [scores](#scores)
* [scoreThreshold](#scorethreshold)
* [messageImpressions](#messageimpressions)
* [blockedCountByType](#blockedcountbytype)
## Detailed usage
### `addonsInfo`
Provides information about the add-ons the user has installed.
Note that the `name`, `userDisabled`, and `installDate` is only available if `isFullData` is `true` (this is usually not the case right at start-up).
**Due to an existing bug, `userDisabled` is not currently available**
#### Examples
* Has the user installed the unicorn addon?
```java
addonsInfo.addons["unicornaddon@mozilla.org"]
```
* Has the user installed and disabled the unicorn addon?
```java
addonsInfo.isFullData && addonsInfo.addons["unicornaddon@mozilla.org"].userDisabled
```
#### Definition
```ts
declare const addonsInfo: Promise<AddonsInfoResponse>;
interface AddonsInfoResponse {
// Does this include extra information requiring I/O?
isFullData: boolean;
// addonId should be something like activity-stream@mozilla.org
[addonId: string]: {
// Version of the add-on
version: string;
// (string) e.g. "extension"
type: AddonType;
// Version of the add-on
isSystem: boolean;
// Is the add-on a webextension?
isWebExtension: boolean;
// The name of the add-on
name: string;
// Is the add-on disabled?
// CURRENTLY UNAVAILABLE due to an outstanding bug
userDisabled: boolean;
// When was it installed? e.g. "2018-03-10T03:41:06.000Z"
installDate: string;
};
}
```
### `attributionData`
An object containing information on exactly how Firefox was downloaded
#### Examples
* Was the browser installed via the `"back_to_school"` campaign?
```java
attributionData && attributionData.campaign == "back_to_school"
```
#### Definition
```ts
declare const attributionData: AttributionCode;
interface AttributionCode {
// Descriptor for where the download started from
campaign: string,
// A source, like addons.mozilla.org, or google.com
source: string,
// The medium for the download, like if this was referral
medium: string,
// Additional content, like an addonID for instance
content: string
}
```
### `browserSettings`
Includes two properties:
* `attribution`, which indicates how Firefox was downloaded - DEPRECATED - please use [attributionData](#attributiondata)
* `update`, which has information about how Firefox updates
Note that attribution can be `undefined`, so you should check that it exists first.
#### Examples
* Is updating enabled?
```java
browserSettings.update.enabled
```
#### Definition
```ts
declare const browserSettings: {
attribution: undefined | {
// Referring partner domain, when install happens via a known partner
// e.g. google.com
source: string;
// category of the source, such as "organic" for a search engine
// e.g. organic
medium: string;
// identifier of the particular campaign that led to the download of the product
// e.g. back_to_school
campaign: string;
// identifier to indicate the particular link within a campaign
// e.g. https://mozilla.org/some-page
content: string;
},
update: {
// Is auto-downloading enabled?
autoDownload: boolean;
// What release channel, e.g. "nightly"
channel: string;
// Is updating enabled?
enabled: boolean;
}
}
```
### `currentDate`
The current date at the moment message targeting is checked.
#### Examples
* Is the current date after Oct 3, 2018?
```java
currentDate > "Wed Oct 03 2018 00:00:00"|date
```
#### Definition
```ts
declare const currentDate; ECMA262DateString;
// ECMA262DateString = Date.toString()
type ECMA262DateString = string;
```
### `devToolsOpenedCount`
Number of usages of the web console.
#### Examples
* Has the user opened the web console more than 10 times?
```java
devToolsOpenedCount > 10
```
#### Definition
```ts
declare const devToolsOpenedCount: number;
```
### `isDefaultBrowser`
Is Firefox the user's default browser?
#### Definition
```ts
declare const isDefaultBrowser: boolean;
```
### `firefoxVersion`
The major Firefox version of the browser
#### Examples
* Is the version of the browser greater than 63?
```java
firefoxVersion > 63
```
#### Definition
```ts
declare const firefoxVersion: number;
```
### `locale`
The current locale of the browser including country code, e.g. `en-US`.
#### Examples
* Is the locale of the browser either English (US) or German (Germany)?
```java
locale in ["en-US", "de-DE"]
```
#### Definition
```ts
declare const locale: string;
```
### `localeLanguageCode`
The current locale of the browser NOT including country code, e.g. `en`.
This is useful for matching all countries of a particular language.
#### Examples
* Is the locale of the browser any English locale?
```java
localeLanguageCode == "en"
```
#### Definition
```ts
declare const localeLanguageCode: string;
```
### `needsUpdate`
Does the client have the latest available version installed
```ts
declare const needsUpdate: boolean;
```
### `pinnedSites`
The sites (including search shortcuts) that are pinned on a user's new tab page.
#### Examples
* Has the user pinned any site on `foo.com`?
```java
"foo.com" in pinnedSites|mapToProperty("host")
```
* Does the user have a pinned `duckduckgo.com` search shortcut?
```java
"duckduckgo.com" in pinnedSites[.searchTopSite == true]|mapToProperty("host")
```
#### Definition
```ts
interface PinnedSite {
// e.g. https://foo.mozilla.com/foo/bar
url: string;
// e.g. foo.mozilla.com
host: string;
// is the pin a search shortcut?
searchTopSite: boolean;
}
declare const pinnedSites: Array<PinnedSite>
```
### `previousSessionEnd`
Timestamp of the previously closed session.
#### Definition
```ts
declare const previousSessionEnd: UnixEpochNumber;
// UnixEpochNumber is UNIX Epoch timestamp, e.g. 1522843725924
type UnixEpochNumber = number;
```
### `profileAgeCreated`
The date the profile was created as a UNIX Epoch timestamp.
#### Definition
```ts
declare const profileAgeCreated: UnixEpochNumber;
// UnixEpochNumber is UNIX Epoch timestamp, e.g. 1522843725924
type UnixEpochNumber = number;
```
### `profileAgeReset`
The date the profile was reset as a UNIX Epoch timestamp (if it was reset).
#### Examples
* Was the profile never reset?
```java
!profileAgeReset
```
#### Definition
```ts
// profileAgeReset can be undefined if the profile was never reset
// UnixEpochNumber is number, e.g. 1522843725924
declare const profileAgeReset: undefined | UnixEpochNumber;
// UnixEpochNumber is UNIX Epoch timestamp, e.g. 1522843725924
type UnixEpochNumber = number;
```
### `providerCohorts`
Information about cohort settings (from prefs, including shield studies) for each provider.
#### Examples
* Is the user in the "foo_test" cohort for snippets?
```java
providerCohorts.snippets == "foo_test"
```
#### Definition
```ts
declare const providerCohorts: {
[providerId: string]: string;
}
```
### `region`
Country code retrieved from `location.services.mozilla.com`. Can be `""` if request did not finish or encountered an error.
#### Examples
* Is the user in Canada?
```java
region == "CA"
```
#### Definition
```ts
declare const region: string;
```
### `searchEngines`
Information about the current and available search engines.
#### Examples
* Is the current default search engine set to google?
```java
searchEngines.current == "google"
```
#### Definition
```ts
declare const searchEngines: Promise<SearchEnginesResponse>;
interface SearchEnginesResponse: {
current: SearchEngineId;
installed: Array<SearchEngineId>;
}
// This is an identifier for a search engine such as "google" or "amazondotcom"
type SearchEngineId = string;
```
### `sync`
Information about synced devices.
#### Examples
* Is at least 1 mobile device synced to this profile?
```java
sync.mobileDevices > 0
```
#### Definition
```ts
declare const sync: {
desktopDevices: number;
mobileDevices: number;
totalDevices: number;
}
```
### `topFrecentSites`
Information about the browser's top 25 frecent sites.
**Please note this is a restricted targeting property that influences what telemetry is allowed to be collected may not be used without review**
#### Examples
* Is mozilla.com in the user's top frecent sites with a frececy greater than 400?
```java
"mozilla.com" in topFrecentSites[.frecency >= 400]|mapToProperty("host")
```
#### Definition
```ts
declare const topFrecentSites: Promise<Array<TopSite>>
interface TopSite {
// e.g. https://foo.mozilla.com/foo/bar
url: string;
// e.g. foo.mozilla.com
host: string;
frecency: number;
lastVisitDate: UnixEpochNumber;
}
// UnixEpochNumber is UNIX Epoch timestamp, e.g. 1522843725924
type UnixEpochNumber = number;
```
### `totalBookmarksCount`
Total number of bookmarks.
#### Definition
```ts
declare const totalBookmarksCount: number;
```
### `trailheadInterrupt`
(67.05+ only) Experiment branch for "interrupt" study
### `trailheadTriplet`
(67.05+ only) Experiment branch for "triplet" study
### `usesFirefoxSync`
Does the user use Firefox sync?
#### Definition
```ts
declare const usesFirefoxSync: boolean;
```
### `isFxAEnabled`
Does the user have Firefox sync enabled? The service could potentially be turned off [for enterprise builds](https://searchfox.org/mozilla-central/rev/b59a99943de4dd314bae4e44ab43ce7687ccbbec/browser/components/enterprisepolicies/Policies.jsm#327).
#### Definition
```ts
declare const isFxAEnabled: boolean;
```
### `xpinstallEnabled`
Pref used by system administrators to disallow add-ons from installed altogether.
#### Definition
```ts
declare const xpinstallEnabled: boolean;
```
### `hasPinnedTabs`
Does the user have any pinned tabs in any windows.
#### Definition
```ts
declare const hasPinnedTabs: boolean;
```
### `hasAccessedFxAPanel`
Boolean pref that gets set the first time the user opens the FxA toolbar panel
#### Definition
```ts
declare const hasAccessedFxAPanel: boolean;
```
### `isWhatsNewPanelEnabled`
Boolean pref that controls if the What's New panel feature is enabled
#### Definition
```ts
declare const isWhatsNewPanelEnabled: boolean;
```
### `isFxABadgeEnabled`
Boolean pref that controls if the FxA toolbar button is badged by Messaging System.
#### Definition
```ts
declare const isFxABadgeEnabled: boolean;
```
### `totalBlockedCount`
Total number of events from the content blocking database
#### Definition
```ts
declare const totalBlockedCount: number;
```
### `recentBookmarks`
An array of GUIDs of recent bookmarks as provided by [`NewTabUtils.getRecentBookmarks`](https://searchfox.org/mozilla-central/rev/e0b0c38ee83f99d3cf868bad525ace4a395039f1/toolkit/modules/NewTabUtils.jsm#1087)
#### Definition
```ts
interface Bookmark {
bookmarkGuid: string;
url: string;
title: string;
...
}
declare const recentBookmarks: Array<Bookmark>
```
### `userPrefs`
Information about user facing prefs configurable from `about:preferences`.
#### Examples
```java
userPrefs.cfrFeatures == false
```
#### Definition
```ts
declare const userPrefs: {
cfrFeatures: boolean;
cfrAddons: boolean;
snippets: boolean;
}
```
### `attachedFxAOAuthClients`
Information about connected services associated with the FxA Account.
Return an empty array if no account is found or an error occurs.
#### Definition
```
interface OAuthClient {
// OAuth client_id of the service
// https://docs.telemetry.mozilla.org/datasets/fxa_metrics/attribution.html#service-attribution
id: string;
lastAccessedDaysAgo: number;
}
declare const attachedFxAOAuthClients: Promise<OAuthClient[]>
```
#### Examples
```javascript
{
id: "7377719276ad44ee",
name: "Pocket",
lastAccessTime: 1513599164000
}
```
### `platformName`
[Platform information](https://searchfox.org/mozilla-central/rev/05a22d864814cb1e4352faa4004e1f975c7d2eb9/toolkit/modules/AppConstants.jsm#156).
#### Definition
```
declare const platformName = "linux" | "win" | "macosx" | "android" | "other";
```
### `scores`
#### Definition
See more in [CFR Machine Learning Experiment](https://bugzilla.mozilla.org/show_bug.cgi?id=1594422).
```
declare const scores = { [cfrId: string]: number (integer); }
```
### `scoreThreshold`
#### Definition
See more in [CFR Machine Learning Experiment](https://bugzilla.mozilla.org/show_bug.cgi?id=1594422).
```
declare const scoreThreshold = integer;
```
### `messageImpressions`
Dictionary that maps message ids to impression timestamps. Timestamps are stored in
consecutive order. Can be used to detect first impression of a message, number of
impressions. Can be used in targeting to show a message if another message has been
seen.
Impressions are used for frequency capping so we only store them if the message has
`frequency` configured.
Impressions for badges might not work as expected: we add a badge for every opened
window so the number of impressions stored might be higher than expected. Additionally
not all badges have `frequency` cap so `messageImpressions` might not be defined.
Badge impressions should not be used for targeting.
#### Definition
```
declare const messageImpressions: { [key: string]: Array<UnixEpochNumber> };
```
### `blockedCountByType`
Returns a breakdown by category of all blocked resources in the past 42 days.
#### Definition
```
declare const messageImpressions: { [key: string]: number };
```
#### Examples
```javascript
Object {
trackerCount: 0,
cookieCount: 34,
cryptominerCount: 0,
fingerprinterCount: 3,
socialCount: 2
}
```
================================================
FILE: content-src/asrouter/docs/targeting-guide.md
================================================
# Guide to targeting with JEXL
For a more in-depth explanation of JEXL syntax you can read the [Normady project docs](https://mozilla.github.io/normandy/user/filters.html?highlight=jexl).
### How to write JEXL targeting expressions
A message needs to contain the `targeting` property (JEXL string) which is evaluated against the provided attributes.
Examples:
```javascript
{
"id": "7864",
"content": {...},
// simple equality check
"targeting": "usesFirefoxSync == true"
}
{
"id": "7865",
"content": {...},
// using JEXL transforms and combining two attributes
"targeting": "usesFirefoxSync == true && profileAgeCreated > '2018-01-07'|date"
}
{
"id": "7866",
"content": {...},
// targeting addon information
"targeting": "addonsInfo.addons['activity-stream@mozilla.org'].name == 'Activity Stream'"
}
{
"id": "7866",
"content": {...},
// targeting based on time
"targeting": "currentDate > '2018-08-08'|date"
}
```
================================================
FILE: content-src/asrouter/docs/user-actions.md
================================================
# User Actions
A subset of actions are available to messages via fields like `button_action` for snippets, or `primary_action` for CFRs.
## Usage
For snippets, you should add the action type in `button_action` and any additional parameters in `button_action_args. For example:
```json
{
"button_action": "OPEN_ABOUT_PAGE",
"button_action_args": "config"
}
```
## Available Actions
### `OPEN_APPLICATIONS_MENU`
* args: (none)
Opens the applications menu.
### `OPEN_PRIVATE_BROWSER_WINDOW`
* args: (none)
Opens a new private browsing window.
### `OPEN_URL`
* args: `string` (a url)
Opens a given url.
Example:
```json
{
"button_action": "OPEN_URL",
"button_action_args": "https://foo.com"
}
```
### `OPEN_ABOUT_PAGE`
* args: `string` (a valid about page without the `about:` prefix)
Opens a given about page
Example:
```json
{
"button_action": "OPEN_ABOUT_PAGE",
"button_action_args": "config"
}
```
### `OPEN_PREFERENCES_PAGE`
* args: `string` (a category accessible via a `#`)
Opens `about:preferences` with an optional category accessible via a `#` in the URL (e.g. `about:preferences#home`).
Example:
```json
{
"button_action": "OPEN_PREFERENCES_PAGE",
"button_action_args": "home"
}
```
### `SHOW_FIREFOX_ACCOUNTS`
* args: (none)
Opens Firefox accounts sign-up page. Encodes some information that the origin was from snippets by default.
### `SHOW_MIGRATION_WIZARD`
* args: (none)
Opens import wizard to bring in settings and data from another browser.
### `PIN_CURRENT_TAB`
* args: (none)
Pins the currently focused tab.
### `ENABLE_FIREFOX_MONITOR`
* args:
```ts
{
url: string;
flowRequestParams: {
entrypoint: string;
utm_term: string;
form_type: string;
}
}
```
Opens an oauth flow to enable Firefox Monitor at a given `url` and adds Firefox metrics that user given a set of `flowRequestParams`.
### `url`
The URL should start with `https://monitor.firefox.com/oauth/init` and add various metrics tags as search params, including:
* `utm_source`
* `utm_campaign`
* `form_type`
* `entrypoint`
You should verify the values of these search params with whoever is doing the data analysis (e.g. Leif Oines).
### `flowRequestParams`
These params are used by Firefox to add information specific to that individual user to the final oauth URL. You should include:
* `entrypoint`
* `utm_term`
* `form_type`
The `entrypoint` and `form_type` values should match the encoded values in your `url`.
You should verify the values with whoever is doing the data analysis (e.g. Leif Oines).
### Example
```json
{
"button_action": "ENABLE_FIREFOX_MONITOR",
"button_action_args": {
"url": "https://monitor.firefox.com/oauth/init?utm_source=snippets&utm_campaign=monitor-snippet-test&form_type=email&entrypoint=newtab",
"flowRequestParams": {
"entrypoint": "snippets",
"utm_term": "monitor",
"form_type": "email"
}
}
}
```
================================================
FILE: content-src/asrouter/rich-text-strings.js
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import { FluentBundle } from "fluent";
/**
* Properties that allow rich text MUST be added to this list.
* key: the localization_id that should be used
* value: a property or array of properties on the message.content object
*/
const RICH_TEXT_CONFIG = {
text: ["text", "scene1_text"],
success_text: "success_text",
error_text: "error_text",
scene2_text: "scene2_text",
amo_html: "amo_html",
privacy_html: "scene2_privacy_html",
disclaimer_html: "scene2_disclaimer_html",
};
export const RICH_TEXT_KEYS = Object.keys(RICH_TEXT_CONFIG);
/**
* Generates an array of messages suitable for fluent's localization provider
* including all needed strings for rich text.
* @param {object} content A .content object from an ASR message (i.e. message.content)
* @returns {FluentBundle[]} A array containing the fluent message context
*/
export function generateBundles(content) {
const bundle = new FluentBundle("en-US");
RICH_TEXT_KEYS.forEach(key => {
const attrs = RICH_TEXT_CONFIG[key];
const attrsToTry = Array.isArray(attrs) ? [...attrs] : [attrs];
let string = "";
while (!string && attrsToTry.length) {
const attr = attrsToTry.pop();
string = content[attr];
}
bundle.addMessages(`${key} = ${string}`);
});
return [bundle];
}
================================================
FILE: content-src/asrouter/schemas/message-format.md
================================================
## Activity Stream Router message format
Field name | Type | Required | Description | Example / Note
--- | --- | --- | --- | ---
`id` | `string` | Yes | A unique identifier for the message that should not conflict with any other previous message | `ONBOARDING_1`
`template` | `string` | Yes | An id matching an existing Activity Stream Router template | [See example](https://github.com/mozilla/activity-stream/blob/33669c67c2269078a6d3d6d324fb48175d98f634/system-addon/content-src/message-center/templates/SimpleSnippet.jsx)
`content` | `object` | Yes | An object containing all variables/props to be rendered in the template. Subset of allowed tags detailed below. | [See example below](#html-subset)
`bundled` | `integer` | No | The number of messages of the same template this one should be shown with | [See example below](#a-bundled-message-example)
`order` | `integer` | No | If bundled with other messages of the same template, which order should this one be placed in? Defaults to 0 if no order is desired | [See example below](#a-bundled-message-example)
`campaign` | `string` | No | Campaign id that the message belongs to | `RustWebAssembly`
`targeting` | `string` `JEXL` | No | A [JEXL expression](http://normandy.readthedocs.io/en/latest/user/filter_expressions.html#jexl-basics) with all targeting information needed in order to decide if the message is shown | Not yet implemented, [Examples](#targeting-attributes)
`trigger` | `string` | No | An event or condition upon which the message will be immediately shown. This can be combined with `targeting`. Messages that define a trigger will not be shown during non-trigger-based passive message rotation.
`trigger.params` | `[string]` | No | A set of hostnames passed down as parameters to the trigger condition. Used to restrict the number of domains where the trigger/message is valid. | [See example below](#trigger-params)
`trigger.patterns` | `[string]` | No | A set of patterns that match multiple hostnames passed down as parameters to the trigger condition. Used to restrict the number of domains where the trigger/message is valid. | [See example below](#trigger-patterns)
`frequency` | `object` | No | A definition for frequency cap information for the message
`frequency.lifetime` | `integer` | No | The maximum number of lifetime impressions for the message.
`frequency.custom` | `array` | No | An array of frequency cap definition objects including `period`, a time period in milliseconds, and `cap`, a max number of impressions for that period.
### Message example
```javascript
{
id: "ONBOARDING_1",
template: "simple_snippet",
content: {
title: "Find it faster",
body: "Access all of your favorite search engines with a click. Search the whole Web or just one website from the search box."
},
targeting: "usesFirefoxSync && !addonsInfo.addons['activity-stream@mozilla.org']",
frequency: {
lifetime: 20,
custom: [{period: "daily", cap: 5}, {period: 3600000, cap: 1}]
}
}
```
### A Bundled Message example
The following 2 messages have a `bundled` property, indicating that they should be shown together, since they have the same template. The number `2` indicates that this message should be shown in a bundle of 2 messages of the same template. The order property defines that ONBOARDING_2 should be shown after ONBOARDING_3 in the bundle.
```javascript
{
id: "ONBOARDING_2",
template: "onboarding",
bundled: 2,
order: 2,
content: {
title: "Private Browsing",
body: "Browse by yourself. Private Browsing with Tracking Protection blocks online trackers that follow you around the web."
},
targeting: "",
trigger: "firstRun"
}
{
id: "ONBOARDING_3",
template: "onboarding",
bundled: 2,
order: 1,
content: {
title: "Find it faster",
body: "Access all of your favorite search engines with a click. Search the whole Web or just one website from the search box."
},
targeting: "",
trigger: "firstRun"
}
```
### HTML subset
The following tags are allowed in the content of the snippet: `i, b, u, strong, em, br`.
Links cannot be rendered using regular anchor tags because [Fluent does not allow for href attributes](https://github.com/projectfluent/fluent.js/blob/a03d3aa833660f8c620738b26c80e46b1a4edb05/fluent-dom/src/overlay.js#L13). They will be wrapped in custom tags, for example `<cta>link</cta>` and the url will be provided as part of the payload:
```
{
"id": "7899",
"content": {
"text": "Use the CMD (CTRL) + T keyboard shortcut to <cta>open a new tab quickly!</cta>",
"links": {
"cta": {
"url": "https://support.mozilla.org/en-US/kb/keyboard-shortcuts-perform-firefox-tasks-quickly"
}
}
}
}
```
If a tag that is not on the allowed is used, the text content will be extracted and displayed.
Grouping multiple allowed elements is not possible, only the first level will be used: `<u><b>text</b></u>` will be interpreted as `<u>text</u>`.
### Trigger params
A set of hostnames that need to exactly match the location of the selected tab in order for the trigger to execute.
```
["github.com", "wwww.github.com"]
```
More examples in the [CFRMessageProvider](https://github.com/mozilla/activity-stream/blob/e76ce12fbaaac1182aa492b84fc038f78c3acc33/lib/CFRMessageProvider.jsm#L40-L47).
### Trigger patterns
A set of patterns that can match multiple hostnames. When the location of the selected tab matches one of the patterns it can execute a trigger.
```
["*://*.github.com"] // can match `github.com` but also match `https://gist.github.com/`
```
More [MatchPattern examples](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns#Examples).
### Targeting attributes
(This section has moved to [targeting-attributes.md](../docs/targeting-attributes.md)).
================================================
FILE: content-src/asrouter/schemas/panel/cfr-fxa-bookmark.schema.json
================================================
{
"title": "CFRFxABookmark",
"description": "A message shown in the bookmark panel when user adds or edits a bookmark",
"version": "1.0.0",
"type": "object",
"definitions": {
"plainText": {
"description": "Plain text (no HTML allowed)",
"type": "string"
},
"richText": {
"description": "Text with HTML subset allowed: i, b, u, strong, em, br",
"type": "string"
},
"link_url": {
"description": "Target for links or buttons",
"type": "string",
"format": "uri"
}
},
"properties": {
"title": {
"description": "Shown at the top of the message in the largest font size.",
"oneOf": [
{
"allOf": [
{"$ref": "#/definitions/richText"},
{"description": "Message to be shown"}
]
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Fluent id of localized string"
}
},
"required": ["string_id"]
}
]
},
"text": {
"description": "Longest part of the message, below the title, provides explanation.",
"oneOf": [
{
"allOf": [
{"$ref": "#/definitions/richText"},
{"description": "Message to be shown"}
]
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Fluent id of localized string"
}
},
"required": ["string_id"]
}
]
},
"cta": {
"description": "Link shown at the bottom of the message, call to action",
"oneOf": [
{
"allOf": [
{"$ref": "#/definitions/richText"},
{"description": "Message to be shown"}
]
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Fluent id of localized string"
}
},
"required": ["string_id"]
}
]
},
"info_icon": {
"type": "object",
"description": "The small icon displayed in the top right corner of the panel. Not configurable, only the tooltip text." ,
"properties": {
"tooltiptext": {
"oneOf": [
{
"allOf": [
{"$ref": "#/definitions/plainText"},
{"description": "Message to be shown"}
]
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Fluent id of localized string"
}
},
"required": ["string_id"]
}
]
}
},
"required": ["tooltiptext"]
},
"close_button": {
"type": "object",
"description": "The small dissmiss icon displayed in the top right corner of the message. Not configurable, only the tooltip text." ,
"properties": {
"tooltiptext": {
"oneOf": [
{
"allOf": [
{"$ref": "#/definitions/plainText"},
{"description": "Message to be shown"}
]
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Fluent id of localized string"
}
},
"required": ["string_id"]
}
]
}
},
"required": ["tooltiptext"]
},
"color": {
"description": "Message text color",
"allOf": [
{"$ref": "#/definitions/plainText"},
{"description": "Valid CSS color"}
]
},
"background_color_1": {
"description": "Configurable background color through CSS gradient",
"allOf": [
{"$ref": "#/definitions/plainText"},
{"description": "Valid CSS color"}
]
},
"background_color_2": {
"description": "Configurable background color through CSS gradient",
"allOf": [
{"$ref": "#/definitions/plainText"},
{"description": "Valid CSS color"}
]
}
},
"additionalProperties": false,
"required": ["title", "text", "cta", "info_icon"]
}
================================================
FILE: content-src/asrouter/schemas/provider-response.schema.json
================================================
{
"title": "ProviderResponse",
"description": "A response object for remote providers of AS Router",
"type": "object",
"version": "6.1.0",
"properties": {
"messages": {
"type": "array",
"description": "An array of router messages",
"items": {
"title": "RouterMessage",
"description": "A definition of an individual message",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "A unique identifier for the message that should not conflict with any other previous message"
},
"template": {
"type": "string",
"description": "An id matching an existing Activity Stream Router template",
"enum": ["simple_snippet"]
},
"bundled": {
"type": "integer",
"description": "The number of messages of the same template this one should be shown with (optional)"
},
"order": {
"type": "integer",
"minimum": 0,
"description": "If bundled with other messages of the same template, which order should this one be placed in? (optional - defaults to 0)"
},
"content": {
"type": "object",
"description": "An object containing all variables/props to be rendered in the template. See individual template schemas for details."
},
"targeting": {
"type": "string",
"description": "A JEXL expression representing targeting information"
},
"personalized": {
"type": "boolean",
"description": "Is a personalized score applied to the provider's messages?"
},
"personalizedModelVersion": {
"type": "string",
"description": "The version of the model use for personalization"
},
"trigger": {
"type": "object",
"description": "An action to trigger potentially showing the message",
"properties": {
"id": {
"type": "string",
"description": "A string identifying the trigger action",
"enum": ["firstRun", "openURL"]
},
"params": {
"type": "array",
"description": "An optional array of string parameters for the trigger action",
"items": {
"type": "string",
"description": "A parameter for the trigger action"
}
}
},
"required": ["id"]
},
"frequency": {
"type": "object",
"description": "An object containing frequency cap information for a message.",
"properties": {
"lifetime": {
"type": "integer",
"description": "The maximum lifetime impressions for a message.",
"minimum": 1,
"maximum": 100
},
"custom": {
"type": "array",
"description": "An array of custom frequency cap definitions.",
"items": {
"description": "A frequency cap definition containing time and max impression information",
"type": "object",
"properties": {
"period": {
"oneOf": [
{
"type": "integer",
"description": "Period of time in milliseconds (e.g. 86400000 for one day)"
},
{
"type": "string",
"description": "One of a preset list of short forms for period of time (e.g. 'daily' for one day)",
"enum": ["daily"]
}
]
},
"cap": {
"type": "integer",
"description": "The maximum impressions for the message within the defined period.",
"minimum": 1,
"maximum": 100
}
},
"required": ["period", "cap"]
}
}
}
}
},
"required": ["id", "template", "content"]
}
}
},
"required": ["messages"]
}
================================================
FILE: content-src/asrouter/template-utils.js
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
export function safeURI(url) {
if (!url) {
return "";
}
const { protocol } = new URL(url);
const isAllowed = [
"http:",
"https:",
"data:",
"resource:",
"chrome:",
].includes(protocol);
if (!isAllowed) {
console.warn(`The protocol ${protocol} is not allowed for template URLs.`); // eslint-disable-line no-console
}
return isAllowed ? url : "";
}
================================================
FILE: content-src/asrouter/templates/CFR/templates/ExtensionDoorhanger.schema.json
================================================
{
"title": "ExtensionDoorhanger",
"description": "A template with a heading, addon icon, title and description. No markup allowed.",
"version": "1.0.0",
"type": "object",
"definitions": {
"plainText": {
"description": "Plain text (no HTML allowed)",
"type": "string"
},
"linkUrl": {
"description": "Target for links or buttons",
"type": "string",
"format": "uri"
}
},
"properties": {
"layout": {
"type": "string",
"description": "The layout style of the pop-over."
},
"category": {
"type": "string",
"description": "Attribute used for different groups of messages from the same provider"
},
"layout": {
"type": "string",
"description": "Attribute used for different groups of messages from the same provider",
"enum": ["short_message", "message_and_animation", "icon_and_message", "addon_recommendation"]
},
"anchor_id": {
"type": "string",
"description": "A DOM element ID that the pop-over will be anchored."
},
"bucket_id": {
"type": "string",
"description": "A bucket identifier for the addon. This is used in order to anonymize telemetry for history-sensitive targeting."
},
"skip_address_bar_notifier": {
"type": "boolean",
"description": "Skip the 'Recommend' notifier and show directly."
},
"notification_text": {
"description": "The text in the small blue chicklet that appears in the URL bar. This can be a reference to a localized string in Firefox or just a plain string.",
"oneOf": [
{
"type": "string",
"description": "Message shown in the location bar notification."
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Id of localized string for the location bar notification."
}
},
"required": ["string_id"]
}
]
},
"info_icon": {
"type": "object",
"description": "The small icon displayed in the top right corner of the pop-over. Should be 19x19px, svg or png. Defaults to a small question mark." ,
"properties": {
"label": {
"oneOf": [
{
"type": "object",
"properties": {
"attributes": {
"type": "object",
"properties": {
"tooltiptext": {
"type": "string",
"description": "Text for button tooltip used to provide information about the doorhanger."
}
},
"required": ["tooltiptext"]
}
},
"required": ["attributes"]
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Id of localized string used to provide information about the doorhanger."
}
},
"required": ["string_id"]
}
]
},
"sumo_path": {
"type": "string",
"description": "Last part of the path in the URL to the support page with the information about the doorhanger.",
"examples": ["extensionpromotions", "extensionrecommendations"]
}
}
},
"learn_more": {
"type": "string",
"description": "Last part of the path in the SUMO URL to the support page with the information about the doorhanger.",
"examples": ["extensionpromotions", "extensionrecommendations"]
},
"heading_text": {
"description": "The larger heading text displayed in the pop-over. This can be a reference to a localized string in Firefox or just a plain string.",
"oneOf": [
{
"type": "string",
"description": "The message displayed in the title of the extension doorhanger"
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string"
}
},
"required": ["string_id"],
"description": "Id of localized string for extension doorhanger title"
}
]
},
"icon": {
"description": "The icon displayed in the pop-over. Should be 32x32px or 64x64px and png/svg.",
"allOf": [
{"$ref": "#/definitions/linkUrl"},
{"description": "Icon associated with the message"}
]
},
"icon_dark_theme": {
"type": "string",
"description": "Pop-over icon, dark theme variant. Should be 32x32px or 64x64px and png/svg."
},
"icon_class": {
"type": "string",
"description": "CSS class of the pop-over icon."
},
"addon": {
"description": "Addon information including AMO URL.",
"type": "object",
"properties": {
"id": {
"allOf": [
{"$ref": "#/definitions/plainText"},
{"description": "Unique addon ID"}
]
},
"title": {
"allOf": [
{"$ref": "#/definitions/plainText"},
{"description": "Addon name"}
]
},
"author": {
"allOf": [
{"$ref": "#/definitions/plainText"},
{"description": "Addon author"}
]
},
"icon": {
"description": "The icon displayed in the pop-over. Should be 64x64px and png/svg.",
"allOf": [
{"$ref": "#/definitions/linkUrl"},
{"description": "Addon icon"}
]
},
"rating": {
"type": "number",
"minimum": 0,
"maximum": 5,
"description": "Star rating"
},
"users": {
"type": "integer",
"minimum": 0,
"description": "Installed users"
},
"amo_url": {
"allOf": [
{"$ref": "#/definitions/linkUrl"},
{"description": "Link that offers more information related to the addon."}
]
}
},
"required": ["title", "author", "icon", "amo_url"]
},
"text": {
"description": "The body text displayed in the pop-over. This can be a reference to a localized string in Firefox or just a plain string.",
"oneOf": [
{
"type": "string",
"description": "Description message of the addon."
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Id of string to localized addon description"
}
},
"required": ["string_id"]
}
]
},
"descriptionDetails": {
"description": "Additional information and steps on how to use",
"type": "object",
"properties": {
"steps": {
"description": "Array of messages or string_ids",
"type": "array",
"items": {
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Id of string to localized addon description"
}
},
"required": ["string_id"]
}
}
},
"required": ["steps"]
},
"buttons": {
"description": "The label and functionality for the buttons in the pop-over.",
"type": "object",
"properties": {
"primary": {
"type": "object",
"properties": {
"label": {
"type": "object",
"oneOf": [
{
"properties": {
"value": {
"allOf": [
{"$ref": "#/definitions/plainText"},
{"description": "Button label override used when a localized version is not available."}
]
},
"attributes": {
"type": "object",
"properties": {
"accesskey": {
"type": "string",
"description": "A single character to be used as a shortcut key for the secondary button. This should be one of the characters that appears in the button label."
}
},
"required": ["accesskey"],
"description": "Button attributes."
}
},
"required": ["value", "attributes"]
},
{
"
gitextract_p813z3cw/ ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .mcignore ├── .nvmrc ├── .prettierrc ├── .sass-lint.yml ├── .taskcluster.yml ├── .travis.yml ├── AboutNewTabService.jsm ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── aboutlibrary/ │ ├── content/ │ │ └── aboutlibrary.xhtml │ ├── jar.mn │ └── moz.build ├── bin/ │ ├── bootstrap │ ├── download-firefox-artifact │ ├── prepare-mochitests-dev │ ├── render-activity-stream-html.js │ ├── try-runner.js │ └── vendor.js ├── common/ │ ├── Actions.jsm │ ├── Dedupe.jsm │ ├── PerfService.jsm │ └── Reducers.jsm ├── components.conf ├── content-src/ │ ├── .eslintrc.js │ ├── aboutlibrary/ │ │ ├── aboutlibrary.jsx │ │ └── aboutlibrary.scss │ ├── activity-stream.jsx │ ├── asrouter/ │ │ ├── README.md │ │ ├── asrouter-content.jsx │ │ ├── components/ │ │ │ ├── Button/ │ │ │ │ ├── Button.jsx │ │ │ │ └── _Button.scss │ │ │ ├── ConditionalWrapper/ │ │ │ │ └── ConditionalWrapper.jsx │ │ │ ├── FxASignupForm/ │ │ │ │ ├── FxASignupForm.jsx │ │ │ │ └── _FxASignupForm.scss │ │ │ ├── ImpressionsWrapper/ │ │ │ │ └── ImpressionsWrapper.jsx │ │ │ ├── ModalOverlay/ │ │ │ │ ├── ModalOverlay.jsx │ │ │ │ └── _ModalOverlay.scss │ │ │ ├── RichText/ │ │ │ │ └── RichText.jsx │ │ │ └── SnippetBase/ │ │ │ ├── SnippetBase.jsx │ │ │ └── _SnippetBase.scss │ │ ├── docs/ │ │ │ ├── debugging-docs.md │ │ │ ├── experiment-guide.md │ │ │ ├── targeting-attributes.md │ │ │ ├── targeting-guide.md │ │ │ └── user-actions.md │ │ ├── rich-text-strings.js │ │ ├── schemas/ │ │ │ ├── message-format.md │ │ │ ├── panel/ │ │ │ │ └── cfr-fxa-bookmark.schema.json │ │ │ └── provider-response.schema.json │ │ ├── template-utils.js │ │ └── templates/ │ │ ├── CFR/ │ │ │ └── templates/ │ │ │ └── ExtensionDoorhanger.schema.json │ │ ├── EOYSnippet/ │ │ │ ├── EOYSnippet.jsx │ │ │ ├── EOYSnippet.schema.json │ │ │ └── _EOYSnippet.scss │ │ ├── FXASignupSnippet/ │ │ │ ├── FXASignupSnippet.jsx │ │ │ └── FXASignupSnippet.schema.json │ │ ├── FirstRun/ │ │ │ ├── FirstRun.jsx │ │ │ ├── Interrupt.jsx │ │ │ ├── Triplets.jsx │ │ │ └── addUtmParams.js │ │ ├── FullPageInterrupt/ │ │ │ ├── FullPageInterrupt.jsx │ │ │ └── _FullPageInterrupt.scss │ │ ├── NewsletterSnippet/ │ │ │ ├── NewsletterSnippet.jsx │ │ │ └── NewsletterSnippet.schema.json │ │ ├── OnboardingMessage/ │ │ │ ├── OnboardingMessage.jsx │ │ │ ├── OnboardingMessage.schema.json │ │ │ ├── ToolbarBadgeMessage.schema.json │ │ │ ├── UpdateAction.schema.json │ │ │ ├── WhatsNewMessage.schema.json │ │ │ └── _OnboardingMessage.scss │ │ ├── ReturnToAMO/ │ │ │ ├── ReturnToAMO.jsx │ │ │ └── _ReturnToAMO.scss │ │ ├── SendToDeviceSnippet/ │ │ │ ├── SendToDeviceSnippet.jsx │ │ │ ├── SendToDeviceSnippet.schema.json │ │ │ └── isEmailOrPhoneNumber.js │ │ ├── SimpleBelowSearchSnippet/ │ │ │ ├── SimpleBelowSearchSnippet.jsx │ │ │ ├── SimpleBelowSearchSnippet.schema.json │ │ │ └── _SimpleBelowSearchSnippet.scss │ │ ├── SimpleSnippet/ │ │ │ ├── SimpleSnippet.jsx │ │ │ ├── SimpleSnippet.schema.json │ │ │ └── _SimpleSnippet.scss │ │ ├── SubmitFormSnippet/ │ │ │ ├── SubmitFormSnippet.jsx │ │ │ ├── SubmitFormSnippet.schema.json │ │ │ └── _SubmitFormSnippet.scss │ │ ├── Trailhead/ │ │ │ ├── Trailhead.jsx │ │ │ └── _Trailhead.scss │ │ └── template-manifest.jsx │ ├── components/ │ │ ├── A11yLinkButton/ │ │ │ ├── A11yLinkButton.jsx │ │ │ └── _A11yLinkButton.scss │ │ ├── ASRouterAdmin/ │ │ │ ├── ASRouterAdmin.jsx │ │ │ ├── ASRouterAdmin.scss │ │ │ └── SimpleHashRouter.jsx │ │ ├── Base/ │ │ │ ├── Base.jsx │ │ │ └── _Base.scss │ │ ├── Card/ │ │ │ ├── Card.jsx │ │ │ ├── _Card.scss │ │ │ └── types.js │ │ ├── CollapsibleSection/ │ │ │ ├── CollapsibleSection.jsx │ │ │ └── _CollapsibleSection.scss │ │ ├── ComponentPerfTimer/ │ │ │ └── ComponentPerfTimer.jsx │ │ ├── ConfirmDialog/ │ │ │ ├── ConfirmDialog.jsx │ │ │ └── _ConfirmDialog.scss │ │ ├── ContextMenu/ │ │ │ ├── ContextMenu.jsx │ │ │ ├── ContextMenuButton.jsx │ │ │ └── _ContextMenu.scss │ │ ├── DiscoveryStreamBase/ │ │ │ ├── DiscoveryStreamBase.jsx │ │ │ └── _DiscoveryStreamBase.scss │ │ ├── DiscoveryStreamComponents/ │ │ │ ├── CardGrid/ │ │ │ │ ├── CardGrid.jsx │ │ │ │ └── _CardGrid.scss │ │ │ ├── DSCard/ │ │ │ │ ├── DSCard.jsx │ │ │ │ └── _DSCard.scss │ │ │ ├── DSContextFooter/ │ │ │ │ ├── DSContextFooter.jsx │ │ │ │ └── _DSContextFooter.scss │ │ │ ├── DSDismiss/ │ │ │ │ ├── DSDismiss.jsx │ │ │ │ └── _DSDismiss.scss │ │ │ ├── DSEmptyState/ │ │ │ │ ├── DSEmptyState.jsx │ │ │ │ └── _DSEmptyState.scss │ │ │ ├── DSImage/ │ │ │ │ ├── DSImage.jsx │ │ │ │ └── _DSImage.scss │ │ │ ├── DSLinkMenu/ │ │ │ │ ├── DSLinkMenu.jsx │ │ │ │ └── _DSLinkMenu.scss │ │ │ ├── DSMessage/ │ │ │ │ ├── DSMessage.jsx │ │ │ │ └── _DSMessage.scss │ │ │ ├── DSPrivacyModal/ │ │ │ │ ├── DSPrivacyModal.jsx │ │ │ │ └── _DSPrivacyModal.scss │ │ │ ├── DSTextPromo/ │ │ │ │ ├── DSTextPromo.jsx │ │ │ │ └── _DSTextPromo.scss │ │ │ ├── Hero/ │ │ │ │ ├── Hero.jsx │ │ │ │ └── _Hero.scss │ │ │ ├── Highlights/ │ │ │ │ ├── Highlights.jsx │ │ │ │ └── _Highlights.scss │ │ │ ├── HorizontalRule/ │ │ │ │ ├── HorizontalRule.jsx │ │ │ │ └── _HorizontalRule.scss │ │ │ ├── List/ │ │ │ │ ├── List.jsx │ │ │ │ └── _List.scss │ │ │ ├── Navigation/ │ │ │ │ ├── Navigation.jsx │ │ │ │ └── _Navigation.scss │ │ │ ├── SafeAnchor/ │ │ │ │ └── SafeAnchor.jsx │ │ │ ├── SectionTitle/ │ │ │ │ ├── SectionTitle.jsx │ │ │ │ └── _SectionTitle.scss │ │ │ └── TopSites/ │ │ │ ├── TopSites.jsx │ │ │ └── _TopSites.scss │ │ ├── DiscoveryStreamImpressionStats/ │ │ │ ├── ImpressionStats.jsx │ │ │ └── _ImpressionStats.scss │ │ ├── ErrorBoundary/ │ │ │ ├── ErrorBoundary.jsx │ │ │ └── _ErrorBoundary.scss │ │ ├── FluentOrText/ │ │ │ └── FluentOrText.jsx │ │ ├── LinkMenu/ │ │ │ └── LinkMenu.jsx │ │ ├── MoreRecommendations/ │ │ │ ├── MoreRecommendations.jsx │ │ │ └── _MoreRecommendations.scss │ │ ├── PocketLoggedInCta/ │ │ │ ├── PocketLoggedInCta.jsx │ │ │ └── _PocketLoggedInCta.scss │ │ ├── Search/ │ │ │ ├── Search.jsx │ │ │ └── _Search.scss │ │ ├── SectionMenu/ │ │ │ └── SectionMenu.jsx │ │ ├── Sections/ │ │ │ ├── Sections.jsx │ │ │ └── _Sections.scss │ │ ├── TopSites/ │ │ │ ├── SearchShortcutsForm.jsx │ │ │ ├── TopSite.jsx │ │ │ ├── TopSiteForm.jsx │ │ │ ├── TopSiteFormInput.jsx │ │ │ ├── TopSites.jsx │ │ │ ├── TopSitesConstants.js │ │ │ └── _TopSites.scss │ │ └── Topics/ │ │ ├── Topics.jsx │ │ └── _Topics.scss │ ├── lib/ │ │ ├── constants.js │ │ ├── detect-user-session-start.js │ │ ├── init-store.js │ │ ├── link-menu-options.js │ │ ├── screenshot-utils.js │ │ ├── section-menu-options.js │ │ └── selectLayoutRender.js │ └── styles/ │ ├── _activity-stream.scss │ ├── _icons.scss │ ├── _mixins.scss │ ├── _normalize.scss │ ├── _theme.scss │ ├── _variables.scss │ ├── activity-stream-linux.scss │ ├── activity-stream-mac.scss │ └── activity-stream-windows.scss ├── contributing.md ├── data/ │ └── content/ │ └── tippytop/ │ └── top_sites.json ├── docs/ │ ├── ISSUE_TEMPLATE.md │ ├── index.rst │ └── v2-system-addon/ │ ├── 1.GETTING_STARTED.md │ ├── data_dictionary.md │ ├── data_events.md │ ├── geo_locale.md │ ├── mochitests.md │ ├── preferences.md │ ├── remote_cfr.md │ ├── sections.md │ ├── telemetry.md │ ├── test-merges.md │ ├── tippytop.md │ └── unit_testing_guide.md ├── hooks/ │ ├── post-commit │ └── pre-commit ├── jar.mn ├── karma.mc.config.js ├── lib/ │ ├── ASRouter.jsm │ ├── ASRouterFeed.jsm │ ├── ASRouterPreferences.jsm │ ├── ASRouterTargeting.jsm │ ├── ASRouterTriggerListeners.jsm │ ├── AboutPreferences.jsm │ ├── ActivityStream.jsm │ ├── ActivityStreamMessageChannel.jsm │ ├── ActivityStreamPrefs.jsm │ ├── ActivityStreamStorage.jsm │ ├── BookmarkPanelHub.jsm │ ├── CFRMessageProvider.jsm │ ├── CFRPageActions.jsm │ ├── DiscoveryStreamFeed.jsm │ ├── DownloadsManager.jsm │ ├── FaviconFeed.jsm │ ├── FilterAdult.jsm │ ├── HighlightsFeed.jsm │ ├── LinksCache.jsm │ ├── NaiveBayesTextTagger.jsm │ ├── NewTabInit.jsm │ ├── NmfTextTagger.jsm │ ├── OnboardingMessageProvider.jsm │ ├── PanelTestProvider.jsm │ ├── PersistentCache.jsm │ ├── PersonalityProvider.jsm │ ├── PlacesFeed.jsm │ ├── PrefsFeed.jsm │ ├── RecipeExecutor.jsm │ ├── RemoteL10n.jsm │ ├── Screenshots.jsm │ ├── SearchShortcuts.jsm │ ├── SectionsManager.jsm │ ├── ShortURL.jsm │ ├── SiteClassifier.jsm │ ├── SnippetsTestMessageProvider.jsm │ ├── Store.jsm │ ├── SystemTickFeed.jsm │ ├── TelemetryFeed.jsm │ ├── TippyTopProvider.jsm │ ├── Tokenize.jsm │ ├── ToolbarBadgeHub.jsm │ ├── ToolbarPanelHub.jsm │ ├── TopSitesFeed.jsm │ ├── TopStoriesFeed.jsm │ ├── UTEventReporting.jsm │ └── UserDomainAffinityProvider.jsm ├── loaders/ │ └── inject-loader.js ├── mochitest.sh ├── moz.build ├── nsIAboutNewTabService.idl ├── package.json ├── ping-centre/ │ └── PingCentre.jsm ├── test/ │ ├── .eslintrc.js │ ├── browser/ │ │ ├── blue_page.html │ │ ├── browser.ini │ │ ├── browser_aboutwelcome.js │ │ ├── browser_as_load_location.js │ │ ├── browser_as_render.js │ │ ├── browser_asrouter_bookmarkpanel.js │ │ ├── browser_asrouter_cfr.js │ │ ├── browser_asrouter_snippets.js │ │ ├── browser_asrouter_targeting.js │ │ ├── browser_asrouter_toolbarbadge.js │ │ ├── browser_asrouter_trigger_listeners.js │ │ ├── browser_asrouter_whatsnewpanel.js │ │ ├── browser_discovery_render.js │ │ ├── browser_discovery_styles.js │ │ ├── browser_enabled_newtabpage.js │ │ ├── browser_getScreenshots.js │ │ ├── browser_highlights_section.js │ │ ├── browser_newtab_overrides.js │ │ ├── browser_onboarding_rtamo.js │ │ ├── browser_topsites_contextMenu_options.js │ │ ├── browser_topsites_section.js │ │ ├── head.js │ │ └── red_page.html │ ├── schemas/ │ │ └── pings.js │ ├── unit/ │ │ ├── asrouter/ │ │ │ ├── ASRouter.test.js │ │ │ ├── ASRouterFeed.test.js │ │ │ ├── ASRouterPreferences.test.js │ │ │ ├── ASRouterTargeting.test.js │ │ │ ├── ASRouterTriggerListeners.test.js │ │ │ ├── CFRMessageProvider.test.js │ │ │ ├── CFRPageActions.test.js │ │ │ ├── MessageLoaderUtils.test.js │ │ │ ├── ModalOverlay.test.jsx │ │ │ ├── PanelTestProvider.test.js │ │ │ ├── RemoteL10n.test.js │ │ │ ├── RichText.test.jsx │ │ │ ├── SnippetsTestMessageProvider.test.js │ │ │ ├── TargetingDocs.test.js │ │ │ ├── asrouter-content.test.jsx │ │ │ ├── compatibility-reference/ │ │ │ │ ├── fx57-compat.test.js │ │ │ │ └── snippets-fx57.js │ │ │ ├── constants.js │ │ │ ├── schemas/ │ │ │ │ └── panel/ │ │ │ │ └── cfr-fxa-bookmark.schema.test.js │ │ │ ├── template-utils.test.js │ │ │ └── templates/ │ │ │ ├── EOYSnippet.test.jsx │ │ │ ├── ExtensionDoorhanger.test.jsx │ │ │ ├── FXASignupSnippet.test.jsx │ │ │ ├── FirstRun.test.jsx │ │ │ ├── FullPageInterrupt.test.jsx │ │ │ ├── FxASignupForm.test.jsx │ │ │ ├── Interrupt.test.jsx │ │ │ ├── NewsletterSnippet.test.jsx │ │ │ ├── OnboardingMessage.test.jsx │ │ │ ├── SendToDeviceSnippet.test.jsx │ │ │ ├── SimpleBelowSearchSnippet.test.jsx │ │ │ ├── SimpleSnippet.test.jsx │ │ │ ├── SubmitFormSnippet.test.jsx │ │ │ ├── Trailhead.test.jsx │ │ │ ├── Triplets.test.jsx │ │ │ └── isEmailOrPhoneNumber.test.js │ │ ├── common/ │ │ │ ├── Actions.test.js │ │ │ ├── Dedupe.test.js │ │ │ ├── PerfService.test.js │ │ │ └── Reducers.test.js │ │ ├── content-src/ │ │ │ ├── components/ │ │ │ │ ├── ASRouterAdmin.test.jsx │ │ │ │ ├── Base.test.jsx │ │ │ │ ├── Card.test.jsx │ │ │ │ ├── CollapsibleSection.test.jsx │ │ │ │ ├── ComponentPerfTimer.test.jsx │ │ │ │ ├── ConfirmDialog.test.jsx │ │ │ │ ├── ContextMenu.test.jsx │ │ │ │ ├── DiscoveryStreamBase.test.jsx │ │ │ │ ├── DiscoveryStreamComponents/ │ │ │ │ │ ├── CardGrid.test.jsx │ │ │ │ │ ├── DSCard.test.jsx │ │ │ │ │ ├── DSContextFooter.test.jsx │ │ │ │ │ ├── DSDismiss.test.jsx │ │ │ │ │ ├── DSEmptyState.test.jsx │ │ │ │ │ ├── DSImage.test.jsx │ │ │ │ │ ├── DSLinkMenu.test.jsx │ │ │ │ │ ├── DSMessage.test.jsx │ │ │ │ │ ├── DSPrivacyModal.test.jsx │ │ │ │ │ ├── DSTextPromo.test.jsx │ │ │ │ │ ├── Hero.test.jsx │ │ │ │ │ ├── Highlights.test.jsx │ │ │ │ │ ├── HorizontalRule.test.jsx │ │ │ │ │ ├── ImpressionStats.test.jsx │ │ │ │ │ ├── List.test.jsx │ │ │ │ │ ├── Navigation.test.jsx │ │ │ │ │ ├── SafeAnchor.test.jsx │ │ │ │ │ ├── SectionTitle.test.jsx │ │ │ │ │ └── TopSites.test.jsx │ │ │ │ ├── ErrorBoundary.test.jsx │ │ │ │ ├── FluentOrText.test.jsx │ │ │ │ ├── LinkMenu.test.jsx │ │ │ │ ├── MoreRecommendations.test.jsx │ │ │ │ ├── PocketLoggedInCta.test.jsx │ │ │ │ ├── ReturnToAMO.test.jsx │ │ │ │ ├── Search.test.jsx │ │ │ │ ├── SectionMenu.test.jsx │ │ │ │ ├── Sections.test.jsx │ │ │ │ ├── TopSites/ │ │ │ │ │ └── SearchShortcutsForm.test.jsx │ │ │ │ ├── TopSites.test.jsx │ │ │ │ ├── Topics.test.jsx │ │ │ │ └── addUtmParams.test.js │ │ │ └── lib/ │ │ │ ├── detect-user-session-start.test.js │ │ │ ├── init-store.test.js │ │ │ ├── screenshot-utils.test.js │ │ │ └── selectLayoutRender.test.js │ │ ├── lib/ │ │ │ ├── AboutPreferences.test.js │ │ │ ├── ActivityStream.test.js │ │ │ ├── ActivityStreamMessageChannel.test.js │ │ │ ├── ActivityStreamPrefs.test.js │ │ │ ├── ActivityStreamStorage.test.js │ │ │ ├── BookmarkPanelHub.test.js │ │ │ ├── DiscoveryStreamFeed.test.js │ │ │ ├── DownloadsManager.test.js │ │ │ ├── FaviconFeed.test.js │ │ │ ├── FilterAdult.test.js │ │ │ ├── HighlightsFeed.test.js │ │ │ ├── LinksCache.test.js │ │ │ ├── NaiveBayesTextTagger.test.js │ │ │ ├── NewTabInit.test.js │ │ │ ├── NmfTextTagger.test.js │ │ │ ├── PersistentCache.test.js │ │ │ ├── PersonalityProvider.test.js │ │ │ ├── PlacesFeed.test.js │ │ │ ├── PrefsFeed.test.js │ │ │ ├── RecipeExecutor.test.js │ │ │ ├── Screenshots.test.js │ │ │ ├── SectionsManager.test.js │ │ │ ├── ShortUrl.test.js │ │ │ ├── SiteClassifier.test.js │ │ │ ├── Store.test.js │ │ │ ├── SystemTickFeed.test.js │ │ │ ├── TelemetryFeed.test.js │ │ │ ├── TippyTopProvider.test.js │ │ │ ├── Tokenize.test.js │ │ │ ├── ToolbarBadgeHub.test.js │ │ │ ├── ToolbarPanelHub.test.js │ │ │ ├── TopSitesFeed.test.js │ │ │ ├── TopStoriesFeed.test.js │ │ │ ├── UTEventReporting.test.js │ │ │ └── UserDomainAffinityProvider.test.js │ │ ├── ping-centre/ │ │ │ └── PingCentre.test.js │ │ ├── unit-entry.js │ │ └── utils.js │ └── xpcshell/ │ ├── test_ASRouterTargeting_attribution.js │ ├── test_AboutNewTabService.js │ └── xpcshell.ini ├── vendor/ │ ├── PROP_TYPES_LICENSE │ ├── REACT_AND_REACT_DOM_LICENSE │ ├── REACT_REDUX_LICENSE │ ├── REACT_TRANSITION_GROUP_LICENSE │ ├── REDUX_LICENSE │ ├── Redux.jsm │ ├── prop-types.js │ ├── react-dev.js │ ├── react-dom-dev.js │ ├── react-dom.js │ ├── react-redux.js │ ├── react-transition-group.js │ ├── react.js │ └── redux.js ├── webpack.aboutlibrary.config.js ├── webpack.system-addon.config.js └── yamscripts.yml
SYMBOL INDEX (2173 symbols across 180 files)
FILE: bin/render-activity-stream-html.js
constant DEFAULT_OPTIONS (line 12) | const DEFAULT_OPTIONS = {
function templateHTML (line 27) | function templateHTML(options) {
function writeFiles (line 83) | function writeFiles(destPath, filesMap, options) {
constant STATIC_FILES (line 90) | const STATIC_FILES = new Map([
function main (line 107) | function main() {
FILE: bin/try-runner.js
function logErrors (line 18) | function logErrors(tool, errors) {
function execOut (line 25) | function execOut(...args) {
function logStart (line 46) | function logStart(name) {
function karma (line 50) | function karma() {
function sasslint (line 98) | function sasslint() {
FILE: content-src/aboutlibrary/aboutlibrary.jsx
class LibraryRouter (line 4) | class LibraryRouter extends React.PureComponent {
method render (line 5) | render() {
FILE: content-src/asrouter/asrouter-content.jsx
constant INCOMING_MESSAGE_NAME (line 20) | const INCOMING_MESSAGE_NAME = "ASRouter:parent-to-child";
constant OUTGOING_MESSAGE_NAME (line 21) | const OUTGOING_MESSAGE_NAME = "ASRouter:child-to-parent";
constant TEMPLATES_ABOVE_PAGE (line 22) | const TEMPLATES_ABOVE_PAGE = [
constant FIRST_RUN_TEMPLATES (line 28) | const FIRST_RUN_TEMPLATES = TEMPLATES_ABOVE_PAGE;
constant TEMPLATES_BELOW_SEARCH (line 29) | const TEMPLATES_BELOW_SEARCH = ["simple_below_search_snippet"];
method addListener (line 32) | addListener(listener) {
method removeListener (line 37) | removeListener(listener) {
method sendMessage (line 42) | sendMessage(action) {
method blockById (line 47) | blockById(id, options) {
method dismissById (line 53) | dismissById(id) {
method executeAction (line 56) | executeAction(button_action) {
method unblockById (line 62) | unblockById(id) {
method unblockBundle (line 65) | unblockBundle(bundle) {
method overrideMessage (line 68) | overrideMessage(id) {
method sendTelemetry (line 71) | sendTelemetry(ping) {
method getPreviewEndpoint (line 77) | getPreviewEndpoint() {
method getPreviewTheme (line 94) | getPreviewTheme() {
function shouldSendImpressionOnUpdate (line 102) | function shouldSendImpressionOnUpdate(nextProps, prevProps) {
class ASRouterUISurface (line 109) | class ASRouterUISurface extends React.PureComponent {
method constructor (line 110) | constructor(props) {
method fetchFlowParams (line 130) | async fetchFlowParams(params = {}) {
method sendUserActionTelemetry (line 173) | sendUserActionTelemetry(extraProps = {}) {
method sendImpression (line 184) | sendImpression(extraProps) {
method sendClick (line 196) | sendClick(event) {
method onBlockById (line 221) | onBlockById(id) {
method onDismissById (line 225) | onDismissById(id) {
method clearMessage (line 229) | clearMessage(id) {
method onMessageFromParent (line 247) | onMessageFromParent({ data: action }) {
method requestMessage (line 272) | requestMessage(endpoint) {
method componentWillMount (line 290) | componentWillMount() {
method componentWillUnmount (line 303) | componentWillUnmount() {
method getMonitorUrl (line 307) | async getMonitorUrl({ url, flowRequestParams = {} }) {
method onUserAction (line 321) | async onUserAction(action) {
method renderSnippets (line 333) | renderSnippets() {
method renderPreviewBanner (line 365) | renderPreviewBanner() {
method renderFirstRun (line 378) | renderFirstRun() {
method render (line 409) | render() {
FILE: content-src/asrouter/components/Button/Button.jsx
constant ALLOWED_STYLE_TAGS (line 7) | const ALLOWED_STYLE_TAGS = ["color", "backgroundColor"];
FILE: content-src/asrouter/components/FxASignupForm/FxASignupForm.jsx
class FxASignupForm (line 12) | class FxASignupForm extends React.PureComponent {
method constructor (line 13) | constructor(props) {
method email (line 25) | get email() {
method onSubmit (line 31) | onSubmit(event) {
method handleSignIn (line 50) | handleSignIn(event) {
method componentDidMount (line 55) | componentDidMount() {
method onInputChange (line 62) | onInputChange(e) {
method onInputInvalid (line 69) | onInputInvalid(e) {
method render (line 77) | render() {
FILE: content-src/asrouter/components/ImpressionsWrapper/ImpressionsWrapper.jsx
constant VISIBLE (line 7) | const VISIBLE = "visible";
constant VISIBILITY_CHANGE_EVENT (line 8) | const VISIBILITY_CHANGE_EVENT = "visibilitychange";
class ImpressionsWrapper (line 13) | class ImpressionsWrapper extends React.PureComponent {
method sendImpressionOrAddListener (line 17) | sendImpressionOrAddListener() {
method componentWillUnmount (line 47) | componentWillUnmount() {
method componentDidMount (line 56) | componentDidMount() {
method componentDidUpdate (line 62) | componentDidUpdate(prevProps) {
method render (line 68) | render() {
FILE: content-src/asrouter/components/ModalOverlay/ModalOverlay.jsx
class ModalOverlayWrapper (line 7) | class ModalOverlayWrapper extends React.PureComponent {
method constructor (line 8) | constructor(props) {
method onKeyDown (line 15) | onKeyDown(event) {
method componentWillMount (line 21) | componentWillMount() {
method componentWillUnmount (line 34) | componentWillUnmount() {
method render (line 46) | render() {
class ModalOverlay (line 81) | class ModalOverlay extends React.PureComponent {
method render (line 82) | render() {
FILE: content-src/asrouter/components/RichText/RichText.jsx
constant ALLOWED_TAGS (line 11) | const ALLOWED_TAGS = {
function convertLinks (line 24) | function convertLinks(
function RichText (line 60) | function RichText(props) {
FILE: content-src/asrouter/components/SnippetBase/SnippetBase.jsx
class SnippetBase (line 8) | class SnippetBase extends React.PureComponent {
method constructor (line 9) | constructor(props) {
method componentDidMount (line 19) | componentDidMount() {
method componentWillUnmount (line 32) | componentWillUnmount() {
method setBlockButtonRef (line 45) | setBlockButtonRef(element) {
method onBlockButtonMouseEnter (line 49) | onBlockButtonMouseEnter() {
method onBlockButtonMouseLeave (line 53) | onBlockButtonMouseLeave() {
method onBlockClicked (line 57) | onBlockClicked() {
method onDismissClicked (line 68) | onDismissClicked() {
method renderDismissButton (line 79) | renderDismissButton() {
method render (line 109) | render() {
FILE: content-src/asrouter/rich-text-strings.js
constant RICH_TEXT_CONFIG (line 12) | const RICH_TEXT_CONFIG = {
constant RICH_TEXT_KEYS (line 22) | const RICH_TEXT_KEYS = Object.keys(RICH_TEXT_CONFIG);
function generateBundles (line 30) | function generateBundles(content) {
FILE: content-src/asrouter/template-utils.js
function safeURI (line 5) | function safeURI(url) {
FILE: content-src/asrouter/templates/EOYSnippet/EOYSnippet.jsx
class EOYSnippetBase (line 9) | class EOYSnippetBase extends React.PureComponent {
method constructor (line 10) | constructor(props) {
method setFrequencyValue (line 19) | setFrequencyValue() {
method handleSubmit (line 26) | handleSubmit(event) {
method renderDonations (line 35) | renderDonations() {
method render (line 120) | render() {
FILE: content-src/asrouter/templates/FirstRun/FirstRun.jsx
constant TRANSITION_LENGTH (line 11) | const TRANSITION_LENGTH = 500;
constant FLUENT_FILES (line 13) | const FLUENT_FILES = [
method selectInterruptAndTriplets (line 21) | selectInterruptAndTriplets(message = {}, interruptCleared) {
method addFluent (line 48) | addFluent(document) {
class FirstRun (line 57) | class FirstRun extends React.PureComponent {
method constructor (line 58) | constructor(props) {
method getDerivedStateFromProps (line 93) | static getDerivedStateFromProps(props, state) {
method fetchFlowParams (line 135) | async fetchFlowParams() {
method removeHideMain (line 150) | removeHideMain() {
method componentDidMount (line 157) | componentDidMount() {
method componentDidUpdate (line 162) | componentDidUpdate() {
method closeInterrupt (line 168) | closeInterrupt() {
method closeTriplets (line 176) | closeTriplets() {
method render (line 185) | render() {
FILE: content-src/asrouter/templates/FirstRun/Interrupt.jsx
class Interrupt (line 12) | class Interrupt extends React.PureComponent {
method render (line 13) | render() {
FILE: content-src/asrouter/templates/FirstRun/Triplets.jsx
class Triplets (line 9) | class Triplets extends React.PureComponent {
method constructor (line 10) | constructor(props) {
method componentWillMount (line 16) | componentWillMount() {
method componentWillUnmount (line 20) | componentWillUnmount() {
method onCardAction (line 24) | onCardAction(action, message) {
method onHideContainer (line 48) | onHideContainer() {
method render (line 59) | render() {
FILE: content-src/asrouter/templates/FirstRun/addUtmParams.js
constant BASE_PARAMS (line 8) | const BASE_PARAMS = {
function addUtmParams (line 20) | function addUtmParams(url, utmTerm) {
FILE: content-src/asrouter/templates/FullPageInterrupt/FullPageInterrupt.jsx
class FullPageInterrupt (line 80) | class FullPageInterrupt extends React.PureComponent {
method constructor (line 81) | constructor(props) {
method componentWillMount (line 87) | componentWillMount() {
method componentDidMount (line 91) | componentDidMount() {
method removeOverlay (line 98) | removeOverlay() {
method onCardAction (line 110) | onCardAction(action, message) {
method render (line 135) | render() {
FILE: content-src/asrouter/templates/OnboardingMessage/OnboardingMessage.jsx
class OnboardingCard (line 7) | class OnboardingCard extends React.PureComponent {
method constructor (line 8) | constructor(props) {
method onClick (line 13) | onClick() {
method render (line 24) | render() {
FILE: content-src/asrouter/templates/ReturnToAMO/ReturnToAMO.jsx
constant ICON_ALT_TEXT (line 9) | const ICON_ALT_TEXT = "";
class ReturnToAMO (line 11) | class ReturnToAMO extends React.PureComponent {
method constructor (line 12) | constructor(props) {
method componentWillMount (line 18) | componentWillMount() {
method componentDidMount (line 22) | componentDidMount() {
method onClickAddExtension (line 33) | onClickAddExtension() {
method onBlockButton (line 41) | onBlockButton() {
method renderText (line 54) | renderText() {
method render (line 72) | render() {
FILE: content-src/asrouter/templates/SendToDeviceSnippet/SendToDeviceSnippet.jsx
function validateInput (line 10) | function validateInput(value, content) {
function processFormData (line 15) | function processFormData(input, message) {
function addDefaultValues (line 40) | function addDefaultValues(props) {
FILE: content-src/asrouter/templates/SendToDeviceSnippet/isEmailOrPhoneNumber.js
function isEmailOrPhoneNumber (line 11) | function isEmailOrPhoneNumber(val, content) {
FILE: content-src/asrouter/templates/SimpleBelowSearchSnippet/SimpleBelowSearchSnippet.jsx
constant DEFAULT_ICON_PATH (line 11) | const DEFAULT_ICON_PATH = "chrome://branding/content/icon64.png";
constant ICON_ALT_TEXT (line 13) | const ICON_ALT_TEXT = "";
class SimpleBelowSearchSnippet (line 15) | class SimpleBelowSearchSnippet extends React.PureComponent {
method constructor (line 16) | constructor(props) {
method renderText (line 21) | renderText() {
method renderTitle (line 34) | renderTitle() {
method onButtonClick (line 44) | async onButtonClick() {
method _shouldRenderButton (line 63) | _shouldRenderButton() {
method renderButton (line 71) | renderButton() {
method render (line 88) | render() {
FILE: content-src/asrouter/templates/SimpleSnippet/SimpleSnippet.jsx
constant DEFAULT_ICON_PATH (line 12) | const DEFAULT_ICON_PATH = "chrome://branding/content/icon64.png";
constant ICON_ALT_TEXT (line 14) | const ICON_ALT_TEXT = "";
class SimpleSnippet (line 16) | class SimpleSnippet extends React.PureComponent {
method constructor (line 17) | constructor(props) {
method onButtonClick (line 22) | onButtonClick() {
method _shouldRenderButton (line 41) | _shouldRenderButton() {
method renderTitle (line 49) | renderTitle() {
method renderTitleIcon (line 60) | renderTitleIcon() {
method renderButton (line 83) | renderButton() {
method renderText (line 100) | renderText() {
method wrapSectionHeader (line 113) | wrapSectionHeader(url) {
method wrapSnippetContent (line 119) | wrapSnippetContent(children) {
method renderSectionHeader (line 123) | renderSectionHeader() {
method render (line 162) | render() {
FILE: content-src/asrouter/templates/SubmitFormSnippet/SubmitFormSnippet.jsx
constant ICON_ALT_TEXT (line 13) | const ICON_ALT_TEXT = "";
class SubmitFormSnippet (line 15) | class SubmitFormSnippet extends React.PureComponent {
method constructor (line 16) | constructor(props) {
method handleSubmitAttempt (line 31) | handleSubmitAttempt() {
method handleSubmit (line 37) | async handleSubmit(event) {
method expandSnippet (line 101) | expandSnippet() {
method renderHiddenFormInputs (line 115) | renderHiddenFormInputs() {
method renderDisclaimer (line 127) | renderDisclaimer() {
method renderFormPrivacyNotice (line 146) | renderFormPrivacyNotice() {
method renderSignupSubmitted (line 173) | renderSignupSubmitted() {
method onInputChange (line 201) | onInputChange(event) {
method renderInput (line 212) | renderInput() {
method renderSignupView (line 229) | renderSignupView() {
method getFirstSceneContent (line 291) | getFirstSceneContent() {
method render (line 300) | render() {
FILE: content-src/asrouter/templates/Trailhead/Trailhead.jsx
constant FOCUSABLE_SELECTOR (line 12) | const FOCUSABLE_SELECTOR = [
class Trailhead (line 22) | class Trailhead extends React.PureComponent {
method constructor (line 23) | constructor(props) {
method dialog (line 29) | get dialog() {
method componentDidMount (line 33) | componentDidMount() {
method onStartBlur (line 43) | onStartBlur(event) {
method closeModal (line 57) | closeModal(ev) {
method _getFormInfo (line 78) | _getFormInfo() {
method render (line 83) | render() {
FILE: content-src/components/A11yLinkButton/A11yLinkButton.jsx
function A11yLinkButton (line 7) | function A11yLinkButton(props) {
FILE: content-src/components/ASRouterAdmin/ASRouterAdmin.jsx
function relativeTime (line 18) | function relativeTime(timestamp) {
constant LAYOUT_VARIANTS (line 36) | const LAYOUT_VARIANTS = {
class ToggleStoryButton (line 44) | class ToggleStoryButton extends React.PureComponent {
method constructor (line 45) | constructor(props) {
method handleClick (line 50) | handleClick() {
method render (line 54) | render() {
class TogglePrefCheckbox (line 59) | class TogglePrefCheckbox extends React.PureComponent {
method constructor (line 60) | constructor(props) {
method onChange (line 65) | onChange(event) {
method render (line 69) | render() {
class DiscoveryStreamAdmin (line 83) | class DiscoveryStreamAdmin extends React.PureComponent {
method constructor (line 84) | constructor(props) {
method setConfigValue (line 96) | setConfigValue(name, value) {
method restorePrefDefaults (line 105) | restorePrefDefaults(event) {
method expireCache (line 113) | expireCache() {
method changeEndpointVariant (line 123) | changeEndpointVariant(event) {
method renderComponent (line 136) | renderComponent(width, component) {
method isCurrentVariant (line 154) | isCurrentVariant(id) {
method renderFeedData (line 160) | renderFeedData(url) {
method renderFeedsData (line 175) | renderFeedsData() {
method renderSpocs (line 184) | renderSpocs() {
method onStoryToggle (line 219) | onStoryToggle(story) {
method renderStoryData (line 229) | renderStoryData(story) {
method renderFeed (line 249) | renderFeed(feed) {
method render (line 272) | render() {
class ASRouterAdminInner (line 355) | class ASRouterAdminInner extends React.PureComponent {
method constructor (line 356) | constructor(props) {
method onMessage (line 392) | onMessage({ data: action }) {
method componentWillMount (line 409) | componentWillMount() {
method componentWillUnmount (line 418) | componentWillUnmount() {
method findOtherBundledMessagesOfSameTemplate (line 422) | findOtherBundledMessagesOfSameTemplate(template) {
method handleBlock (line 428) | handleBlock(msg) {
method handleUnblock (line 437) | handleUnblock(msg) {
method handleOverride (line 446) | handleOverride(id) {
method expireCache (line 450) | expireCache() {
method resetPref (line 454) | resetPref() {
method handleExpressionEval (line 458) | handleExpressionEval() {
method onChangeTargetingParameters (line 473) | onChangeTargetingParameters(event) {
method handleEnabledToggle (line 497) | handleEnabledToggle(event) {
method handleUserPrefToggle (line 531) | handleUserPrefToggle(event) {
method onChangeMessageFilter (line 540) | onChangeMessageFilter(event) {
method onCopyTargetingParams (line 545) | onCopyTargetingParams(event) {
method onPasteTargetingParams (line 571) | onPasteTargetingParams(event) {
method onNewTargetingParams (line 578) | onNewTargetingParams(event) {
method renderMessageItem (line 592) | renderMessageItem(msg) {
method renderMessages (line 635) | renderMessages() {
method renderMessageFilter (line 652) | renderMessageFilter() {
method renderTableHead (line 676) | renderTableHead() {
method renderProviders (line 690) | renderProviders() {
method renderPasteModal (line 780) | renderPasteModal() {
method renderTargetingParameters (line 809) | renderTargetingParameters() {
method onChangeAttributionParameters (line 917) | onChangeAttributionParameters(event) {
method setAttribution (line 928) | setAttribution(e) {
method renderPocketStory (line 935) | renderPocketStory(story) {
method renderPocketStories (line 950) | renderPocketStories() {
method renderDiscoveryStream (line 963) | renderDiscoveryStream() {
method renderAttributionParamers (line 984) | renderAttributionParamers() {
method renderErrorMessage (line 1062) | renderErrorMessage({ id, errors }) {
method renderErrors (line 1076) | renderErrors() {
method renderTrailheadInfo (line 1099) | renderTrailheadInfo() {
method getSection (line 1117) | getSection() {
method render (line 1183) | render() {
class CollapseToggle (line 1232) | class CollapseToggle extends React.PureComponent {
method constructor (line 1233) | constructor(props) {
method renderAdmin (line 1239) | get renderAdmin() {
method onCollapseToggle (line 1248) | onCollapseToggle(e) {
method setBodyClass (line 1253) | setBodyClass() {
method componentDidMount (line 1261) | componentDidMount() {
method componentDidUpdate (line 1265) | componentDidUpdate() {
method componentWillUnmount (line 1269) | componentWillUnmount() {
method render (line 1273) | render() {
FILE: content-src/components/ASRouterAdmin/SimpleHashRouter.jsx
class SimpleHashRouter (line 7) | class SimpleHashRouter extends React.PureComponent {
method constructor (line 8) | constructor(props) {
method onHashChange (line 14) | onHashChange() {
method componentWillMount (line 18) | componentWillMount() {
method componentWillUnmount (line 22) | componentWillUnmount() {
method render (line 26) | render() {
FILE: content-src/components/Base/Base.jsx
function debounce (line 28) | function debounce(func, wait) {
class _Base (line 44) | class _Base extends React.PureComponent {
method componentWillMount (line 45) | componentWillMount() {
method componentWillUnmount (line 51) | componentWillUnmount() {
method componentWillUpdate (line 55) | componentWillUpdate() {
method updateTheme (line 59) | updateTheme() {
method render (line 75) | render() {
class BaseContent (line 95) | class BaseContent extends React.PureComponent {
method constructor (line 96) | constructor(props) {
method componentDidMount (line 103) | componentDidMount() {
method componentWillUnmount (line 107) | componentWillUnmount() {
method onWindowScroll (line 111) | onWindowScroll() {
method openPreferences (line 120) | openPreferences() {
method render (line 125) | render() {
FILE: content-src/components/Card/Card.jsx
class _Card (line 25) | class _Card extends React.PureComponent {
method constructor (line 26) | constructor(props) {
method maybeLoadImage (line 40) | async maybeLoadImage() {
method getNextStateFromProps (line 93) | static getNextStateFromProps(nextProps, prevState) {
method onMenuButtonUpdate (line 119) | onMenuButtonUpdate(isOpen) {
method _getTelemetryInfo (line 130) | _getTelemetryInfo() {
method onLinkClick (line 139) | onLinkClick(event) {
method componentDidMount (line 193) | componentDidMount() {
method componentDidUpdate (line 197) | componentDidUpdate() {
method componentWillMount (line 204) | componentWillMount() {
method componentWillReceiveProps (line 214) | componentWillReceiveProps(nextProps) {
method componentWillUnmount (line 221) | componentWillUnmount() {
method render (line 225) | render() {
FILE: content-src/components/CollapsibleSection/CollapsibleSection.jsx
constant VISIBLE (line 13) | const VISIBLE = "visible";
constant VISIBILITY_CHANGE_EVENT (line 14) | const VISIBILITY_CHANGE_EVENT = "visibilitychange";
class CollapsibleSection (line 16) | class CollapsibleSection extends React.PureComponent {
method constructor (line 17) | constructor(props) {
method componentWillMount (line 36) | componentWillMount() {
method componentWillUpdate (line 43) | componentWillUpdate(nextProps) {
method setContextMenuButtonRef (line 54) | setContextMenuButtonRef(element) {
method componentDidMount (line 58) | componentDidMount() {
method componentWillUnmount (line 69) | componentWillUnmount() {
method enableOrDisableAnimation (line 84) | enableOrDisableAnimation() {
method onBodyMount (line 92) | onBodyMount(node) {
method onHeaderClick (line 96) | onHeaderClick() {
method onKeyPress (line 120) | onKeyPress(event) {
method _getSectionBodyHeight (line 127) | _getSectionBodyHeight() {
method onTransitionEnd (line 138) | onTransitionEnd(event) {
method renderIcon (line 145) | renderIcon() {
method onMenuButtonMouseEnter (line 162) | onMenuButtonMouseEnter() {
method onMenuButtonMouseLeave (line 166) | onMenuButtonMouseLeave() {
method onMenuUpdate (line 170) | onMenuUpdate(showContextMenu) {
method render (line 174) | render() {
FILE: content-src/components/ComponentPerfTimer/ComponentPerfTimer.jsx
constant RECORDED_SECTIONS (line 11) | const RECORDED_SECTIONS = ["highlights", "topsites"];
class ComponentPerfTimer (line 13) | class ComponentPerfTimer extends React.Component {
method constructor (line 14) | constructor(props) {
method componentDidMount (line 26) | componentDidMount() {
method componentDidUpdate (line 34) | componentDidUpdate() {
method _afterFramePaint (line 62) | _afterFramePaint(callback) {
method _maybeSendBadStateEvent (line 66) | _maybeSendBadStateEvent() {
method _maybeSendPaintedEvent (line 79) | _maybeSendPaintedEvent() {
method _ensureFirstRenderTsRecorded (line 98) | _ensureFirstRenderTsRecorded() {
method _sendBadStateEvent (line 114) | _sendBadStateEvent() {
method _sendPaintedEvent (line 140) | _sendPaintedEvent() {
method render (line 167) | render() {
FILE: content-src/components/ConfirmDialog/ConfirmDialog.jsx
class _ConfirmDialog (line 28) | class _ConfirmDialog extends React.PureComponent {
method constructor (line 29) | constructor(props) {
method _handleCancelBtn (line 35) | _handleCancelBtn() {
method _handleConfirmBtn (line 45) | _handleConfirmBtn() {
method _renderModalMessage (line 49) | _renderModalMessage() {
method render (line 65) | render() {
FILE: content-src/components/ContextMenu/ContextMenu.jsx
class ContextMenu (line 7) | class ContextMenu extends React.PureComponent {
method constructor (line 8) | constructor(props) {
method hideContext (line 15) | hideContext() {
method onShow (line 19) | onShow() {
method componentDidMount (line 25) | componentDidMount() {
method componentWillUnmount (line 32) | componentWillUnmount() {
method onClick (line 36) | onClick(event) {
method render (line 43) | render() {
class ContextMenuItem (line 74) | class ContextMenuItem extends React.PureComponent {
method constructor (line 75) | constructor(props) {
method onClick (line 83) | onClick() {
method focusFirst (line 89) | focusFirst(button) {
method focusSibling (line 96) | focusSibling(target, key) {
method onKeyDown (line 112) | onKeyDown(event) {
method onKeyUp (line 145) | onKeyUp(event) {
method render (line 151) | render() {
FILE: content-src/components/ContextMenu/ContextMenuButton.jsx
class ContextMenuButton (line 7) | class ContextMenuButton extends React.PureComponent {
method constructor (line 8) | constructor(props) {
method openContextMenu (line 19) | openContextMenu(isKeyBoard, event) {
method onClick (line 29) | onClick(event) {
method onKeyDown (line 34) | onKeyDown(event) {
method onUpdate (line 41) | onUpdate(showContextMenu) {
method render (line 48) | render() {
FILE: content-src/components/DiscoveryStreamBase/DiscoveryStreamBase.jsx
constant ALLOWED_CSS_URL_PREFIXES (line 23) | const ALLOWED_CSS_URL_PREFIXES = [
constant DUMMY_CSS_SELECTOR (line 28) | const DUMMY_CSS_SELECTOR = "DUMMY#CSS.SELECTOR";
function isAllowedCSS (line 34) | function isAllowedCSS(property, value) {
class _DiscoveryStreamBase (line 52) | class _DiscoveryStreamBase extends React.PureComponent {
method constructor (line 53) | constructor(props) {
method onStyleMount (line 58) | onStyleMount(style) {
method renderComponent (line 114) | renderComponent(component, embedWidth) {
method renderStyles (line 258) | renderStyles(styles) {
method componentWillReceiveProps (line 265) | componentWillReceiveProps(oldProps) {
method render (line 271) | render() {
method renderLayout (line 379) | renderLayout(layoutRender) {
FILE: content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid.jsx
class CardGrid (line 9) | class CardGrid extends React.PureComponent {
method renderCards (line 10) | renderCards() {
method render (line 67) | render() {
FILE: content-src/components/DiscoveryStreamComponents/DSCard/DSCard.jsx
class DSCard (line 77) | class DSCard extends React.PureComponent {
method constructor (line 78) | constructor(props) {
method onLinkClick (line 91) | onLinkClick(event) {
method onSeen (line 120) | onSeen(entries) {
method onIdleCallback (line 137) | onIdleCallback() {
method componentDidMount (line 148) | componentDidMount() {
method componentWillUnmount (line 158) | componentWillUnmount() {
method render (line 168) | render() {
FILE: content-src/components/DiscoveryStreamComponents/DSContextFooter/DSContextFooter.jsx
constant ANIMATION_DURATION (line 10) | const ANIMATION_DURATION = 3000;
class DSContextFooter (line 22) | class DSContextFooter extends React.PureComponent {
method render (line 23) | render() {
FILE: content-src/components/DiscoveryStreamComponents/DSDismiss/DSDismiss.jsx
class DSDismiss (line 9) | class DSDismiss extends React.PureComponent {
method constructor (line 10) | constructor(props) {
method onDismissClick (line 20) | onDismissClick() {
method onHover (line 46) | onHover() {
method offHover (line 52) | offHover() {
method render (line 58) | render() {
FILE: content-src/components/DiscoveryStreamComponents/DSEmptyState/DSEmptyState.jsx
class DSEmptyState (line 8) | class DSEmptyState extends React.PureComponent {
method constructor (line 9) | constructor(props) {
method componentWillUnmount (line 15) | componentWillUnmount() {
method onReset (line 21) | onReset() {
method renderButton (line 53) | renderButton() {
method renderState (line 72) | renderState() {
method render (line 90) | render() {
FILE: content-src/components/DiscoveryStreamComponents/DSImage/DSImage.jsx
class DSImage (line 8) | class DSImage extends React.PureComponent {
method constructor (line 9) | constructor(props) {
method onSeen (line 22) | onSeen(entries) {
method onIdleCallback (line 45) | onIdleCallback() {
method reformatImageURL (line 53) | reformatImageURL(url, width, height) {
method componentDidMount (line 62) | componentDidMount() {
method componentWillUnmount (line 75) | componentWillUnmount() {
method render (line 85) | render() {
method onOptimizedImageError (line 146) | onOptimizedImageError() {
method onNonOptimizedImageError (line 153) | onNonOptimizedImageError() {
FILE: content-src/components/DiscoveryStreamComponents/DSLinkMenu/DSLinkMenu.jsx
class DSLinkMenu (line 9) | class DSLinkMenu extends React.PureComponent {
method constructor (line 10) | constructor(props) {
method onMenuUpdate (line 17) | onMenuUpdate(showContextMenu) {
method nextAnimationFrame (line 24) | nextAnimationFrame() {
method onMenuShow (line 30) | async onMenuShow() {
method render (line 40) | render() {
FILE: content-src/components/DiscoveryStreamComponents/DSMessage/DSMessage.jsx
class DSMessage (line 9) | class DSMessage extends React.PureComponent {
method render (line 10) | render() {
FILE: content-src/components/DiscoveryStreamComponents/DSPrivacyModal/DSPrivacyModal.jsx
class DSPrivacyModal (line 9) | class DSPrivacyModal extends React.PureComponent {
method constructor (line 10) | constructor(props) {
method onLinkClick (line 16) | onLinkClick(event) {
method closeModal (line 25) | closeModal() {
method render (line 32) | render() {
FILE: content-src/components/DiscoveryStreamComponents/DSTextPromo/DSTextPromo.jsx
class DSTextPromo (line 11) | class DSTextPromo extends React.PureComponent {
method constructor (line 12) | constructor(props) {
method onLinkClick (line 17) | onLinkClick() {
method render (line 45) | render() {
FILE: content-src/components/DiscoveryStreamComponents/Hero/Hero.jsx
class Hero (line 16) | class Hero extends React.PureComponent {
method constructor (line 17) | constructor(props) {
method onLinkClick (line 22) | onLinkClick(event) {
method renderHero (line 50) | renderHero() {
method render (line 173) | render() {
FILE: content-src/components/DiscoveryStreamComponents/Highlights/Highlights.jsx
class _Highlights (line 9) | class _Highlights extends React.PureComponent {
method render (line 10) | render() {
FILE: content-src/components/DiscoveryStreamComponents/HorizontalRule/HorizontalRule.jsx
class HorizontalRule (line 7) | class HorizontalRule extends React.PureComponent {
method render (line 8) | render() {
FILE: content-src/components/DiscoveryStreamComponents/List/List.jsx
class ListItem (line 18) | class ListItem extends React.PureComponent {
method constructor (line 21) | constructor(props) {
method onLinkClick (line 26) | onLinkClick(event) {
method render (line 55) | render() {
function _List (line 133) | function _List(props) {
FILE: content-src/components/DiscoveryStreamComponents/Navigation/Navigation.jsx
class Topic (line 9) | class Topic extends React.PureComponent {
method render (line 10) | render() {
class Navigation (line 22) | class Navigation extends React.PureComponent {
method render (line 23) | render() {
FILE: content-src/components/DiscoveryStreamComponents/SafeAnchor/SafeAnchor.jsx
class SafeAnchor (line 8) | class SafeAnchor extends React.PureComponent {
method constructor (line 9) | constructor(props) {
method onClick (line 14) | onClick(event) {
method safeURI (line 38) | safeURI(url) {
method render (line 54) | render() {
FILE: content-src/components/DiscoveryStreamComponents/SectionTitle/SectionTitle.jsx
class SectionTitle (line 7) | class SectionTitle extends React.PureComponent {
method render (line 8) | render() {
FILE: content-src/components/DiscoveryStreamComponents/TopSites/TopSites.jsx
class _TopSites (line 10) | class _TopSites extends React.PureComponent {
method getFirstAvailableSpoc (line 12) | getFirstAvailableSpoc(topSites, data) {
method getFirstAvailableIndex (line 36) | getFirstAvailableIndex(topSites, promoAlignment) {
method insertSpocContent (line 64) | insertSpocContent(TopSites, data, promoAlignment) {
method render (line 133) | render() {
FILE: content-src/components/DiscoveryStreamImpressionStats/ImpressionStats.jsx
constant VISIBLE (line 8) | const VISIBLE = "visible";
constant VISIBILITY_CHANGE_EVENT (line 9) | const VISIBILITY_CHANGE_EVENT = "visibilitychange";
constant INTERSECTION_RATIO (line 16) | const INTERSECTION_RATIO = 0.5;
class ImpressionStats (line 34) | class ImpressionStats extends React.PureComponent {
method _needsImpressionStats (line 37) | _needsImpressionStats(cards) {
method _dispatchImpressionStats (line 54) | _dispatchImpressionStats() {
method _needsLoadedContent (line 84) | _needsLoadedContent(cards) {
method _dispatchLoadedContent (line 101) | _dispatchLoadedContent() {
method setImpressionObserverOrAddListener (line 116) | setImpressionObserverOrAddListener() {
method setImpressionObserver (line 163) | setImpressionObserver() {
method componentDidMount (line 191) | componentDidMount() {
method componentWillUnmount (line 197) | componentWillUnmount() {
method render (line 209) | render() {
FILE: content-src/components/ErrorBoundary/ErrorBoundary.jsx
class ErrorBoundaryFallback (line 8) | class ErrorBoundaryFallback extends React.PureComponent {
method constructor (line 9) | constructor(props) {
method onClick (line 19) | onClick() {
method render (line 23) | render() {
class ErrorBoundary (line 49) | class ErrorBoundary extends React.PureComponent {
method constructor (line 50) | constructor(props) {
method componentDidCatch (line 55) | componentDidCatch(error, info) {
method render (line 59) | render() {
FILE: content-src/components/FluentOrText/FluentOrText.jsx
class FluentOrText (line 11) | class FluentOrText extends React.PureComponent {
method render (line 12) | render() {
FILE: content-src/components/LinkMenu/LinkMenu.jsx
constant DEFAULT_SITE_MENU_OPTIONS (line 11) | const DEFAULT_SITE_MENU_OPTIONS = [
class _LinkMenu (line 21) | class _LinkMenu extends React.PureComponent {
method getOptions (line 22) | getOptions() {
method render (line 82) | render() {
FILE: content-src/components/MoreRecommendations/MoreRecommendations.jsx
class MoreRecommendations (line 7) | class MoreRecommendations extends React.PureComponent {
method render (line 8) | render() {
FILE: content-src/components/PocketLoggedInCta/PocketLoggedInCta.jsx
class _PocketLoggedInCta (line 8) | class _PocketLoggedInCta extends React.PureComponent {
method render (line 9) | render() {
FILE: content-src/components/Search/Search.jsx
class _Search (line 13) | class _Search extends React.PureComponent {
method constructor (line 14) | constructor(props) {
method handleEvent (line 26) | handleEvent(event) {
method onSearchClick (line 33) | onSearchClick(event) {
method doSearchHandoff (line 37) | doSearchHandoff(text) {
method onSearchHandoffClick (line 48) | onSearchHandoffClick(event) {
method onSearchHandoffPaste (line 57) | onSearchHandoffPaste(event) {
method onSearchHandoffDrop (line 62) | onSearchHandoffDrop(event) {
method componentWillUnmount (line 70) | componentWillUnmount() {
method onInputMount (line 74) | onInputMount(input) {
method onSearchHandoffButtonMount (line 106) | onSearchHandoffButtonMount(button) {
method render (line 116) | render() {
FILE: content-src/components/SectionMenu/SectionMenu.jsx
constant DEFAULT_SECTION_MENU_OPTIONS (line 10) | const DEFAULT_SECTION_MENU_OPTIONS = [
constant WEBEXT_SECTION_MENU_OPTIONS (line 19) | const WEBEXT_SECTION_MENU_OPTIONS = [
class _SectionMenu (line 28) | class _SectionMenu extends React.PureComponent {
method handleAddWhileCollapsed (line 29) | handleAddWhileCollapsed() {
method getOptions (line 42) | getOptions() {
method render (line 97) | render() {
FILE: content-src/components/Sections/Sections.jsx
constant VISIBLE (line 17) | const VISIBLE = "visible";
constant VISIBILITY_CHANGE_EVENT (line 18) | const VISIBILITY_CHANGE_EVENT = "visibilitychange";
constant CARDS_PER_ROW_DEFAULT (line 19) | const CARDS_PER_ROW_DEFAULT = 3;
constant CARDS_PER_ROW_COMPACT_WIDE (line 20) | const CARDS_PER_ROW_COMPACT_WIDE = 4;
class Section (line 22) | class Section extends React.PureComponent {
method numRows (line 23) | get numRows() {
method _dispatchImpressionStats (line 28) | _dispatchImpressionStats() {
method sendImpressionStatsOrAddListener (line 57) | sendImpressionStatsOrAddListener() {
method componentWillMount (line 95) | componentWillMount() {
method componentDidMount (line 99) | componentDidMount() {
method componentDidUpdate (line 105) | componentDidUpdate(prevProps) {
method componentWillUpdate (line 122) | componentWillUpdate(nextProps) {
method componentWillUnmount (line 126) | componentWillUnmount() {
method needsImpressionStats (line 135) | needsImpressionStats(cards) {
method sendNewTabRehydrated (line 155) | sendNewTabRehydrated(initialized) {
method render (line 164) | render() {
class _Sections (line 351) | class _Sections extends React.PureComponent {
method renderSections (line 352) | renderSections() {
method render (line 382) | render() {
FILE: content-src/components/TopSites/SearchShortcutsForm.jsx
class SelectableSearchShortcut (line 9) | class SelectableSearchShortcut extends React.PureComponent {
method render (line 10) | render() {
class SearchShortcutsForm (line 44) | class SearchShortcutsForm extends React.PureComponent {
method constructor (line 45) | constructor(props) {
method handleChange (line 69) | handleChange(event) {
method onCancelButtonClick (line 80) | onCancelButtonClick(ev) {
method onSaveButtonClick (line 85) | onSaveButtonClick(ev) {
method _searchTopSite (line 144) | _searchTopSite(shortcut) {
method render (line 153) | render() {
FILE: content-src/components/TopSites/TopSite.jsx
constant SPOC_TYPE (line 20) | const SPOC_TYPE = "SPOC";
class TopSiteLink (line 22) | class TopSiteLink extends React.PureComponent {
method constructor (line 23) | constructor(props) {
method _allowDrop (line 34) | _allowDrop(e) {
method onDragEvent (line 38) | onDragEvent(event) {
method getNextStateFromProps (line 91) | static getNextStateFromProps(nextProps, prevState) {
method componentWillMount (line 112) | componentWillMount() {
method componentWillReceiveProps (line 122) | componentWillReceiveProps(nextProps) {
method componentWillUnmount (line 129) | componentWillUnmount() {
method onKeyPress (line 133) | onKeyPress(event) {
method render (line 142) | render() {
class TopSite (line 297) | class TopSite extends React.PureComponent {
method constructor (line 298) | constructor(props) {
method _getTelemetryInfo (line 308) | _getTelemetryInfo() {
method userEvent (line 325) | userEvent(event) {
method onLinkClick (line 340) | onLinkClick(event) {
method onMenuUpdate (line 383) | onMenuUpdate(isOpen) {
method render (line 391) | render() {
method onActivate (line 439) | onActivate() {}
class TopSitePlaceholder (line 442) | class TopSitePlaceholder extends React.PureComponent {
method constructor (line 443) | constructor(props) {
method onEditButtonClick (line 448) | onEditButtonClick() {
method render (line 455) | render() {
class TopSiteList (line 473) | class TopSiteList extends React.PureComponent {
method DEFAULT_STATE (line 474) | static get DEFAULT_STATE() {
method constructor (line 484) | constructor(props) {
method componentWillReceiveProps (line 491) | componentWillReceiveProps(nextProps) {
method userEvent (line 510) | userEvent(event, index) {
method onDragEvent (line 520) | onDragEvent(event, index, link, title) {
method _getTopSites (line 573) | _getTopSites() {
method _makeTopSitesPreview (line 584) | _makeTopSitesPreview(index) {
method onActivate (line 627) | onActivate(index) {
method render (line 631) | render() {
FILE: content-src/components/TopSites/TopSiteForm.jsx
class TopSiteForm (line 12) | class TopSiteForm extends React.PureComponent {
method constructor (line 13) | constructor(props) {
method onLabelChange (line 37) | onLabelChange(event) {
method onUrlChange (line 41) | onUrlChange(event) {
method onClearUrlClick (line 48) | onClearUrlClick() {
method onEnableScreenshotUrlForm (line 55) | onEnableScreenshotUrlForm() {
method _updateCustomScreenshotInput (line 59) | _updateCustomScreenshotInput(customScreenshotUrl) {
method onCustomScreenshotUrlChange (line 67) | onCustomScreenshotUrlChange(event) {
method onClearScreenshotInput (line 71) | onClearScreenshotInput() {
method onCancelButtonClick (line 75) | onCancelButtonClick(ev) {
method onDoneButtonClick (line 80) | onDoneButtonClick(ev) {
method onPreviewButtonClick (line 116) | onPreviewButtonClick(event) {
method cleanUrl (line 134) | cleanUrl(url) {
method _tryParseUrl (line 142) | _tryParseUrl(url) {
method validateUrl (line 150) | validateUrl(url) {
method validateCustomScreenshotUrl (line 158) | validateCustomScreenshotUrl() {
method validateForm (line 163) | validateForm() {
method _renderCustomScreenshotInput (line 174) | _renderCustomScreenshotInput() {
method render (line 220) | render() {
FILE: content-src/components/TopSites/TopSiteFormInput.jsx
class TopSiteFormInput (line 7) | class TopSiteFormInput extends React.PureComponent {
method constructor (line 8) | constructor(props) {
method componentWillReceiveProps (line 16) | componentWillReceiveProps(nextProps) {
method onClearIconPress (line 29) | onClearIconPress(event) {
method onChange (line 38) | onChange(ev) {
method onMount (line 45) | onMount(input) {
method renderLoadingOrCloseButton (line 49) | renderLoadingOrCloseButton() {
method render (line 71) | render() {
FILE: content-src/components/TopSites/TopSites.jsx
function topSiteIconType (line 21) | function topSiteIconType(link) {
function countTopSitesIconsTypes (line 45) | function countTopSitesIconsTypes(topSites) {
class _TopSites (line 61) | class _TopSites extends React.PureComponent {
method constructor (line 62) | constructor(props) {
method _dispatchTopSitesStats (line 73) | _dispatchTopSitesStats() {
method _getVisibleTopSites (line 97) | _getVisibleTopSites() {
method componentDidUpdate (line 110) | componentDidUpdate() {
method componentDidMount (line 114) | componentDidMount() {
method onEditFormClose (line 118) | onEditFormClose() {
method onSearchShortcutsFormClose (line 128) | onSearchShortcutsFormClose() {
method render (line 138) | render() {
FILE: content-src/components/TopSites/TopSitesConstants.js
constant TOP_SITES_SOURCE (line 5) | const TOP_SITES_SOURCE = "TOP_SITES";
constant TOP_SITES_CONTEXT_MENU_OPTIONS (line 6) | const TOP_SITES_CONTEXT_MENU_OPTIONS = [
constant TOP_SITES_SPOC_CONTEXT_MENU_OPTIONS (line 16) | const TOP_SITES_SPOC_CONTEXT_MENU_OPTIONS = [
constant TOP_SITES_SEARCH_SHORTCUTS_CONTEXT_MENU_OPTIONS (line 26) | const TOP_SITES_SEARCH_SHORTCUTS_CONTEXT_MENU_OPTIONS = [
constant MIN_RICH_FAVICON_SIZE (line 32) | const MIN_RICH_FAVICON_SIZE = 96;
constant MIN_CORNER_FAVICON_SIZE (line 34) | const MIN_CORNER_FAVICON_SIZE = 16;
FILE: content-src/components/Topics/Topics.jsx
class Topic (line 7) | class Topic extends React.PureComponent {
method render (line 8) | render() {
class Topics (line 20) | class Topics extends React.PureComponent {
method render (line 21) | render() {
FILE: content-src/lib/constants.js
constant IS_NEWTAB (line 5) | const IS_NEWTAB =
constant NEWTAB_DARK_THEME (line 7) | const NEWTAB_DARK_THEME = {
FILE: content-src/lib/detect-user-session-start.js
constant VISIBLE (line 8) | const VISIBLE = "visible";
constant VISIBILITY_CHANGE_EVENT (line 9) | const VISIBILITY_CHANGE_EVENT = "visibilitychange";
class DetectUserSessionStart (line 11) | class DetectUserSessionStart {
method constructor (line 12) | constructor(store, options = {}) {
method sendEventOrAddListener (line 26) | sendEventOrAddListener() {
method _sendEvent (line 45) | _sendEvent() {
method _onVisibilityChange (line 69) | _onVisibilityChange() {
FILE: content-src/lib/init-store.js
constant MERGE_STORE_ACTION (line 14) | const MERGE_STORE_ACTION = "NEW_TAB_INITIAL_STATE";
constant OUTGOING_MESSAGE_NAME (line 15) | const OUTGOING_MESSAGE_NAME = "ActivityStream:ContentToMain";
constant INCOMING_MESSAGE_NAME (line 16) | const INCOMING_MESSAGE_NAME = "ActivityStream:MainToContent";
constant EARLY_QUEUED_ACTIONS (line 17) | const EARLY_QUEUED_ACTIONS = [at.SAVE_SESSION_PERF_DATA];
function mergeStateReducer (line 35) | function mergeStateReducer(mainReducer) {
function initStore (line 129) | function initStore(reducers) {
FILE: content-src/lib/screenshot-utils.js
method isBlob (line 18) | isBlob(isLocal, image) {
method createLocalImageObject (line 27) | createLocalImageObject(remoteImage) {
method maybeRevokeBlobObjectURL (line 42) | maybeRevokeBlobObjectURL(localImage) {
method isRemoteImageLocal (line 49) | isRemoteImageLocal(localImage, remoteImage) {
FILE: content-src/lib/selectLayoutRender.js
function rollForSpocs (line 18) | function rollForSpocs(data, spocsConfig, spocsData, placementName) {
FILE: karma.mc.config.js
constant PATHS (line 7) | const PATHS = {
FILE: loaders/inject-loader.js
constant QUOTE_REGEX_STRING (line 9) | const QUOTE_REGEX_STRING = "['|\"]{1}";
function createRequireStringRegex (line 15) | function createRequireStringRegex(query) {
FILE: test/browser/browser_aboutwelcome.js
constant BRANCH_PREF (line 7) | const BRANCH_PREF = "trailhead.firstrun.branches";
function setTrailheadBranch (line 12) | async function setTrailheadBranch(value) {
function test_trailhead_branch (line 27) | async function test_trailhead_branch(
FILE: test/browser/browser_as_load_location.js
function checkNewtabLoads (line 9) | async function checkNewtabLoads(selector, message) {
function checkActivityStreamLoads (line 30) | async function checkActivityStreamLoads() {
FILE: test/browser/browser_as_render.js
method before (line 4) | async before({ pushPrefs }) {
method before (line 22) | async before({ pushPrefs }) {
method before (line 40) | async before({ pushPrefs }) {
FILE: test/browser/browser_asrouter_cfr.js
function checkCFRFeaturesElements (line 85) | function checkCFRFeaturesElements(notification) {
function checkCFRAddonsElements (line 104) | function checkCFRAddonsElements(notification) {
function checkCFRSocialTrackingProtection (line 125) | function checkCFRSocialTrackingProtection(notification) {
function checkCFRTrackingProtectionMilestone (line 138) | function checkCFRTrackingProtectionMilestone(notification) {
function clearNotifications (line 146) | function clearNotifications() {
function trigger_cfr_panel (line 159) | function trigger_cfr_panel(
FILE: test/browser/browser_asrouter_snippets.js
method before (line 11) | async before() {
method before (line 41) | async before() {
FILE: test/browser/browser_asrouter_targeting.js
method FOO (line 62) | get FOO() {
function onError (line 107) | function onError(...args) {
function onError (line 135) | function onError(...args) {
method foo (line 141) | get foo() {
FILE: test/browser/browser_asrouter_trigger_listeners.js
function openURLInWindow (line 17) | async function openURLInWindow(window, url) {
FILE: test/browser/browser_discovery_render.js
function before (line 3) | async function before({ pushPrefs }) {
FILE: test/browser/browser_discovery_styles.js
function fakePref (line 3) | function fakePref(layout) {
method before (line 14) | async before({ pushPrefs }) {
method before (line 48) | async before({ pushPrefs }) {
method before (line 84) | async before({ pushPrefs }) {
method before (line 137) | async before({ pushPrefs }) {
FILE: test/browser/browser_enabled_newtabpage.js
function checkSpec (line 1) | function checkSpec(uri, check, message) {
FILE: test/browser/browser_getScreenshots.js
constant TEST_URL (line 7) | const TEST_URL =
constant XHTMLNS (line 9) | const XHTMLNS = "http://www.w3.org/1999/xhtml";
function get_pixels_for_blob (line 17) | function get_pixels_for_blob(blob, width, height) {
FILE: test/browser/browser_highlights_section.js
function test_highlights (line 8) | function test_highlights(bookmarkCount, test) {
FILE: test/browser/browser_newtab_overrides.js
function nextChangeNotificationPromise (line 14) | function nextChangeNotificationPromise(aNewURL, testMessage) {
FILE: test/browser/browser_onboarding_rtamo.js
constant BRANCH_PREF (line 11) | const BRANCH_PREF = "trailhead.firstrun.branches";
function setRTAMOOnboarding (line 13) | async function setRTAMOOnboarding() {
FILE: test/browser/browser_topsites_contextMenu_options.js
method after (line 93) | async after() {
FILE: test/browser/browser_topsites_section.js
method after (line 191) | after(searchTopSiteTag) {
FILE: test/browser/head.js
function popPrefs (line 14) | function popPrefs() {
function pushPrefs (line 17) | function pushPrefs(...prefs) {
function setDefaultTopSites (line 22) | async function setDefaultTopSites() {
function clearHistoryAndBookmarks (line 38) | async function clearHistoryAndBookmarks() {
function waitForPreloaded (line 49) | async function waitForPreloaded(browser) {
function refreshHighlightsFeed (line 63) | function refreshHighlightsFeed() {
function addHighlightsBookmarks (line 80) | async function addHighlightsBookmarks(count) {
function addContentHelpers (line 101) | function addContentHelpers() {
function test_newtab (line 137) | function test_newtab(testInfo) {
FILE: test/schemas/pings.js
function chaiAssertions (line 346) | function chaiAssertions(_chai, utils) {
FILE: test/unit/asrouter/ASRouter.test.js
constant OUTGOING_MESSAGE_NAME (line 27) | const OUTGOING_MESSAGE_NAME = "ASRouter:parent-to-child";
constant MESSAGE_PROVIDER_PREF_NAME (line 28) | const MESSAGE_PROVIDER_PREF_NAME =
constant FAKE_PROVIDERS (line 30) | const FAKE_PROVIDERS = [
constant FAKE_BUNDLE (line 35) | const FAKE_BUNDLE = [FAKE_LOCAL_MESSAGES[1], FAKE_LOCAL_MESSAGES[2]];
constant ONE_DAY_IN_MS (line 36) | const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000;
method get (line 37) | get() {}
constant USE_REMOTE_L10N_PREF (line 39) | const USE_REMOTE_L10N_PREF =
function fakeAsyncMessage (line 44) | function fakeAsyncMessage(action) {
function fakeExecuteUserAction (line 48) | function fakeExecuteUserAction(action) {
function createFakeStorage (line 72) | function createFakeStorage() {
function setMessageProviderPref (line 96) | function setMessageProviderPref(value) {
function createRouterAndInit (line 100) | async function createRouterAndInit(providers = FAKE_PROVIDERS) {
method bucket (line 178) | bucket() {
method collection (line 181) | collection() {
method getRecord (line 184) | getRecord() {
method download (line 189) | download() {
function assertRouterContainsMessages (line 625) | function assertRouterContainsMessages(messages) {
method getExtraAttributes (line 1359) | getExtraAttributes() {
function addProviderWithFrequency (line 2615) | async function addProviderWithFrequency(id, frequency) {
method getAttribute (line 3164) | getAttribute() {
method getAttribute (line 3179) | getAttribute() {
method getAttribute (line 3193) | getAttribute() {
FILE: test/unit/asrouter/ASRouterPreferences.test.js
constant FAKE_PROVIDERS (line 7) | const FAKE_PROVIDERS = [{ id: "foo" }, { id: "bar" }];
constant PROVIDER_PREF_BRANCH (line 9) | const PROVIDER_PREF_BRANCH =
constant DEVTOOLS_PREF (line 11) | const DEVTOOLS_PREF =
constant SNIPPETS_USER_PREF (line 13) | const SNIPPETS_USER_PREF = "browser.newtabpage.activity-stream.feeds.sni...
constant CFR_USER_PREF_ADDONS (line 14) | const CFR_USER_PREF_ADDONS =
constant CFR_USER_PREF_FEATURES (line 16) | const CFR_USER_PREF_FEATURES =
constant NUMBER_OF_PREFS_TO_OBSERVE (line 27) | const NUMBER_OF_PREFS_TO_OBSERVE = 6;
function getPrefNameForProvider (line 63) | function getPrefNameForProvider(providerId) {
function setPrefForProvider (line 67) | function setPrefForProvider(providerId, value) {
FILE: test/unit/asrouter/ASRouterTargeting.test.js
method foo (line 194) | get foo() {
method bar (line 199) | get bar() {
method foo (line 210) | get foo() {
method foo (line 215) | get foo() {
function assertSortsCorrectly (line 397) | function assertSortsCorrectly(expectedOrderArray, options) {
FILE: test/unit/asrouter/CFRMessageProvider.test.js
constant REGULAR_IDS (line 4) | const REGULAR_IDS = [
FILE: test/unit/asrouter/CFRPageActions.test.js
method hideAddressBarNotifier (line 1145) | hideAddressBarNotifier() {}
FILE: test/unit/asrouter/MessageLoaderUtils.test.js
constant FAKE_OPTIONS (line 5) | const FAKE_OPTIONS = {
method set (line 7) | set() {
method get (line 10) | get() {
method get (line 16) | get() {}
function assertReturnsCorrectMessages (line 105) | function assertReturnsCorrectMessages(actual) {
method set (line 176) | set() {
method get (line 179) | get() {
method set (line 303) | set() {
method get (line 306) | get() {
method set (line 333) | set() {
method get (line 336) | get() {
method getElementById (line 441) | getElementById() {
FILE: test/unit/asrouter/ModalOverlay.test.jsx
method getElementById (line 17) | getElementById() {
FILE: test/unit/asrouter/TargetingDocs.test.js
constant SKIP_DOCS (line 5) | const SKIP_DOCS = [];
constant MESSAGE_CONTEXT_ATTRIBUTES (line 7) | const MESSAGE_CONTEXT_ATTRIBUTES = [
function getHeadingsFromDocs (line 13) | function getHeadingsFromDocs() {
function getTOCFromDocs (line 26) | function getTOCFromDocs() {
FILE: test/unit/asrouter/asrouter-content.test.jsx
constant FAKE_NEWSLETTER_SNIPPET (line 16) | const FAKE_NEWSLETTER_SNIPPET = FAKE_LOCAL_MESSAGES.find(
constant FAKE_FXA_SNIPPET (line 19) | const FAKE_FXA_SNIPPET = FAKE_LOCAL_MESSAGES.find(msg => msg.id === "fxa");
constant FAKE_BELOW_SEARCH_SNIPPET (line 20) | const FAKE_BELOW_SEARCH_SNIPPET = FAKE_LOCAL_MESSAGES.find(
method appendChild (line 75) | appendChild(el) {
method visibilityState (line 79) | get visibilityState() {
method visibilityState (line 82) | set visibilityState(value) {
method addEventListener (line 89) | addEventListener(event, listener) {
method removeEventListener (line 92) | removeEventListener(event, listener) {
method body (line 95) | get body() {
method getElementById (line 98) | getElementById(id) {
method createElement (line 106) | createElement(tag) {
function simulateVisibilityChange (line 300) | function simulateVisibilityChange(value) {
FILE: test/unit/asrouter/compatibility-reference/snippets-fx57.js
constant DATA_URI_IMAGE (line 9) | const DATA_URI_IMAGE =
FILE: test/unit/asrouter/constants.js
constant CHILD_TO_PARENT_MESSAGE_NAME (line 1) | const CHILD_TO_PARENT_MESSAGE_NAME = "ASRouter:child-to-parent";
constant PARENT_TO_CHILD_MESSAGE_NAME (line 2) | const PARENT_TO_CHILD_MESSAGE_NAME = "ASRouter:parent-to-child";
constant FAKE_LOCAL_MESSAGES (line 4) | const FAKE_LOCAL_MESSAGES = [
constant FAKE_LOCAL_PROVIDER (line 52) | const FAKE_LOCAL_PROVIDER = {
constant FAKE_LOCAL_PROVIDERS (line 59) | const FAKE_LOCAL_PROVIDERS = {
constant FAKE_REMOTE_MESSAGES (line 63) | const FAKE_REMOTE_MESSAGES = [
constant FAKE_REMOTE_PROVIDER (line 70) | const FAKE_REMOTE_PROVIDER = {
constant FAKE_REMOTE_SETTINGS_PROVIDER (line 77) | const FAKE_REMOTE_SETTINGS_PROVIDER = {
constant FAKE_RECOMMENDATION (line 87) | const FAKE_RECOMMENDATION = {
class FakeRemotePageManager (line 137) | class FakeRemotePageManager {
method constructor (line 138) | constructor() {
FILE: test/unit/asrouter/schemas/panel/cfr-fxa-bookmark.schema.test.js
constant DEFAULT_CONTENT (line 3) | const DEFAULT_CONTENT = {
constant L10N_CONTENT (line 12) | const L10N_CONTENT = {
FILE: test/unit/asrouter/templates/EOYSnippet.test.jsx
constant DEFAULT_CONTENT (line 7) | const DEFAULT_CONTENT = {
function mountAndCheckProps (line 28) | function mountAndCheckProps(content = {}, provider = "test-provider") {
FILE: test/unit/asrouter/templates/ExtensionDoorhanger.test.jsx
constant DEFAULT_CONTENT (line 4) | const DEFAULT_CONTENT = {
constant L10N_CONTENT (line 43) | const L10N_CONTENT = {
FILE: test/unit/asrouter/templates/FXASignupSnippet.test.jsx
constant DEFAULT_CONTENT (line 7) | const DEFAULT_CONTENT = SnippetsTestMessageProvider.getMessages().find(
function mountAndCheckProps (line 14) | function mountAndCheckProps(content = {}) {
method onBlock (line 43) | onBlock() {}
FILE: test/unit/asrouter/templates/FirstRun.test.jsx
constant FAKE_TRIPLETS_BUNDLE_1 (line 11) | const FAKE_TRIPLETS_BUNDLE_1 = [
constant FAKE_TRIPLETS_BUNDLE_2 (line 29) | const FAKE_TRIPLETS_BUNDLE_2 = [
constant FAKE_FLOW_PARAMS (line 47) | const FAKE_FLOW_PARAMS = {
function getTestMessage (line 53) | async function getTestMessage(id, requestNewBundle) {
function setup (line 73) | async function setup() {
FILE: test/unit/asrouter/templates/FullPageInterrupt.test.jsx
constant CARDS (line 12) | const CARDS = [
constant FAKE_FLOW_PARAMS (line 30) | const FAKE_FLOW_PARAMS = {
method getElementById (line 57) | getElementById() {
FILE: test/unit/asrouter/templates/FxASignupForm.test.jsx
method getElementById (line 41) | getElementById() {
FILE: test/unit/asrouter/templates/NewsletterSnippet.test.jsx
constant DEFAULT_CONTENT (line 7) | const DEFAULT_CONTENT = SnippetsTestMessageProvider.getMessages().find(
function mountAndCheckProps (line 14) | function mountAndCheckProps(content = {}) {
method onBlock (line 47) | onBlock() {}
FILE: test/unit/asrouter/templates/OnboardingMessage.test.jsx
constant DEFAULT_CONTENT (line 7) | const DEFAULT_CONTENT = {
constant L10N_CONTENT (line 20) | const L10N_CONTENT = {
FILE: test/unit/asrouter/templates/SendToDeviceSnippet.test.jsx
constant DEFAULT_CONTENT (line 7) | const DEFAULT_CONTENT = SnippetsTestMessageProvider.getMessages().find(
function testBodyContains (line 11) | async function testBodyContains(body, key, value) {
function openFormAndSetValue (line 25) | function openFormAndSetValue(wrapper, value, setCustomValidity = () => {...
function mountAndCheckProps (line 40) | function mountAndCheckProps(content = {}) {
method onBlock (line 69) | onBlock() {}
FILE: test/unit/asrouter/templates/SimpleBelowSearchSnippet.test.jsx
constant DEFAULT_CONTENT (line 6) | const DEFAULT_CONTENT = { text: "foo" };
function mountAndCheckProps (line 18) | function mountAndCheckProps(content = {}, provider = "test-provider") {
FILE: test/unit/asrouter/templates/SimpleSnippet.test.jsx
constant DEFAULT_CONTENT (line 6) | const DEFAULT_CONTENT = { text: "foo" };
function mountAndCheckProps (line 19) | function mountAndCheckProps(content = {}, provider = "test-provider") {
FILE: test/unit/asrouter/templates/SubmitFormSnippet.test.jsx
constant DEFAULT_CONTENT (line 7) | const DEFAULT_CONTENT = {
function mountAndCheckProps (line 28) | function mountAndCheckProps(content = {}) {
function validateInput (line 114) | function validateInput(value, content) {
FILE: test/unit/asrouter/templates/Trailhead.test.jsx
constant CARDS (line 8) | const CARDS = [
method activeElement (line 47) | get activeElement() {
method body (line 50) | get body() {
method getElementById (line 53) | getElementById() {
FILE: test/unit/asrouter/templates/Triplets.test.jsx
constant CARDS (line 6) | const CARDS = [
function setup (line 32) | async function setup() {
FILE: test/unit/asrouter/templates/isEmailOrPhoneNumber.test.js
constant CONTENT (line 3) | const CONTENT = {};
FILE: test/unit/common/PerfService.test.js
function bogusGet (line 53) | function bogusGet() {
FILE: test/unit/common/Reducers.test.js
function prevState (line 266) | function prevState(custom = {}) {
FILE: test/unit/content-src/components/ASRouterAdmin.test.jsx
function onClick (line 344) | function onClick(spoc) {
FILE: test/unit/content-src/components/Card.test.jsx
constant DEFAULT_PROPS (line 16) | let DEFAULT_PROPS = {
constant DEFAULT_BLOB_IMAGE (line 33) | let DEFAULT_BLOB_IMAGE = {
function mountCardWithProps (line 38) | function mountCardWithProps(props) {
method addEventListener (line 338) | addEventListener(event, callback) {
method preventDefault (line 484) | preventDefault() {}
FILE: test/unit/content-src/components/CollapsibleSection.test.jsx
constant DEFAULT_PROPS (line 7) | const DEFAULT_PROPS = {
function setup (line 24) | function setup(props = {}) {
function dispatch (line 58) | function dispatch(a) {
FILE: test/unit/content-src/components/ComponentPerfTimer.test.jsx
method mark (line 9) | mark() {}
method getMostRecentAbsMarkStartByName (line 10) | getMostRecentAbsMarkStartByName() {}
constant DEFAULT_PROPS (line 13) | let DEFAULT_PROPS = {
method dispatch (line 17) | dispatch() {}
FILE: test/unit/content-src/components/ContextMenu.test.jsx
constant DEFAULT_PROPS (line 9) | const DEFAULT_PROPS = {
constant DEFAULT_MENU_OPTIONS (line 15) | const DEFAULT_MENU_OPTIONS = [
FILE: test/unit/content-src/components/DiscoveryStreamBase.test.jsx
function mountComponent (line 92) | function mountComponent(props = {}) {
FILE: test/unit/content-src/components/DiscoveryStreamComponents/ImpressionStats.test.jsx
function buildIntersectionObserver (line 24) | function buildIntersectionObserver(entries) {
function renderImpressionStats (line 51) | function renderImpressionStats(props = {}) {
FILE: test/unit/content-src/components/ErrorBoundary.test.jsx
class TestFallback (line 31) | class TestFallback extends React.PureComponent {
method render (line 32) | render() {
method render (line 47) | render() {
class TestFallback (line 46) | class TestFallback extends React.PureComponent {
method render (line 32) | render() {
method render (line 47) | render() {
FILE: test/unit/content-src/components/PocketLoggedInCta.test.jsx
function mountSectionWithProps (line 11) | function mountSectionWithProps(props) {
FILE: test/unit/content-src/components/ReturnToAMO.test.jsx
method activeElement (line 26) | get activeElement() {
method body (line 29) | get body() {
method getElementById (line 32) | getElementById() {
FILE: test/unit/content-src/components/Search.test.jsx
method dispatch (line 6) | dispatch() {}
FILE: test/unit/content-src/components/SectionMenu.test.jsx
constant DEFAULT_PROPS (line 6) | const DEFAULT_PROPS = {
FILE: test/unit/content-src/components/Sections.test.jsx
function mountSectionWithProps (line 18) | function mountSectionWithProps(props) {
function mountSectionIntlWithProps (line 27) | function mountSectionIntlWithProps(props) {
function renderWithSites (line 165) | function renderWithSites(rows) {
function renderSection (line 384) | function renderSection(props = {}) {
FILE: test/unit/content-src/components/TopSites.test.jsx
method mark (line 28) | mark() {}
method getMostRecentAbsMarkStartByName (line 29) | getMostRecentAbsMarkStartByName() {}
constant DEFAULT_PROPS (line 32) | const DEFAULT_PROPS = {
method dispatch (line 37) | dispatch() {}
constant DEFAULT_BLOB_URL (line 41) | const DEFAULT_BLOB_URL = "blob://test";
method setData (line 628) | setData() {}
method includes (line 628) | includes() {}
method preventDefault (line 629) | preventDefault() {
method blur (line 632) | blur() {}
method preventDefault (line 763) | preventDefault() {}
method preventDefault (line 780) | preventDefault() {}
method preventDefault (line 808) | preventDefault() {}
method preventDefault (line 834) | preventDefault() {}
method preventDefault (line 855) | preventDefault() {}
function setup (line 868) | function setup(props = {}) {
FILE: test/unit/content-src/lib/detect-user-session-start.test.js
class PerfService (line 6) | class PerfService {
method getMostRecentAbsMarkStartByName (line 7) | getMostRecentAbsMarkStartByName() {
method mark (line 10) | mark() {}
FILE: test/unit/content-src/lib/screenshot-utils.test.js
constant DEFAULT_BLOB_URL (line 4) | const DEFAULT_BLOB_URL = "blob://test";
FILE: test/unit/content-src/lib/selectLayoutRender.test.js
constant FAKE_LAYOUT (line 6) | const FAKE_LAYOUT = [
constant FAKE_FEEDS (line 14) | const FAKE_FEEDS = {
FILE: test/unit/lib/AboutPreferences.test.js
method setAttributes (line 137) | setAttributes(el, id, args) {
FILE: test/unit/lib/ActivityStream.test.js
function Fake (line 9) | function Fake() {}
function FakeStore (line 10) | function FakeStore() {
FILE: test/unit/lib/ActivityStreamMessageChannel.test.js
constant OPTIONS (line 9) | const OPTIONS = [
function RP (line 22) | function RP(url, isFromAboutNewTab = false) {
method getAttribute (line 224) | getAttribute() {
method getAttribute (line 236) | getAttribute() {
method getAttribute (line 249) | getAttribute() {
method getAttribute (line 368) | getAttribute() {
method getAttribute (line 387) | getAttribute() {
method getAttribute (line 402) | getAttribute() {
FILE: test/unit/lib/ActivityStreamPrefs.test.js
constant TEST_PREF_CONFIG (line 3) | const TEST_PREF_CONFIG = new Map([
FILE: test/unit/lib/DiscoveryStreamFeed.test.js
constant CONFIG_PREF_NAME (line 11) | const CONFIG_PREF_NAME = "discoverystream.config";
constant DUMMY_ENDPOINT (line 12) | const DUMMY_ENDPOINT = "https://getpocket.cdn.mozilla.net/dummy";
constant ENDPOINTS_PREF_NAME (line 13) | const ENDPOINTS_PREF_NAME = "discoverystream.endpoints";
constant SPOC_IMPRESSION_TRACKING_PREF (line 14) | const SPOC_IMPRESSION_TRACKING_PREF = "discoverystream.spoc.impressions";
constant REC_IMPRESSION_TRACKING_PREF (line 15) | const REC_IMPRESSION_TRACKING_PREF = "discoverystream.rec.impressions";
constant THIRTY_MINUTES (line 16) | const THIRTY_MINUTES = 30 * 60 * 1000;
constant ONE_WEEK (line 17) | const ONE_WEEK = 7 * 24 * 60 * 60 * 1000;
constant FAKE_UUID (line 19) | const FAKE_UUID = "{foo-123-foo}";
class FakeUserDomainAffinityProvider (line 46) | class FakeUserDomainAffinityProvider {
method constructor (line 47) | constructor(
method getAffinities (line 61) | getAffinities() {
FILE: test/unit/lib/DownloadsManager.test.js
method createInstance (line 13) | createInstance() {
method dispatch (line 33) | dispatch() {}
method isBlocked (line 43) | isBlocked() {}
method dispatch (line 51) | dispatch() {}
FILE: test/unit/lib/FaviconFeed.test.js
constant FAKE_ENDPOINT (line 6) | const FAKE_ENDPOINT = "https://foo.com/";
method getState (line 44) | getState() {
FILE: test/unit/lib/FilterAdult.test.js
method createInstance (line 18) | createInstance() {
FILE: test/unit/lib/HighlightsFeed.test.js
constant FAKE_LINKS (line 9) | const FAKE_LINKS = new Array(20)
constant FAKE_IMAGE (line 12) | const FAKE_IMAGE = "data123";
method getState (line 93) | getState() {
function fetchImage (line 623) | function fetchImage(page) {
FILE: test/unit/lib/NaiveBayesTextTagger.test.js
constant EPSILON (line 4) | const EPSILON = 0.00001;
FILE: test/unit/lib/NmfTextTagger.test.js
constant EPSILON (line 4) | const EPSILON = 0.00001;
FILE: test/unit/lib/PersonalityProvider.test.js
constant TIME_SEGMENTS (line 4) | const TIME_SEGMENTS = [
constant PARAMETER_SETS (line 11) | const PARAMETER_SETS = {
FILE: test/unit/lib/PlacesFeed.test.js
constant FAKE_BOOKMARK (line 6) | const FAKE_BOOKMARK = {
constant TYPE_BOOKMARK (line 12) | const TYPE_BOOKMARK = 0;
constant SOURCES (line 13) | const SOURCES = {
constant BLOCKED_EVENT (line 21) | const BLOCKED_EVENT = "newtab-linkBlocked";
method getBookmark (line 31) | getBookmark() {}
method createInstance (line 57) | createInstance() {
method ownerGlobal (line 159) | ownerGlobal() {}
FILE: test/unit/lib/PrefsFeed.test.js
method getState (line 33) | getState() {
FILE: test/unit/lib/RecipeExecutor.test.js
class MockTagger (line 3) | class MockTagger {
method constructor (line 4) | constructor(mode, tagScoreMap) {
method tagTokens (line 8) | tagTokens(tokens) {
method tag (line 23) | tag(text) {
FILE: test/unit/lib/Screenshots.test.js
constant URL (line 5) | const URL = "foo.com";
constant FAKE_THUMBNAIL_PATH (line 6) | const FAKE_THUMBNAIL_PATH = "fake/path/thumb.jpg";
method getEnumerator (line 19) | getEnumerator() {
FILE: test/unit/lib/SectionsManager.test.js
constant FAKE_ID (line 12) | const FAKE_ID = "FAKE_ID";
constant FAKE_OPTIONS (line 13) | const FAKE_OPTIONS = { icon: "FAKE_ICON", title: "FAKE_TITLE" };
constant FAKE_ROWS (line 14) | const FAKE_ROWS = [
constant FAKE_TRENDING_ROWS (line 19) | const FAKE_TRENDING_ROWS = [{ url: "bar", type: "trending" }];
constant FAKE_URL (line 20) | const FAKE_URL = "2.example.com";
constant FAKE_CARD_OPTIONS (line 21) | const FAKE_CARD_OPTIONS = { title: "Some fake title" };
method addObserver (line 359) | addObserver() {}
method removeObserver (line 360) | removeObserver() {}
method getState (line 529) | getState() {
FILE: test/unit/lib/SiteClassifier.test.js
constant FAKE_CLASSIFIER_DATA (line 3) | const FAKE_CLASSIFIER_DATA = [
function RemoteSettings (line 96) | function RemoteSettings() {
FILE: test/unit/lib/Store.test.js
function ActivityStreamMessageChannel (line 12) | function ActivityStreamMessageChannel(options) {
function FakeActivityStreamStorage (line 20) | function FakeActivityStreamStorage() {
class Foo (line 56) | class Foo {}
function createFeed (line 66) | function createFeed() {
class Foo (line 79) | class Foo {}
function createFeed (line 94) | function createFeed() {
class Foo (line 108) | class Foo {}
FILE: test/unit/lib/SystemTickFeed.test.js
method getState (line 13) | getState() {
method dispatch (line 16) | dispatch() {}
FILE: test/unit/lib/TelemetryFeed.test.js
constant FAKE_UUID (line 21) | const FAKE_UUID = "{foo-123-foo}";
constant FAKE_ROUTER_MESSAGE_PROVIDER (line 22) | const FAKE_ROUTER_MESSAGE_PROVIDER = [{ id: "cfr", enabled: true }];
constant FAKE_ROUTER_MESSAGE_PROVIDER_COHORT (line 23) | const FAKE_ROUTER_MESSAGE_PROVIDER_COHORT = [
constant FAKE_TELEMETRY_ID (line 26) | const FAKE_TELEMETRY_ID = "foo123";
method getAttribute (line 33) | getAttribute() {
class PingCentre (line 42) | class PingCentre {
method sendPing (line 43) | sendPing() {}
method uninit (line 44) | uninit() {}
method sendStructuredIngestionPing (line 45) | sendStructuredIngestionPing() {}
class UTEventReporting (line 47) | class UTEventReporting {
method sendUserEvent (line 48) | sendUserEvent() {}
method sendSessionEndEvent (line 49) | sendSessionEndEvent() {}
method sendTrailheadEnrollEvent (line 50) | sendTrailheadEnrollEvent() {}
method uninit (line 51) | uninit() {}
class PerfService (line 53) | class PerfService {
method getMostRecentAbsMarkStartByName (line 54) | getMostRecentAbsMarkStartByName() {
method mark (line 57) | mark() {}
method absNow (line 58) | absNow() {
method timeOrigin (line 61) | get timeOrigin() {
method get (line 85) | get() {
method initialize (line 90) | initialize() {
method getSetting (line 93) | getSetting() {}
method getUpdateChannel (line 779) | getUpdateChannel() {
method getUpdateChannel (line 799) | getUpdateChannel() {
method getUpdateChannel (line 819) | getUpdateChannel() {
method getAttribute (line 1368) | getAttribute() {
method getAttribute (line 1386) | getAttribute() {
FILE: test/unit/lib/Tokenize.test.js
constant EPSILON (line 3) | const EPSILON = 0.00001;
FILE: test/unit/lib/TopSitesFeed.test.js
constant FAKE_FAVICON (line 14) | const FAKE_FAVICON = "data987";
constant FAKE_FAVICON_SIZE (line 15) | const FAKE_FAVICON_SIZE = 128;
constant FAKE_FRECENCY (line 16) | const FAKE_FRECENCY = 200;
constant FAKE_LINKS (line 17) | const FAKE_LINKS = new Array(2 * TOP_SITES_MAX_SITES_PER_ROW)
constant FAKE_SCREENSHOT (line 23) | const FAKE_SCREENSHOT = "data123";
constant SEARCH_SHORTCUTS_EXPERIMENT_PREF (line 24) | const SEARCH_SHORTCUTS_EXPERIMENT_PREF = "improvesearch.topSiteSearchSho...
constant SEARCH_SHORTCUTS_SEARCH_ENGINES_PREF (line 25) | const SEARCH_SHORTCUTS_SEARCH_ENGINES_PREF =
constant SEARCH_SHORTCUTS_HAVE_PINNED_PREF (line 27) | const SEARCH_SHORTCUTS_HAVE_PINNED_PREF =
function FakeTippyTopProvider (line 30) | function FakeTippyTopProvider() {}
method init (line 32) | async init() {
method processSite (line 35) | processSite(site) {
method getState (line 131) | getState() {
function stubFaviconsToUseScreenshots (line 152) | function stubFaviconsToUseScreenshots() {
FILE: test/unit/lib/TopStoriesFeed.test.js
method isUserLoggedIn (line 42) | isUserLoggedIn() {}
class FakeUserDomainAffinityProvider (line 53) | class FakeUserDomainAffinityProvider {
method constructor (line 54) | constructor(
method getAffinities (line 68) | getAffinities() {
class FakePersonalityProvider (line 72) | class FakePersonalityProvider extends FakeUserDomainAffinityProvider {}
method getState (line 97) | getState() {
method getState (line 2027) | getState() {
FILE: test/unit/lib/UTEventReporting.test.js
constant FAKE_EVENT_PING_PC (line 9) | const FAKE_EVENT_PING_PC = {
constant FAKE_SESSION_PING_PC (line 19) | const FAKE_SESSION_PING_PC = {
constant FAKE_EVENT_PING_UT (line 27) | const FAKE_EVENT_PING_UT = [
constant FAKE_SESSION_PING_UT (line 40) | const FAKE_SESSION_PING_UT = [
constant FAKE_TRAILHEAD_ENROLL_EVENT (line 52) | const FAKE_TRAILHEAD_ENROLL_EVENT = {
constant FAKE_TRAILHEAD_ENROLL_EVENT_UT (line 57) | const FAKE_TRAILHEAD_ENROLL_EVENT_UT = [
FILE: test/unit/lib/UserDomainAffinityProvider.test.js
constant TIME_SEGMENTS (line 4) | const TIME_SEGMENTS = [
constant PARAMETER_SETS (line 11) | const PARAMETER_SETS = {
function calculateScore (line 63) | function calculateScore(visitCounts, timeSeg, domain, ps) {
FILE: test/unit/ping-centre/PingCentre.test.js
constant FAKE_UPDATE_CHANNEL (line 21) | const FAKE_UPDATE_CHANNEL = "beta";
constant FAKE_LOCALE (line 22) | const FAKE_LOCALE = "en-US";
constant FAKE_ACTIVE_EXPERIMENTS (line 23) | const FAKE_ACTIVE_EXPERIMENTS = {
constant FAKE_PROFILE_CREATION_DATE (line 27) | const FAKE_PROFILE_CREATION_DATE = 16587;
constant FAKE_BROWSER_SEARCH_REGION (line 28) | const FAKE_BROWSER_SEARCH_REGION = "US";
method getUpdateChannel (line 56) | getUpdateChannel() {
function testEnabled (line 88) | function testEnabled(p) {
function testExperimentString (line 178) | function testExperimentString(experimentString, activeExperiments, filte...
FILE: test/unit/unit-entry.js
constant TEST_GLOBAL (line 39) | const TEST_GLOBAL = {
method getActiveAddons (line 41) | getActiveAddons() {
method getUpdateChannel (line 46) | getUpdateChannel() {}
method getTopWindow (line 47) | getTopWindow() {}
method defineModuleGetter (line 49) | defineModuleGetter() {}
method generateQI (line 50) | generateQI() {
method import (line 53) | import() {
method userId (line 58) | get userId() {
method Constructor (line 63) | Constructor(classId) {
method addObserver (line 80) | addObserver() {}
method getService (line 81) | getService() {
method removeObserver (line 84) | removeObserver() {}
method addObserver (line 89) | addObserver() {}
method executeQuery (line 90) | executeQuery() {}
method getNewQuery (line 91) | getNewQuery() {}
method getNewQueryOptions (line 92) | getNewQueryOptions() {}
method getService (line 93) | getService() {
method insert (line 96) | insert() {}
method markPageAsTyped (line 97) | markPageAsTyped() {}
method removeObserver (line 98) | removeObserver() {}
method createInstance (line 101) | createInstance() {
method createInstance (line 106) | createInstance() {
method createInstance (line 116) | createInstance() {}
method getService (line 118) | getService() {
method createInstance (line 123) | createInstance() {
method importGlobalProperties (line 143) | importGlobalProperties() {}
method reportError (line 145) | reportError() {}
method dump (line 147) | dump() {}
method fetch (line 152) | fetch() {}
method writeAtomic (line 163) | writeAtomic() {}
method makeDir (line 164) | makeDir() {}
method stat (line 165) | stat() {}
method exists (line 166) | exists() {}
method remove (line 167) | remove() {}
method removeEmptyDir (line 168) | removeEmptyDir() {}
method join (line 171) | join() {
method bookmarks (line 182) | get bookmarks() {
method history (line 185) | get history() {
method addListener (line 189) | addListener() {}
method removeListener (line 190) | removeListener() {}
method get (line 193) | get() {}
method appLocaleAsLangTag (line 212) | get appLocaleAsLangTag() {
method negotiateLanguages (line 215) | negotiateLanguages() {}
method removeMessageListener (line 220) | removeMessageListener() {}
method addObserver (line 224) | addObserver() {}
method removeObserver (line 225) | removeObserver() {}
method addObserver (line 233) | addObserver() {}
method prefHasUserValue (line 234) | prefHasUserValue() {}
method removeObserver (line 235) | removeObserver() {}
method getPrefType (line 236) | getPrefType() {}
method clearUserPref (line 237) | clearUserPref() {}
method getChildList (line 238) | getChildList() {
method getStringPref (line 241) | getStringPref() {}
method setStringPref (line 242) | setStringPref() {}
method getIntPref (line 243) | getIntPref() {}
method getBoolPref (line 244) | getBoolPref() {}
method getCharPref (line 245) | getCharPref() {}
method setBoolPref (line 246) | setBoolPref() {}
method setCharPref (line 247) | setCharPref() {}
method setIntPref (line 248) | setIntPref() {}
method getBranch (line 249) | getBranch() {}
method getDefaultBranch (line 253) | getDefaultBranch() {
method getBaseDomain (line 267) | getBaseDomain({ spec }) {
method getPublicSuffix (line 270) | getPublicSuffix() {}
method init (line 286) | init() {
method createNullPrincipal (line 308) | createNullPrincipal() {}
method getSystemPrincipal (line 309) | getSystemPrincipal() {}
method registerNotification (line 316) | registerNotification() {}
method unregisterNotification (line 316) | unregisterNotification() {}
method defineLazyGetter (line 320) | defineLazyGetter(object, name, f) {
method defineLazyGlobalGetters (line 327) | defineLazyGlobalGetters() {}
method defineLazyModuleGetter (line 328) | defineLazyModuleGetter() {}
method defineLazyModuleGetters (line 329) | defineLazyModuleGetters() {}
method defineLazyServiceGetter (line 330) | defineLazyServiceGetter() {}
method defineLazyServiceGetters (line 331) | defineLazyServiceGetters() {}
method defineLazyPreferenceGetter (line 332) | defineLazyPreferenceGetter(obj, name) {
method generateQI (line 338) | generateQI() {
method eval (line 345) | eval() {
method RemoteSettings (line 349) | RemoteSettings(name) {
method formatMessages (line 361) | async formatMessages(stringsIds) {
method promiseConnectAccountURI (line 368) | promiseConnectAccountURI(id) {
method setExperimentActive (line 373) | setExperimentActive() {}
method ratioSample (line 376) | ratioSample(seed, ratios) {
method kiosk (line 381) | get kiosk() {
FILE: test/unit/utils.js
class GlobalOverrider (line 5) | class GlobalOverrider {
method constructor (line 6) | constructor() {
method _override (line 19) | _override(key, value) {
method set (line 34) | set(key, value) {
method reset (line 48) | reset() {
method restore (line 56) | restore() {
class FakensIPrefBranch (line 74) | class FakensIPrefBranch {
method constructor (line 75) | constructor(args) {
method addObserver (line 87) | addObserver(prefName, callback) {
method removeObserver (line 90) | removeObserver(prefName, callback) {
method observeBranch (line 95) | observeBranch(listener) {}
method ignoreBranch (line 96) | ignoreBranch(listener) {}
method setStringPref (line 97) | setStringPref(prefName) {}
method getStringPref (line 99) | getStringPref(prefName) {
method getBoolPref (line 102) | getBoolPref(prefName) {
method get (line 105) | get(prefName) {
method setBoolPref (line 108) | setBoolPref(prefName, value) {
class FakePrefs (line 122) | class FakePrefs extends FakensIPrefBranch {
method observe (line 123) | observe(prefName, callback) {
method ignore (line 126) | ignore(prefName, callback) {
method set (line 129) | set(prefName, value) {
function EventEmitter (line 141) | function EventEmitter() {}
method on (line 150) | on(event, listener) {
method off (line 159) | off(event, listener) {
method once (line 173) | once(event, listener) {
method emit (line 188) | emit(event, ...args) {
function FakePerformance (line 218) | function FakePerformance() {}
method now (line 221) | now() {
method timeOrigin (line 225) | get timeOrigin() {
method getEntriesByName (line 229) | getEntriesByName(name, type) {
method mark (line 241) | mark(name) {
function addNumberReducer (line 261) | function addNumberReducer(prevState = 0, action) {
FILE: test/xpcshell/test_AboutNewTabService.js
constant IS_RELEASE_OR_BETA (line 21) | const IS_RELEASE_OR_BETA = AppConstants.RELEASE_OR_BETA;
constant DOWNLOADS_URL (line 23) | const DOWNLOADS_URL =
constant SEPARATE_PRIVILEGED_CONTENT_PROCESS_PREF (line 25) | const SEPARATE_PRIVILEGED_CONTENT_PROCESS_PREF =
constant ACTIVITY_STREAM_DEBUG_PREF (line 27) | const ACTIVITY_STREAM_DEBUG_PREF = "browser.newtabpage.activity-stream.d...
function cleanup (line 29) | function cleanup() {
constant ACTIVITY_STREAM_URL (line 37) | let ACTIVITY_STREAM_URL;
constant ACTIVITY_STREAM_DEBUG_URL (line 38) | let ACTIVITY_STREAM_DEBUG_URL;
function setExpectedUrlsWithScripts (line 40) | function setExpectedUrlsWithScripts() {
function setExpectedUrlsWithoutScripts (line 47) | function setExpectedUrlsWithoutScripts() {
function nextChangeNotificationPromise (line 55) | function nextChangeNotificationPromise(aNewURL, testMessage) {
function setPrivilegedContentProcessPref (line 66) | function setPrivilegedContentProcessPref(usePrivilegedContentProcess) {
function addTestsWithPrivilegedContentProcessPref (line 85) | function addTestsWithPrivilegedContentProcessPref(test) {
function setBoolPrefAndWaitForChange (line 98) | function setBoolPrefAndWaitForChange(pref, value, testMessage) {
FILE: vendor/prop-types.js
function s (line 1) | function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&re...
function e (line 1) | function e(e,r,t,n,p,o){o!==ReactPropTypesSecret&&invariant(!1,"Calling ...
function r (line 1) | function r(){return e}
function makeEmptyFunction (line 1) | function makeEmptyFunction(arg){return function(){return arg}}
function invariant (line 1) | function invariant(condition,format,a,b,c,d,e,f){if(validateFormat(forma...
FILE: vendor/react-dev.js
function getIteratorFn (line 43) | function getIteratorFn(maybeIterable) {
function toObject (line 66) | function toObject(val) {
function shouldUseNative (line 74) | function shouldUseNative() {
function invariant (line 166) | function invariant(condition, format, a, b, c, d, e, f) {
function warnNoop (line 295) | function warnNoop(publicInstance, callerName) {
function Component (line 384) | function Component(props, context, updater) {
function ComponentDummy (line 469) | function ComponentDummy() {}
function PureComponent (line 475) | function PureComponent(props, context, updater) {
function createRef (line 490) | function createRef() {
function ensureHostCallbackIsScheduled (line 543) | function ensureHostCallbackIsScheduled() {
function flushFirstCallback (line 559) | function flushFirstCallback() {
function flushImmediateWork (line 642) | function flushImmediateWork() {
function flushWork (line 665) | function flushWork(didTimeout) {
function unstable_runWithPriority (line 717) | function unstable_runWithPriority(priorityLevel, eventHandler) {
function unstable_next (line 745) | function unstable_next(eventHandler) {
function unstable_wrapCallback (line 776) | function unstable_wrapCallback(callback) {
function unstable_scheduleCallback (line 795) | function unstable_scheduleCallback(callback, deprecated_options) {
function unstable_pauseExecution (line 868) | function unstable_pauseExecution() {
function unstable_continueExecution (line 872) | function unstable_continueExecution() {
function unstable_getFirstCallbackNode (line 879) | function unstable_getFirstCallbackNode() {
function unstable_cancelCallback (line 883) | function unstable_cancelCallback(callbackNode) {
function unstable_getCurrentPriorityLevel (line 906) | function unstable_getCurrentPriorityLevel() {
function unstable_shouldYield (line 910) | function unstable_shouldYield() {
function unstable_clear (line 1228) | function unstable_clear(callback) {
function unstable_getCurrent (line 1243) | function unstable_getCurrent() {
function unstable_getThreadID (line 1251) | function unstable_getThreadID() {
function unstable_trace (line 1255) | function unstable_trace(name, timestamp, callback) {
function unstable_wrap (line 1316) | function unstable_wrap(callback) {
function unstable_subscribe (line 1414) | function unstable_subscribe(subscriber) {
function unstable_unsubscribe (line 1431) | function unstable_unsubscribe(subscriber) {
function onInteractionTraced (line 1441) | function onInteractionTraced(interaction) {
function onInteractionScheduledWorkCompleted (line 1461) | function onInteractionScheduledWorkCompleted(interaction) {
function onWorkScheduled (line 1481) | function onWorkScheduled(interactions, threadID) {
function onWorkStarted (line 1501) | function onWorkStarted(interactions, threadID) {
function onWorkStopped (line 1521) | function onWorkStopped(interactions, threadID) {
function onWorkCanceled (line 1541) | function onWorkCanceled(interactions, threadID) {
function refineResolvedLazyComponent (line 1617) | function refineResolvedLazyComponent(lazyComponent) {
function getWrappedName (line 1621) | function getWrappedName(outerType, innerType, wrapperName) {
function getComponentName (line 1626) | function getComponentName(type) {
function setCurrentlyValidatingElement (line 1683) | function setCurrentlyValidatingElement(element) {
function hasValidRef (line 1809) | function hasValidRef(config) {
function hasValidKey (line 1821) | function hasValidKey(config) {
function defineKeyPropWarningGetter (line 1833) | function defineKeyPropWarningGetter(props, displayName) {
function defineRefPropWarningGetter (line 1847) | function defineRefPropWarningGetter(props, displayName) {
function createElement (line 1941) | function createElement(type, config, children) {
function cloneAndReplaceKey (line 2017) | function cloneAndReplaceKey(oldElement, newKey) {
function cloneElement (line 2027) | function cloneElement(element, config, children) {
function isValidElement (line 2098) | function isValidElement(object) {
function escape (line 2111) | function escape(key) {
function escapeUserProvidedKey (line 2132) | function escapeUserProvidedKey(text) {
function getPooledTraverseContext (line 2138) | function getPooledTraverseContext(mapResult, keyPrefix, mapFunction, map...
function releaseTraverseContext (line 2158) | function releaseTraverseContext(traverseContext) {
function traverseAllChildrenImpl (line 2177) | function traverseAllChildrenImpl(children, nameSoFar, callback, traverse...
function traverseAllChildren (line 2271) | function traverseAllChildren(children, callback, traverseContext) {
function getComponentKey (line 2286) | function getComponentKey(component, index) {
function forEachSingleChild (line 2297) | function forEachSingleChild(bookKeeping, child, name) {
function forEachChildren (line 2316) | function forEachChildren(children, forEachFunc, forEachContext) {
function mapSingleChildIntoContext (line 2325) | function mapSingleChildIntoContext(bookKeeping, child, childKey) {
function mapIntoWithKeyPrefixInternal (line 2348) | function mapIntoWithKeyPrefixInternal(children, array, prefix, func, con...
function mapChildren (line 2371) | function mapChildren(children, func, context) {
function countChildren (line 2389) | function countChildren(children) {
function toArray (line 2401) | function toArray(children) {
function onlyChild (line 2423) | function onlyChild(children) {
function createContext (line 2428) | function createContext(defaultValue, calculateChangedBits) {
function lazy (line 2532) | function lazy(ctor) {
function forwardRef (line 2580) | function forwardRef(render) {
function isValidElementType (line 2603) | function isValidElementType(type) {
function memo (line 2609) | function memo(type, compare) {
function resolveDispatcher (line 2622) | function resolveDispatcher() {
function useContext (line 2628) | function useContext(Context, unstable_observedBits) {
function useState (line 2648) | function useState(initialState) {
function useReducer (line 2653) | function useReducer(reducer, initialArg, init) {
function useRef (line 2658) | function useRef(initialValue) {
function useEffect (line 2663) | function useEffect(create, inputs) {
function useLayoutEffect (line 2668) | function useLayoutEffect(create, inputs) {
function useCallback (line 2673) | function useCallback(callback, inputs) {
function useMemo (line 2678) | function useMemo(create, inputs) {
function useImperativeHandle (line 2683) | function useImperativeHandle(ref, create, inputs) {
function useDebugValue (line 2688) | function useDebugValue(value, formatterFn) {
function checkPropTypes (line 2748) | function checkPropTypes(typeSpecs, values, location, componentName, getS...
function getDeclarationErrorAddendum (line 2813) | function getDeclarationErrorAddendum() {
function getSourceInfoErrorAddendum (line 2823) | function getSourceInfoErrorAddendum(elementProps) {
function getCurrentComponentErrorInfo (line 2840) | function getCurrentComponentErrorInfo(parentType) {
function validateExplicitKey (line 2863) | function validateExplicitKey(element, parentType) {
function validateChildKeys (line 2900) | function validateChildKeys(node, parentType) {
function validatePropTypes (line 2940) | function validatePropTypes(element) {
function validateFragmentProps (line 2974) | function validateFragmentProps(fragment) {
function createElementWithValidation (line 2993) | function createElementWithValidation(type, props, children) {
function createFactoryWithValidation (line 3054) | function createFactoryWithValidation(type) {
function cloneElementWithValidation (line 3074) | function cloneElementWithValidation(element, props, children) {
FILE: vendor/react-dom-dev.js
function invariant (line 39) | function invariant(condition, format, a, b, c, d, e, f) {
function callCallback (line 128) | function callCallback() {
function handleWindowError (line 163) | function handleWindowError(event) {
function invokeGuardedCallback (line 247) | function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) {
function invokeGuardedCallbackAndCatchFirstError (line 263) | function invokeGuardedCallbackAndCatchFirstError(name, func, context, a,...
function rethrowCaughtError (line 278) | function rethrowCaughtError() {
function hasCaughtError (line 287) | function hasCaughtError() {
function clearCaughtError (line 291) | function clearCaughtError() {
function recomputePluginOrdering (line 317) | function recomputePluginOrdering() {
function publishEventForPlugin (line 346) | function publishEventForPlugin(dispatchConfig, pluginModule, eventName) {
function publishRegistrationName (line 373) | function publishRegistrationName(registrationName, pluginModule, eventNa...
function injectEventPluginOrder (line 432) | function injectEventPluginOrder(injectedEventPluginOrder) {
function injectEventPluginsByName (line 449) | function injectEventPluginsByName(injectedNamesToPlugins) {
function setComponentTree (line 521) | function setComponentTree(getFiberCurrentPropsFromNodeImpl, getInstanceF...
function executeDispatch (line 552) | function executeDispatch(event, listener, inst) {
function executeDispatchesInOrder (line 562) | function executeDispatchesInOrder(event) {
function accumulateInto (line 617) | function accumulateInto(current, next) {
function forEachAccumulated (line 652) | function forEachAccumulated(arr, cb, scope) {
function isInteractive (line 685) | function isInteractive(tag) {
function shouldPreventMouseEvent (line 689) | function shouldPreventMouseEvent(name, type, props) {
function getListener (line 751) | function getListener(inst, registrationName) {
function extractEvents (line 781) | function extractEvents(topLevelType, targetInst, nativeEvent, nativeEven...
function runEventsInBatch (line 796) | function runEventsInBatch(events) {
function runExtractedEventsInBatch (line 816) | function runExtractedEventsInBatch(topLevelType, targetInst, nativeEvent...
function precacheFiberNode (line 845) | function precacheFiberNode(hostInst, node) {
function getClosestInstanceFromNode (line 853) | function getClosestInstanceFromNode(node) {
function getInstanceFromNode$1 (line 881) | function getInstanceFromNode$1(node) {
function getNodeFromInstance$1 (line 897) | function getNodeFromInstance$1(inst) {
function getFiberCurrentPropsFromNode$1 (line 909) | function getFiberCurrentPropsFromNode$1(node) {
function updateFiberProps (line 913) | function updateFiberProps(node, props) {
function getParent (line 917) | function getParent(inst) {
function getLowestCommonAncestor (line 936) | function getLowestCommonAncestor(instA, instB) {
function traverseTwoPhase (line 983) | function traverseTwoPhase(inst, fn, arg) {
function traverseEnterLeave (line 1005) | function traverseEnterLeave(from, to, fn, argFrom, argTo) {
function listenerAtPhase (line 1049) | function listenerAtPhase(inst, event, propagationPhase) {
function accumulateDirectionalDispatches (line 1070) | function accumulateDirectionalDispatches(inst, phase, event) {
function accumulateTwoPhaseDispatchesSingle (line 1088) | function accumulateTwoPhaseDispatchesSingle(event) {
function accumulateDispatches (line 1099) | function accumulateDispatches(inst, ignoredDirection, event) {
function accumulateDirectDispatchesSingle (line 1115) | function accumulateDirectDispatchesSingle(event) {
function accumulateTwoPhaseDispatches (line 1121) | function accumulateTwoPhaseDispatches(events) {
function accumulateEnterLeaveDispatches (line 1127) | function accumulateEnterLeaveDispatches(leave, enter, from, to) {
function accumulateDirectDispatches (line 1131) | function accumulateDirectDispatches(events) {
function unsafeCastStringToDOMTopLevelType (line 1141) | function unsafeCastStringToDOMTopLevelType(topLevelType) {
function unsafeCastDOMTopLevelTypeToString (line 1145) | function unsafeCastDOMTopLevelTypeToString(topLevelType) {
function makePrefixMap (line 1156) | function makePrefixMap(styleProp, eventName) {
function getVendorPrefixedEventName (line 1214) | function getVendorPrefixedEventName(eventName) {
function getRawEventName (line 1327) | function getRawEventName(topLevelType) {
function initialize (line 1347) | function initialize(nativeEventTarget) {
function reset (line 1353) | function reset() {
function getData (line 1359) | function getData() {
function getText (line 1389) | function getText() {
function functionThatReturnsTrue (line 1425) | function functionThatReturnsTrue() {
function functionThatReturnsFalse (line 1429) | function functionThatReturnsFalse() {
function SyntheticEvent (line 1451) | function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeE...
function Class (line 1586) | function Class() {
function getPooledWarningPropertyDefinition (line 1609) | function getPooledWarningPropertyDefinition(propName, getVal) {
function getPooledEvent (line 1636) | function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeI...
function releasePooledEvent (line 1646) | function releasePooledEvent(event) {
function addEventPoolingTo (line 1655) | function addEventPoolingTo(EventConstructor) {
function isKeypressCommand (line 1741) | function isKeypressCommand(nativeEvent) {
function getCompositionEventType (line 1753) | function getCompositionEventType(topLevelType) {
function isFallbackCompositionStart (line 1772) | function isFallbackCompositionStart(topLevelType, nativeEvent) {
function isFallbackCompositionEnd (line 1783) | function isFallbackCompositionEnd(topLevelType, nativeEvent) {
function getDataFromCustomEvent (line 1811) | function getDataFromCustomEvent(nativeEvent) {
function isUsingKoreanIME (line 1829) | function isUsingKoreanIME(nativeEvent) {
function extractCompositionEvent (line 1839) | function extractCompositionEvent(topLevelType, targetInst, nativeEvent, ...
function getNativeBeforeInputChars (line 1891) | function getNativeBeforeInputChars(topLevelType, nativeEvent) {
function getFallbackBeforeInputChars (line 1945) | function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
function extractBeforeInputEvent (line 2009) | function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, ...
function restoreStateOfTarget (line 2075) | function restoreStateOfTarget(target) {
function setRestoreImplementation (line 2088) | function setRestoreImplementation(impl) {
function enqueueStateRestore (line 2092) | function enqueueStateRestore(target) {
function needsStateRestore (line 2104) | function needsStateRestore() {
function restoreStateIfNeeded (line 2108) | function restoreStateIfNeeded() {
function batchedUpdates (line 2141) | function batchedUpdates(fn, bookkeeping) {
function interactiveUpdates (line 2167) | function interactiveUpdates(fn, a, b) {
function setBatchingImplementation (line 2173) | function setBatchingImplementation(batchedUpdatesImpl, interactiveUpdate...
function isTextInputElement (line 2200) | function isTextInputElement(elem) {
function getEventTarget (line 2231) | function getEventTarget(nativeEvent) {
function isEventSupported (line 2259) | function isEventSupported(eventNameSuffix) {
function isCheckable (line 2276) | function isCheckable(elem) {
function getTracker (line 2282) | function getTracker(node) {
function detachTracker (line 2286) | function detachTracker(node) {
function getValueFromNode (line 2290) | function getValueFromNode(node) {
function trackValueOnNode (line 2305) | function trackValueOnNode(node) {
function track (line 2354) | function track(node) {
function updateValueIfChanged (line 2363) | function updateValueIfChanged(node) {
function getIteratorFn (line 2444) | function getIteratorFn(maybeIterable) {
function refineResolvedLazyComponent (line 2459) | function refineResolvedLazyComponent(lazyComponent) {
function getWrappedName (line 2463) | function getWrappedName(outerType, innerType, wrapperName) {
function getComponentName (line 2468) | function getComponentName(type) {
function describeFiber (line 2523) | function describeFiber(fiber) {
function getStackByFiberInDevAndProd (line 2544) | function getStackByFiberInDevAndProd(workInProgress) {
function getCurrentFiberOwnerNameInDevOrNull (line 2557) | function getCurrentFiberOwnerNameInDevOrNull() {
function getCurrentFiberStackInDev (line 2570) | function getCurrentFiberStackInDev() {
function resetCurrentFiber (line 2582) | function resetCurrentFiber() {
function setCurrentFiber (line 2590) | function setCurrentFiber(fiber) {
function setCurrentPhase (line 2598) | function setCurrentPhase(lifeCyclePhase) {
function isAttributeNameSafe (line 2678) | function isAttributeNameSafe(attributeName) {
function shouldIgnoreAttribute (line 2696) | function shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag) {
function shouldRemoveAttributeWithWarning (line 2709) | function shouldRemoveAttributeWithWarning(name, value, propertyInfo, isC...
function shouldRemoveAttribute (line 2736) | function shouldRemoveAttribute(name, value, propertyInfo, isCustomCompon...
function getPropertyInfo (line 2761) | function getPropertyInfo(name) {
function PropertyInfoRecord (line 2765) | function PropertyInfoRecord(name, type, mustUseProperty, attributeName, ...
function getValueForProperty (line 2920) | function getValueForProperty(node, name, expected, propertyInfo) {
function getValueForAttribute (line 2979) | function getValueForAttribute(node, name, expected) {
function setValueForProperty (line 3002) | function setValueForProperty(node, name, value, isCustomComponentTag) {
function toString (line 3066) | function toString(value) {
function getToStringValue (line 3070) | function getToStringValue(value) {
function checkPropTypes (line 3137) | function checkPropTypes(typeSpecs, values, location, componentName, getS...
function isControlled (line 3281) | function isControlled(props) {
function getHostProps (line 3303) | function getHostProps(element, props) {
function initWrapperState (line 3317) | function initWrapperState(element, props) {
function updateChecked (line 3341) | function updateChecked(element, props) {
function updateWrapper (line 3349) | function updateWrapper(element, props) {
function postMountWrapper (line 3425) | function postMountWrapper(element, props, isHydrating) {
function restoreControlledState (line 3533) | function restoreControlledState(element, props) {
function updateNamedCousins (line 3539) | function updateNamedCousins(rootNode, props) {
function setDefaultValue (line 3589) | function setDefaultValue(node, type, value) {
function createAndAccumulateChangeEvent (line 3611) | function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
function shouldUseChangeEvent (line 3628) | function shouldUseChangeEvent(elem) {
function manualDispatchChangeEvent (line 3633) | function manualDispatchChangeEvent(nativeEvent) {
function runEventInBatch (line 3650) | function runEventInBatch(event) {
function getInstIfValueChanged (line 3654) | function getInstIfValueChanged(targetInst) {
function getTargetInstForChangeEvent (line 3661) | function getTargetInstForChangeEvent(topLevelType, targetInst) {
function startWatchingForValueChange (line 3682) | function startWatchingForValueChange(target, targetInst) {
function stopWatchingForValueChange (line 3692) | function stopWatchingForValueChange() {
function handlePropertyChange (line 3705) | function handlePropertyChange(nativeEvent) {
function handleEventsForInputEventPolyfill (line 3714) | function handleEventsForInputEventPolyfill(topLevelType, target, targetI...
function getTargetInstForInputEventPolyfill (line 3734) | function getTargetInstForInputEventPolyfill(topLevelType, targetInst) {
function shouldUseClickEvent (line 3753) | function shouldUseClickEvent(elem) {
function getTargetInstForClickEvent (line 3761) | function getTargetInstForClickEvent(topLevelType, targetInst) {
function getTargetInstForInputOrChangeEvent (line 3767) | function getTargetInstForInputOrChangeEvent(topLevelType, targetInst) {
function handleControlledInputBlur (line 3773) | function handleControlledInputBlur(node) {
function modifierStateGetter (line 3869) | function modifierStateGetter(keyArg) {
function getEventModifierState (line 3879) | function getEventModifierState(nativeEvent) {
function is (line 4072) | function is(x, y) {
function shallowEqual (line 4084) | function shallowEqual(objA, objB) {
function get (line 4127) | function get(key) {
function has (line 4131) | function has(key) {
function set (line 4135) | function set(key, value) {
function isFiberMountedImpl (line 4170) | function isFiberMountedImpl(fiber) {
function isFiberMounted (line 4199) | function isFiberMounted(fiber) {
function isMounted (line 4203) | function isMounted(component) {
function assertIsMounted (line 4221) | function assertIsMounted(fiber) {
function findCurrentFiberUsingSlowPath (line 4225) | function findCurrentFiberUsingSlowPath(fiber) {
function findCurrentHostFiber (line 4337) | function findCurrentHostFiber(parent) {
function findCurrentHostFiberWithNoPortals (line 4370) | function findCurrentHostFiberWithNoPortals(parent) {
function addEventBubbleListener (line 4403) | function addEventBubbleListener(element, eventType, listener) {
function addEventCaptureListener (line 4407) | function addEventCaptureListener(element, eventType, listener) {
function getEventCharCode (line 4450) | function getEventCharCode(nativeEvent) {
function getEventKey (line 4548) | function getEventKey(nativeEvent) {
function addEventTypeNameToConfig (line 4712) | function addEventTypeNameToConfig(_ref, isInteractive) {
function findRootContainerNode (line 4865) | function findRootContainerNode(inst) {
function getTopLevelCallbackBookKeeping (line 4880) | function getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targe...
function releaseTopLevelCallbackBookKeeping (line 4896) | function releaseTopLevelCallbackBookKeeping(instance) {
function handleTopLevel (line 4906) | function handleTopLevel(bookKeeping) {
function setEnabled (line 4936) | function setEnabled(enabled) {
function isEnabled (line 4940) | function isEnabled() {
function trapBubbledEvent (line 4953) | function trapBubbledEvent(topLevelType, element) {
function trapCapturedEvent (line 4973) | function trapCapturedEvent(topLevelType, element) {
function dispatchInteractiveEvent (line 4984) | function dispatchInteractiveEvent(topLevelType, nativeEvent) {
function dispatchEvent (line 4988) | function dispatchEvent(topLevelType, nativeEvent) {
function getListeningForDocument (line 5078) | function getListeningForDocument(mountAt) {
function listenTo (line 5109) | function listenTo(registrationName, mountAt) {
function isListeningToAllDependencies (line 5155) | function isListeningToAllDependencies(registrationName, mountAt) {
function getActiveElement (line 5167) | function getActiveElement(doc) {
function getLeafNode (line 5185) | function getLeafNode(node) {
function getSiblingNode (line 5199) | function getSiblingNode(node) {
function getNodeForCharacterOffset (line 5215) | function getNodeForCharacterOffset(root, offset) {
function getOffsets (line 5242) | function getOffsets(outerNode) {
function getModernOffsetsFromPoints (line 5286) | function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset,...
function setOffsets (line 5367) | function setOffsets(node, offsets) {
function isTextNode (line 5412) | function isTextNode(node) {
function containsNode (line 5416) | function containsNode(outerNode, innerNode) {
function isInDocument (line 5434) | function isInDocument(node) {
function isSameOriginFrame (line 5438) | function isSameOriginFrame(iframe) {
function getActiveElementDeep (line 5454) | function getActiveElementDeep() {
function hasSelectionCapabilities (line 5480) | function hasSelectionCapabilities(elem) {
function getSelectionInformation (line 5485) | function getSelectionInformation() {
function restoreSelection (line 5498) | function restoreSelection(priorSelectionInformation) {
function getSelection$1 (line 5538) | function getSelection$1(input) {
function setSelection (line 5561) | function setSelection(input, offsets) {
function getSelection (line 5603) | function getSelection(node) {
function getEventTargetDocument (line 5627) | function getEventTargetDocument(eventTarget) {
function constructSelectEvent (line 5638) | function constructSelectEvent(nativeEvent, nativeEventTarget) {
function flattenChildren (line 5762) | function flattenChildren(children) {
function validateProps (line 5787) | function validateProps(element, props) {
function postMountWrapper$1 (line 5819) | function postMountWrapper$1(element, props) {
function getHostProps$1 (line 5826) | function getHostProps$1(element, props) {
function getDeclarationErrorAddendum (line 5844) | function getDeclarationErrorAddendum() {
function checkSelectPropTypes (line 5857) | function checkSelectPropTypes(props) {
function updateOptions (line 5874) | function updateOptions(node, multiple, propValue, setDefaultSelected) {
function getHostProps$2 (line 5932) | function getHostProps$2(element, props) {
function initWrapperState$1 (line 5938) | function initWrapperState$1(element, props) {
function postMountWrapper$2 (line 5956) | function postMountWrapper$2(element, props) {
function postUpdateWrapper (line 5967) | function postUpdateWrapper(element, props) {
function restoreControlledState$2 (line 5986) | function restoreControlledState$2(element, props) {
function getHostProps$3 (line 6013) | function getHostProps$3(element, props) {
function initWrapperState$2 (line 6032) | function initWrapperState$2(element, props) {
function updateWrapper$1 (line 6072) | function updateWrapper$1(element, props) {
function postMountWrapper$3 (line 6093) | function postMountWrapper$3(element, props) {
function restoreControlledState$3 (line 6108) | function restoreControlledState$3(element, props) {
function getIntrinsicNamespace (line 6124) | function getIntrinsicNamespace(type) {
function getChildNamespace (line 6135) | function getChildNamespace(parentNamespace, type) {
function prefixKey (line 6324) | function prefixKey(prefix, key) {
function dangerousStyleValue (line 6351) | function dangerousStyleValue(name, value, isCustomProperty) {
function hyphenateStyleName (line 6390) | function hyphenateStyleName(name) {
function createDangerousStringForStyles (line 6496) | function createDangerousStringForStyles(styles) {
function setValueForStyles (line 6524) | function setValueForStyles(node, styles) {
function isValueEmpty (line 6548) | function isValueEmpty(value) {
function expandShorthandMap (line 6560) | function expandShorthandMap(styles) {
function validateShorthandPropertyCollisionInDev (line 6585) | function validateShorthandPropertyCollisionInDev(styleUpdates, nextStyle...
function assertValidProps (line 6649) | function assertValidProps(tag, props) {
function isCustomComponent (line 6667) | function isCustomComponent(tagName, props) {
function validateProperty (line 7240) | function validateProperty(tagName, name) {
function warnInvalidARIAProps (line 7285) | function warnInvalidARIAProps(type, props) {
function validateProperties (line 7306) | function validateProperties(type, props) {
function validateProperties$1 (line 7315) | function validateProperties$1(type, props) {
function validateProperties$2 (line 7479) | function validateProperties$2(type, props, canUseEventSystem) {
function ensureListeningTo (line 7619) | function ensureListeningTo(rootContainerElement, registrationName) {
function getOwnerDocumentFromRootContainer (line 7625) | function getOwnerDocumentFromRootContainer(rootContainerElement) {
function noop (line 7629) | function noop() {}
function trapClickOnNonInteractiveElement (line 7631) | function trapClickOnNonInteractiveElement(node) {
function setInitialDOMProperties (line 7644) | function setInitialDOMProperties(tag, domElement, rootContainerElement, ...
function updateDOMProperties (line 7698) | function updateDOMProperties(domElement, updatePayload, wasCustomCompone...
function createElement (line 7715) | function createElement(type, props, rootContainerElement, parentNamespac...
function createTextNode (line 7787) | function createTextNode(text, rootContainerElement) {
function setInitialProperties (line 7791) | function setInitialProperties(domElement, tag, rawProps, rootContainerEl...
function diffProperties (line 7902) | function diffProperties(domElement, tag, lastRawProps, nextRawProps, roo...
function updateProperties (line 8070) | function updateProperties(domElement, updatePayload, tag, lastRawProps, ...
function getPossibleStandardName (line 8103) | function getPossibleStandardName(propName) {
function diffHydratedProperties (line 8114) | function diffHydratedProperties(domElement, tag, rawProps, parentNamespa...
function diffHydratedText (line 8366) | function diffHydratedText(textNode, text) {
function warnForUnmatchedText (line 8371) | function warnForUnmatchedText(textNode, text) {
function warnForDeletedHydratableElement (line 8377) | function warnForDeletedHydratableElement(parentNode, child) {
function warnForDeletedHydratableText (line 8387) | function warnForDeletedHydratableText(parentNode, child) {
function warnForInsertedHydratedElement (line 8397) | function warnForInsertedHydratedElement(parentNode, tag, props) {
function warnForInsertedHydratedText (line 8407) | function warnForInsertedHydratedText(parentNode, text) {
function restoreControlledState$1 (line 8424) | function restoreControlledState$1(domElement, tag, props) {
function shim (line 8756) | function shim() {
function shouldAutoFocusHostComponent (line 8784) | function shouldAutoFocusHostComponent(type, props) {
function getRootHostContext (line 8795) | function getRootHostContext(rootContainerInstance) {
function getChildHostContext (line 8825) | function getChildHostContext(parentHostContext, type, rootContainerInsta...
function getPublicInstance (line 8836) | function getPublicInstance(instance) {
function prepareForCommit (line 8840) | function prepareForCommit(containerInfo) {
function resetAfterCommit (line 8846) | function resetAfterCommit(containerInfo) {
function createInstance (line 8853) | function createInstance(type, props, rootContainerInstance, hostContext,...
function appendInitialChild (line 8872) | function appendInitialChild(parentInstance, child) {
function finalizeInitialChildren (line 8876) | function finalizeInitialChildren(domElement, type, props, rootContainerI...
function prepareUpdate (line 8881) | function prepareUpdate(domElement, type, oldProps, newProps, rootContain...
function shouldSetTextContent (line 8893) | function shouldSetTextContent(type, props) {
function shouldDeprioritizeSubtree (line 8897) | function shouldDeprioritizeSubtree(type, props) {
function createTextInstance (line 8901) | function createTextInstance(text, rootContainerInstance, hostContext, in...
function commitMount (line 8927) | function commitMount(domElement, type, newProps, internalInstanceHandle) {
function commitUpdate (line 8939) | function commitUpdate(domElement, updatePayload, type, oldProps, newProp...
function resetTextContent (line 8947) | function resetTextContent(domElement) {
function commitTextUpdate (line 8951) | function commitTextUpdate(textInstance, oldText, newText) {
function appendChild (line 8955) | function appendChild(parentInstance, child) {
function appendChildToContainer (line 8959) | function appendChildToContainer(container, child) {
function insertBefore (line 8983) | function insertBefore(parentInstance, child, beforeChild) {
function insertInContainerBefore (line 8987) | function insertInContainerBefore(container, child, beforeChild) {
function removeChild (line 8995) | function removeChild(parentInstance, child) {
function removeChildFromContainer (line 8999) | function removeChildFromContainer(container, child) {
function clearSuspenseBoundary (line 9007) | function clearSuspenseBoundary(parentInstance, suspenseInstance) {
function clearSuspenseBoundaryFromContainer (line 9034) | function clearSuspenseBoundaryFromContainer(container, suspenseInstance) {
function hideInstance (line 9044) | function hideInstance(instance) {
function hideTextInstance (line 9051) | function hideTextInstance(textInstance) {
function unhideInstance (line 9055) | function unhideInstance(instance, props) {
function unhideTextInstance (line 9062) | function unhideTextInstance(textInstance, text) {
function canHydrateInstance (line 9072) | function canHydrateInstance(instance, type, props) {
function canHydrateTextInstance (line 9080) | function canHydrateTextInstance(instance, text) {
function canHydrateSuspenseInstance (line 9089) | function canHydrateSuspenseInstance(instance) {
function getNextHydratableSibling (line 9098) | function getNextHydratableSibling(instance) {
function getFirstHydratableChild (line 9107) | function getFirstHydratableChild(parentInstance) {
function hydrateInstance (line 9116) | function hydrateInstance(instance, type, props, rootContainerInstance, h...
function hydrateTextInstance (line 9129) | function hydrateTextInstance(textInstance, text, internalInstanceHandle) {
function getNextHydratableInstanceAfterSuspenseInstance (line 9134) | function getNextHydratableInstanceAfterSuspenseInstance(suspenseInstance) {
function didNotMatchHydratedContainerTextInstance (line 9159) | function didNotMatchHydratedContainerTextInstance(parentContainer, textI...
function didNotMatchHydratedTextInstance (line 9165) | function didNotMatchHydratedTextInstance(parentType, parentProps, parent...
function didNotHydrateContainerInstance (line 9171) | function didNotHydrateContainerInstance(parentContainer, instance) {
function didNotHydrateInstance (line 9183) | function didNotHydrateInstance(parentType, parentProps, parentInstance, ...
function didNotFindHydratableContainerInstance (line 9195) | function didNotFindHydratableContainerInstance(parentContainer, type, pr...
function didNotFindHydratableContainerTextInstance (line 9201) | function didNotFindHydratableContainerTextInstance(parentContainer, text) {
function didNotFindHydratableInstance (line 9209) | function didNotFindHydratableInstance(parentType, parentProps, parentIns...
function didNotFindHydratableTextInstance (line 9215) | function didNotFindHydratableTextInstance(parentType, parentProps, paren...
function didNotFindHydratableSuspenseInstance (line 9221) | function didNotFindHydratableSuspenseInstance(parentType, parentProps, p...
function recordEffect (line 9394) | function recordEffect() {
function recordScheduleUpdate (line 9400) | function recordScheduleUpdate() {
function startRequestCallbackTimer (line 9411) | function startRequestCallbackTimer() {
function stopRequestCallbackTimer (line 9420) | function stopRequestCallbackTimer(didExpire, expirationTime) {
function startWorkTimer (line 9430) | function startWorkTimer(fiber) {
function cancelWorkTimer (line 9444) | function cancelWorkTimer(fiber) {
function stopWorkTimer (line 9456) | function stopWorkTimer(fiber) {
function stopFailedWorkTimer (line 9471) | function stopFailedWorkTimer(fiber) {
function startPhaseTimer (line 9487) | function startPhaseTimer(fiber, phase) {
function stopPhaseTimer (line 9501) | function stopPhaseTimer() {
function startWorkLoopTimer (line 9515) | function startWorkLoopTimer(nextUnitOfWork) {
function stopWorkLoopTimer (line 9530) | function stopWorkLoopTimer(interruptedBy, didCompleteRoot) {
function startCommitTimer (line 9554) | function startCommitTimer() {
function stopCommitTimer (line 9566) | function stopCommitTimer() {
function startCommitSnapshotEffectsTimer (line 9587) | function startCommitSnapshotEffectsTimer() {
function stopCommitSnapshotEffectsTimer (line 9597) | function stopCommitSnapshotEffectsTimer() {
function startCommitHostEffectsTimer (line 9608) | function startCommitHostEffectsTimer() {
function stopCommitHostEffectsTimer (line 9618) | function stopCommitHostEffectsTimer() {
function startCommitLifeCyclesTimer (line 9629) | function startCommitLifeCyclesTimer() {
function stopCommitLifeCyclesTimer (line 9639) | function stopCommitLifeCyclesTimer() {
function createCursor (line 9660) | function createCursor(defaultValue) {
function pop (line 9666) | function pop(cursor, fiber) {
function push (line 9691) | function push(cursor, value, fiber) {
function checkThatStackIsEmpty (line 9703) | function checkThatStackIsEmpty() {
function resetStackAfterFatalErrorInDev (line 9711) | function resetStackAfterFatalErrorInDev() {
function getUnmaskedContext (line 9739) | function getUnmaskedContext(workInProgress, Component, didPushOwnContext...
function cacheContext (line 9750) | function cacheContext(workInProgress, unmaskedContext, maskedContext) {
function getMaskedContext (line 9756) | function getMaskedContext(workInProgress, unmaskedContext) {
function hasContextChanged (line 9790) | function hasContextChanged() {
function isContextProvider (line 9794) | function isContextProvider(type) {
function popContext (line 9799) | function popContext(fiber) {
function popTopLevelContextObject (line 9804) | function popTopLevelContextObject(fiber) {
function pushTopLevelContextObject (line 9809) | function pushTopLevelContextObject(fiber, context, didChange) {
function processChildContext (line 9816) | function processChildContext(fiber, type, parentContext) {
function pushContextProvider (line 9861) | function pushContextProvider(workInProgress) {
function invalidateContextProvider (line 9877) | function invalidateContextProvider(workInProgress, type, didChange) {
function findCurrentUnmaskedContext (line 9901) | function findCurrentUnmaskedContext(fiber) {
function catchErrors (line 9929) | function catchErrors(fn) {
function injectInternals (line 9944) | function injectInternals(internals) {
function onCommitRoot (line 9982) | function onCommitRoot(root) {
function onCommitUnmount (line 9988) | function onCommitUnmount(fiber) {
function msToExpirationTime (line 10007) | function msToExpirationTime(ms) {
function expirationTimeToMs (line 10012) | function expirationTimeToMs(expirationTime) {
function ceiling (line 10016) | function ceiling(num, precision) {
function computeExpirationBucket (line 10020) | function computeExpirationBucket(currentTime, expirationInMs, bucketSize...
function computeAsyncExpiration (line 10027) | function computeAsyncExpiration(currentTime) {
function computeInteractiveExpiration (line 10045) | function computeInteractiveExpiration(currentTime) {
function FiberNode (line 10083) | function FiberNode(tag, pendingProps, key, mode) {
function shouldConstruct (line 10176) | function shouldConstruct(Component) {
function isSimpleFunctionComponent (line 10181) | function isSimpleFunctionComponent(type) {
function resolveLazyComponentTag (line 10185) | function resolveLazyComponentTag(Component) {
function createWorkInProgress (line 10201) | function createWorkInProgress(current, pendingProps, expirationTime) {
function createHostRootFiber (line 10268) | function createHostRootFiber(isConcurrent) {
function createFiberFromTypeAndProps (line 10281) | function createFiberFromTypeAndProps(type, // React$ElementType
function createFiberFromElement (line 10352) | function createFiberFromElement(element, mode, expirationTime) {
function createFiberFromFragment (line 10368) | function createFiberFromFragment(elements, mode, expirationTime, key) {
function createFiberFromProfiler (line 10374) | function createFiberFromProfiler(pendingProps, mode, expirationTime, key) {
function createFiberFromMode (line 10390) | function createFiberFromMode(pendingProps, mode, expirationTime, key) {
function createFiberFromSuspense (line 10402) | function createFiberFromSuspense(pendingProps, mode, expirationTime, key) {
function createFiberFromText (line 10414) | function createFiberFromText(content, mode, expirationTime) {
function createFiberFromHostInstanceForDeletion (line 10420) | function createFiberFromHostInstanceForDeletion() {
function createFiberFromPortal (line 10428) | function createFiberFromPortal(portal, mode, expirationTime) {
function assignFiberPropertiesInDEV (line 10441) | function assignFiberPropertiesInDEV(target, source) {
function createFiberRoot (line 10520) | function createFiberRoot(containerInfo, isConcurrent, hydrate) {
function markPendingPriorityLevel (line 10899) | function markPendingPriorityLevel(root, expirationTime) {
function markCommittedPriorityLevels (line 10925) | function markCommittedPriorityLevels(root, earliestRemainingTime) {
function hasLowerPriorityWork (line 11000) | function hasLowerPriorityWork(root, erroredExpirationTime) {
function isPriorityLevelSuspended (line 11007) | function isPriorityLevelSuspended(root, expirationTime) {
function markSuspendedPriorityLevel (line 11013) | function markSuspendedPriorityLevel(root, suspendedTime) {
function markPingedPriorityLevel (line 11054) | function markPingedPriorityLevel(root, pingedTime) {
function clearPing (line 11067) | function clearPing(root, completedTime) {
function findEarliestOutstandingPriorityLevel (line 11074) | function findEarliestOutstandingPriorityLevel(root, renderExpirationTime) {
function didExpireAtExpirationTime (line 11088) | function didExpireAtExpirationTime(root, currentTime) {
function findNextExpirationTimeToWorkOn (line 11096) | function findNextExpirationTimeToWorkOn(completedExpirationTime, root) {
function resolveDefaultProps (line 11125) | function resolveDefaultProps(Component, baseProps) {
function readLazyComponentType (line 11140) | function readLazyComponentType(lazyComponent) {
function applyDerivedStateFromProps (line 11259) | function applyDerivedStateFromProps(workInProgress, ctor, getDerivedStat...
function checkShouldComponentUpdate (line 11347) | function checkShouldComponentUpdate(workInProgress, ctor, oldProps, newP...
function checkClassInstance (line 11368) | function checkClassInstance(workInProgress, ctor, newProps) {
function adoptClassInstance (line 11437) | function adoptClassInstance(workInProgress, instance) {
function constructClassInstance (line 11447) | function constructClassInstance(workInProgress, ctor, props, renderExpir...
function callComponentWillMount (line 11551) | function callComponentWillMount(workInProgress, instance) {
function callComponentWillReceiveProps (line 11572) | function callComponentWillReceiveProps(workInProgress, instance, newProp...
function mountClassInstance (line 11596) | function mountClassInstance(workInProgress, ctor, newProps, renderExpira...
function resumeMountClassInstance (line 11664) | function resumeMountClassInstance(workInProgress, ctor, newProps, render...
function updateClassInstance (line 11759) | function updateClassInstance(current, workInProgress, ctor, newProps, re...
function coerceRef (line 11913) | function coerceRef(returnFiber, current$$1, element) {
function throwOnInvalidObjectType (line 11962) | function throwOnInvalidObjectType(returnFiber, newChild) {
function warnOnFunctionType (line 11972) | function warnOnFunctionType() {
function ChildReconciler (line 11987) | function ChildReconciler(shouldTrackSideEffects) {
function cloneChildFibers (line 12786) | function cloneChildFibers(current$$1, workInProgress) {
function requiredContext (line 12812) | function requiredContext(c) {
function getRootHostContainer (line 12817) | function getRootHostContainer() {
function pushHostContainer (line 12822) | function pushHostContainer(fiber, nextRootInstance) {
function popHostContainer (line 12842) | function popHostContainer(fiber) {
function getHostContext (line 12848) | function getHostContext() {
function pushHostContext (line 12853) | function pushHostContext(fiber) {
function popHostContext (line 12869) | function popHostContext(fiber) {
function mountHookTypesDev (line 12942) | function mountHookTypesDev() {
function updateHookTypesDev (line 12954) | function updateHookTypesDev() {
function warnOnHookMismatchInDev (line 12967) | function warnOnHookMismatchInDev(currentHookName) {
function throwInvalidHookError (line 13001) | function throwInvalidHookError() {
function areHookInputsEqual (line 13005) | function areHookInputsEqual(nextDeps, prevDeps) {
function renderWithHooks (line 13029) | function renderWithHooks(current, workInProgress, Component, props, refO...
function bailoutHooks (line 13150) | function bailoutHooks(current, workInProgress, expirationTime) {
function resetHooks (line 13158) | function resetHooks() {
function mountWorkInProgressHook (line 13191) | function mountWorkInProgressHook() {
function updateWorkInProgressHook (line 13212) | function updateWorkInProgressHook() {
function createFunctionComponentUpdateQueue (line 13252) | function createFunctionComponentUpdateQueue() {
function basicStateReducer (line 13258) | function basicStateReducer(state, action) {
function mountReducer (line 13262) | function mountReducer(reducer, initialArg, init) {
function updateReducer (line 13283) | function updateReducer(reducer, initialArg, init) {
function mountState (line 13410) | function mountState(initialState) {
function updateState (line 13428) | function updateState(initialState) {
function pushEffect (line 13432) | function pushEffect(tag, create, destroy, deps) {
function mountRef (line 13458) | function mountRef(initialValue) {
function updateRef (line 13468) | function updateRef(initialValue) {
function mountEffectImpl (line 13473) | function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) {
function updateEffectImpl (line 13480) | function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) {
function mountEffect (line 13501) | function mountEffect(create, deps) {
function updateEffect (line 13505) | function updateEffect(create, deps) {
function mountLayoutEffect (line 13509) | function mountLayoutEffect(create, deps) {
function updateLayoutEffect (line 13513) | function updateLayoutEffect(create, deps) {
function imperativeHandleEffect (line 13517) | function imperativeHandleEffect(create, ref) {
function mountImperativeHandle (line 13538) | function mountImperativeHandle(ref, create, deps) {
function updateImperativeHandle (line 13549) | function updateImperativeHandle(ref, create, deps) {
function mountDebugValue (line 13560) | function mountDebugValue(value, formatterFn) {
function mountCallback (line 13568) | function mountCallback(callback, deps) {
function updateCallback (line 13575) | function updateCallback(callback, deps) {
function mountMemo (line 13591) | function mountMemo(nextCreate, deps) {
function updateMemo (line 13599) | function updateMemo(nextCreate, deps) {
function dispatchAction (line 13630) | function dispatchAction(fiber, queue, action) {
function getCommitTime (line 14164) | function getCommitTime() {
function recordCommitTime (line 14168) | function recordCommitTime() {
function startProfilerTimer (line 14175) | function startProfilerTimer(fiber) {
function stopProfilerTimerIfRunning (line 14187) | function stopProfilerTimerIfRunning(fiber) {
function stopProfilerTimerIfRunningAndRecordDelta (line 14194) | function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTim...
function enterHydrationState (line 14215) | function enterHydrationState(fiber) {
function reenterHydrationStateFromDehydratedSuspenseInstance (line 14227) | function reenterHydrationStateFromDehydratedSuspenseInstance(fiber) {
function deleteHydratableInstance (line 14239) | function deleteHydratableInstance(returnFiber, instance) {
function insertNonHydratedInstance (line 14269) | function insertNonHydratedInstance(returnFiber, fiber) {
function tryHydrate (line 14319) | function tryHydrate(fiber, nextInstance) {
function tryToClaimNextHydratableInstance (line 14360) | function tryToClaimNextHydratableInstance(fiber) {
function prepareToHydrateHostInstance (line 14395) | function prepareToHydrateHostInstance(fiber, rootContainerInstance, host...
function prepareToHydrateHostTextInstance (line 14412) | function prepareToHydrateHostTextInstance(fiber) {
function skipPastDehydratedSuspenseInstance (line 14448) | function skipPastDehydratedSuspenseInstance(fiber) {
function popToNextHostParent (line 14457) | function popToNextHostParent(fiber) {
function popHydrationState (line 14465) | function popHydrationState(fiber) {
function resetHydrationState (line 14503) | function resetHydrationState() {
function reconcileChildren (line 14531) | function reconcileChildren(current$$1, workInProgress, nextChildren, ren...
function forceUnmountCurrentAndReconcile (line 14549) | function forceUnmountCurrentAndReconcile(current$$1, workInProgress, nex...
function updateForwardRef (line 14566) | function updateForwardRef(current$$1, workInProgress, Component, nextPro...
function updateMemoComponent (line 14613) | function updateMemoComponent(current$$1, workInProgress, Component, next...
function updateSimpleMemoComponent (line 14675) | function updateSimpleMemoComponent(current$$1, workInProgress, Component...
function updateFragment (line 14711) | function updateFragment(current$$1, workInProgress, renderExpirationTime) {
function updateMode (line 14717) | function updateMode(current$$1, workInProgress, renderExpirationTime) {
function updateProfiler (line 14723) | function updateProfiler(current$$1, workInProgress, renderExpirationTime) {
function markRef (line 14733) | function markRef(current$$1, workInProgress) {
function updateFunctionComponent (line 14741) | function updateFunctionComponent(current$$1, workInProgress, Component, ...
function updateClassComponent (line 14783) | function updateClassComponent(current$$1, workInProgress, Component, nex...
function finishClassComponent (line 14842) | function finishClassComponent(current$$1, workInProgress, Component, sho...
function pushHostRootContext (line 14908) | function pushHostRootContext(workInProgress) {
function updateHostRoot (line 14919) | function updateHostRoot(current$$1, workInProgress, renderExpirationTime) {
function updateHostComponent (line 14963) | function updateHostComponent(current$$1, workInProgress, renderExpiratio...
function updateHostText (line 15002) | function updateHostText(current$$1, workInProgress) {
function mountLazyComponent (line 15011) | function mountLazyComponent(_current, workInProgress, elementType, updat...
function mountIncompleteClassComponent (line 15085) | function mountIncompleteClassComponent(_current, workInProgress, Compone...
function mountIndeterminateComponent (line 15120) | function mountIndeterminateComponent(_current, workInProgress, Component...
function validateFunctionComponentInDev (line 15207) | function validateFunctionComponentInDev(workInProgress, Component) {
function updateSuspenseComponent (line 15248) | function updateSuspenseComponent(current$$1, workInProgress, renderExpir...
function updateDehydratedSuspenseComponent (line 15466) | function updateDehydratedSuspenseComponent(current$$1, workInProgress, r...
function updatePortalComponent (line 15525) | function updatePortalComponent(current$$1, workInProgress, renderExpirat...
function updateContextProvider (line 15541) | function updateContextProvider(current$$1, workInProgress, renderExpirat...
function updateContextConsumer (line 15582) | function updateContextConsumer(current$$1, workInProgress, renderExpirat...
function markWorkInProgressReceivedUpdate (line 15629) | function markWorkInProgressReceivedUpdate() {
function bailoutOnAlreadyFinishedWork (line 15633) | function bailoutOnAlreadyFinishedWork(current$$1, workInProgress, render...
function beginWork (line 15661) | function beginWork(current$$1, workInProgress, renderExpirationTime) {
function resetContextDependences (line 15862) | function resetContextDependences() {
function enterDisallowedContextReadInDEV (line 15873) | function enterDisallowedContextReadInDEV() {
function exitDisallowedContextReadInDEV (line 15879) | function exitDisallowedContextReadInDEV() {
function pushProvider (line 15885) | function pushProvider(providerFiber, nextValue) {
function popProvider (line 15907) | function popProvider(providerFiber) {
function calculateChangedBits (line 15920) | function calculateChangedBits(context, newValue, oldValue) {
function scheduleWorkOnParentPath (line 15934) | function scheduleWorkOnParentPath(parent, renderExpirationTime) {
function propagateContextChange (line 15956) | function propagateContextChange(workInProgress, context, changedBits, re...
function prepareToReadContext (line 16060) | function prepareToReadContext(workInProgress, renderExpirationTime) {
function readContext (line 16075) | function readContext(context, observedBits) {
function createUpdateQueue (line 16217) | function createUpdateQueue(baseState) {
function cloneUpdateQueue (line 16232) | function cloneUpdateQueue(currentQueue) {
function createUpdate (line 16252) | function createUpdate(expirationTime) {
function appendUpdateToQueue (line 16265) | function appendUpdateToQueue(queue, update) {
function enqueueUpdate (line 16276) | function enqueueUpdate(fiber, update) {
function enqueueCapturedUpdate (line 16338) | function enqueueCapturedUpdate(workInProgress, update) {
function ensureWorkInProgressQueueIsAClone (line 16361) | function ensureWorkInProgressQueueIsAClone(workInProgress, queue) {
function getStateFromUpdate (line 16373) | function getStateFromUpdate(workInProgress, queue, update, prevState, ne...
function processUpdateQueue (line 16436) | function processUpdateQueue(workInProgress, queue, props, instance, rend...
function callCallback (line 16566) | function callCallback(callback, context) {
function resetHasForceUpdateBeforeProcessing (line 16571) | function resetHasForceUpdateBeforeProcessing() {
function checkHasForceUpdateAfterProcessing (line 16575) | function checkHasForceUpdateAfterProcessing() {
function commitUpdateQueue (line 16579) | function commitUpdateQueue(finishedWork, finishedQueue, instance, render...
function commitUpdateEffects (line 16602) | function commitUpdateEffects(effect, instance) {
function createCapturedValue (line 16613) | function createCapturedValue(value, source) {
function markUpdate (line 16623) | function markUpdate(workInProgress) {
function markRef$1 (line 16629) | function markRef$1(workInProgress) {
function completeWork (line 16963) | function completeWork(current, workInProgress, renderExpirationTime) {
function shouldCaptureSuspense (line 17178) | function shouldCaptureSuspense(workInProgress) {
function showErrorDialog (line 17192) | function showErrorDialog(capturedError) {
function logCapturedError (line 17196) | function logCapturedError(capturedError) {
function logError (line 17263) | function logError(boundary, errorInfo) {
function safelyCallComponentWillUnmount (line 17309) | function safelyCallComponentWillUnmount(current$$1, instance) {
function safelyDetachRef (line 17319) | function safelyDetachRef(current$$1) {
function safelyCallDestroy (line 17336) | function safelyCallDestroy(current$$1, destroy) {
function commitBeforeMutationLifeCycles (line 17346) | function commitBeforeMutationLifeCycles(current$$1, finishedWork) {
function commitHookEffectList (line 17400) | function commitHookEffectList(unmountTag, mountTag, finishedWork) {
function commitPassiveHookEffects (line 17440) | function commitPassiveHookEffects(finishedWork) {
function commitLifeCycles (line 17445) | function commitLifeCycles(finishedRoot, current$$1, finishedWork, commit...
function hideOrUnhideAllChildren (line 17572) | function hideOrUnhideAllChildren(finishedWork, isHidden) {
function commitAttachRef (line 17617) | function commitAttachRef(finishedWork) {
function commitDetachRef (line 17643) | function commitDetachRef(current$$1) {
function commitUnmount (line 17657) | function commitUnmount(current$$1) {
function commitNestedUnmounts (line 17712) | function commitNestedUnmounts(root) {
function detachFiber (line 17744) | function detachFiber(current$$1) {
function emptyPortalContainer (line 17763) | function emptyPortalContainer(current$$1) {
function commitContainer (line 17775) | function commitContainer(finishedWork) {
function getHostParentFiber (line 17810) | function getHostParentFiber(fiber) {
function isHostParent (line 17821) | function isHostParent(fiber) {
function getHostSibling (line 17825) | function getHostSibling(fiber) {
function commitPlacement (line 17866) | function commitPlacement(finishedWork) {
function unmountHostComponents (line 17943) | function unmountHostComponents(current$$1) {
function commitDeletion (line 18035) | function commitDeletion(current$$1) {
function commitWork (line 18047) | function commitWork(current$$1, finishedWork) {
function commitResetTextContent (line 18180) | function commitResetTextContent(current$$1) {
function createRootErrorUpdate (line 18190) | function createRootErrorUpdate(fiber, errorInfo, expirationTime) {
function createClassErrorUpdate (line 18205) | function createClassErrorUpdate(fiber, errorInfo, expirationTime) {
function attachPingListener (line 18246) | function attachPingListener(root, renderExpirationTime, thenable) {
function throwException (line 18274) | function throwException(root, returnFiber, sourceFiber, value, renderExp...
function unwindWork (line 18487) | function unwindWork(workInProgress, renderExpirationTime) {
function unwindInterruptedWork (line 18551) | function unwindInterruptedWork(interruptedWork) {
function resetStack (line 18741) | function resetStack() {
function commitAllHostEffects (line 18762) | function commitAllHostEffects() {
function commitBeforeMutationLifecycles (line 18832) | function commitBeforeMutationLifecycles() {
function commitAllLifeCycles (line 18853) | function commitAllLifeCycles(finishedRoot, committedExpirationTime) {
function commitPassiveEffects (line 18890) | function commitPassiveEffects(root, firstEffect) {
function isAlreadyFailedLegacyErrorBoundary (line 18938) | function isAlreadyFailedLegacyErrorBoundary(instance) {
function markLegacyErrorBoundaryAsFailed (line 18942) | function markLegacyErrorBoundaryAsFailed(instance) {
function flushPassiveEffects (line 18950) | function flushPassiveEffects() {
function commitRoot (line 18961) | function commitRoot(root, finishedWork) {
function resetChildExpirationTime (line 19187) | function resetChildExpirationTime(workInProgress, renderTime) {
function completeUnitOfWork (line 19248) | function completeUnitOfWork(workInProgress) {
function performUnitOfWork (line 19424) | function performUnitOfWork(workInProgress) {
function workLoop (line 19483) | function workLoop(isYieldy) {
function renderRoot (line 19497) | function renderRoot(root, isYieldy) {
function captureCommitPhaseError (line 19747) | function captureCommitPhaseError(sourceFiber, value) {
function computeThreadID (line 19786) | function computeThreadID(expirationTime, interactionThreadID) {
function computeUniqueAsyncExpiration (line 19792) | function computeUniqueAsyncExpiration() {
function computeExpirationForFiber (line 19805) | function computeExpirationForFiber(currentTime, fiber) {
function renderDidSuspend (line 19853) | function renderDidSuspend(root, absoluteTimeoutMs, suspendedTime) {
function renderDidError (line 19860) | function renderDidError() {
function pingSuspendedRoot (line 19864) | function pingSuspendedRoot(root, thenable, pingTime) {
function retryTimedOutBoundary (line 19892) | function retryTimedOutBoundary(boundaryFiber, thenable) {
function scheduleWorkToRoot (line 19929) | function scheduleWorkToRoot(fiber, expirationTime) {
function warnIfNotCurrentlyBatchingInDev (line 20006) | function warnIfNotCurrentlyBatchingInDev(fiber) {
function scheduleWork (line 20014) | function scheduleWork(fiber, expirationTime) {
function syncUpdates (line 20055) | function syncUpdates(fn, a, b, c, d) {
function recomputeCurrentRendererTime (line 20091) | function recomputeCurrentRendererTime() {
function scheduleCallbackWithExpirationTime (line 20096) | function scheduleCallbackWithExpirationTime(root, expirationTime) {
function onFatal (line 20125) | function onFatal(root) {
function onComplete (line 20129) | function onComplete(root, finishedWork, expirationTime) {
function onSuspend (line 20134) | function onSuspend(root, finishedWork, suspendedExpirationTime, rootExpi...
function onYield (line 20146) | function onYield(root) {
function onTimeout (line 20150) | function onTimeout(root, finishedWork, suspendedExpirationTime) {
function onCommit (line 20162) | function onCommit(root, expirationTime) {
function requestCurrentTime (line 20167) | function requestCurrentTime() {
function requestWork (line 20210) | function requestWork(root, expirationTime) {
function addRootToSchedule (line 20238) | function addRootToSchedule(root, expirationTime) {
function findHighestPriorityRoot (line 20262) | function findHighestPriorityRoot() {
function shouldYieldToRenderer (line 20327) | function shouldYieldToRenderer() {
function performAsyncWork (line 20338) | function performAsyncWork() {
function performSyncWork (line 20362) | function performSyncWork() {
function performWork (line 20366) | function performWork(minExpirationTime, isYieldy) {
function flushRoot (line 20411) | function flushRoot(root, expirationTime) {
function finishRendering (line 20423) | function finishRendering() {
function performWorkOnRoot (line 20451) | function performWorkOnRoot(root, expirationTime, isYieldy) {
function completeRoot (line 20520) | function completeRoot(root, finishedWork, expirationTime) {
function onUncaughtError (line 20557) | function onUncaughtError(error) {
function batchedUpdates$1 (line 20570) | function batchedUpdates$1(fn, a) {
function unbatchedUpdates (line 20585) | function unbatchedUpdates(fn, a) {
function flushSync (line 20599) | function flushSync(fn, a) {
function interactiveUpdates$1 (line 20611) | function interactiveUpdates$1(fn, a, b) {
function flushInteractiveUpdates$1 (line 20635) | function flushInteractiveUpdates$1() {
function flushControlled (line 20643) | function flushControlled(fn) {
function getContextForSubtree (line 20668) | function getContextForSubtree(parentComponent) {
function scheduleRootUpdate (line 20686) | function scheduleRootUpdate(current$$1, element, expirationTime, callbac...
function updateContainerAtExpirationTime (line 20712) | function updateContainerAtExpirationTime(element, container, parentCompo...
function findHostInstance (line 20738) | function findHostInstance(component) {
function findHostInstanceWithWarning (line 20754) | function findHostInstanceWithWarning(component, methodName) {
function createContainer (line 20784) | function createContainer(containerInfo, isConcurrent, hydrate) {
function updateContainer (line 20788) | function updateContainer(element, container, parentComponent, callback) {
function getPublicRootInstance (line 20795) | function getPublicRootInstance(container) {
function findHostInstanceWithNoPortals (line 20808) | function findHostInstanceWithNoPortals(fiber) {
function injectIntoDevTools (line 20845) | function injectIntoDevTools(devToolsConfig) {
function createPortal$1 (line 20873) | function createPortal$1(children, containerInfo,
function ReactBatch (line 20934) | function ReactBatch(root) {
function ReactWork (line 21039) | function ReactWork() {
function ReactRoot (line 21074) | function ReactRoot(container, isConcurrent, hydrate) {
function isValidContainer (line 21150) | function isValidContainer(node) {
function getReactRootElementInContainer (line 21154) | function getReactRootElementInContainer(container) {
function shouldHydrateDueToLegacyHeuristic (line 21166) | function shouldHydrateDueToLegacyHeuristic(container) {
function legacyCreateRootFromDOMContainer (line 21175) | function legacyCreateRootFromDOMContainer(container, forceHydrate) {
function legacyRenderSubtreeIntoContainer (line 21202) | function legacyRenderSubtreeIntoContainer(parentComponent, children, con...
function createPortal$$1 (line 21246) | function createPortal$$1(children, container) {
function createRoot (line 21363) | function createRoot(container, options) {
FILE: vendor/react-dom.js
function pb (line 12) | function pb(a,b,c,d,e,f,g,h){if(!a){a=void 0;if(void 0===b)a=Error("Mini...
function n (line 13) | function n(a){for(var b=arguments.length-1,c="https://reactjs.org/docs/e...
function rh (line 13) | function rh(a,b,c,d,e,f,g,h,l){qb=!1;$b=null;sh.apply(th,arguments)}
function uh (line 13) | function uh(a,b,c,d,e,f,g,h,l){rh.apply(this,arguments);
function Ee (line 14) | function Ee(){if(bc)for(var a in Na){var b=Na[a],c=bc.indexOf(a);-1<c?vo...
function Fe (line 15) | function Fe(a,b,c){Oa[a]?n("100",a):void 0;Oa[a]=b;$c[a]=b.eventTypes[c]...
function Ge (line 15) | function Ge(a,b,c){var d=a.type||"unknown-event";a.currentTarget=He(c);u...
function Pa (line 15) | function Pa(a,b){null==b?n("30"):void 0;if(null==a)return b;if(Array.isA...
function ad (line 15) | function ad(a,b,c){Array.isArray(a)?a.forEach(b,c):a&&b.call(c,a)}
function Ie (line 15) | function Ie(a,b){var c=a.stateNode;if(!c)return null;
function cd (line 16) | function cd(a){null!==a&&(rb=Pa(rb,a));a=rb;
function dc (line 17) | function dc(a){if(a[ea])return a[ea];for(;!a[ea];)if(a.parentNode)a=a.pa...
function Je (line 17) | function Je(a){a=a[ea];return!a||5!==a.tag&&6!==a.tag?null:a}
function Da (line 17) | function Da(a){if(5===a.tag||6===a.tag)return a.stateNode;n("33")}
function dd (line 17) | function dd(a){return a[ec]||null}
function fa (line 17) | function fa(a){do a=a.return;while(a&&5!==a.tag);return a?a:null}
function Ke (line 17) | function Ke(a,b,c){if(b=Ie(a,c.dispatchConfig.phasedRegistrationNames[b]...
function wh (line 18) | function wh(a){if(a&&a.dispatchConfig.phasedRegistrationNames){for(var b...
function ed (line 18) | function ed(a,b,c){a&&c&&c.dispatchConfig.registrationName&&(b=Ie(a,c.di...
function xh (line 18) | function xh(a){a&&a.dispatchConfig.registrationName&&
function Qa (line 19) | function Qa(a){ad(a,wh)}
function fc (line 19) | function fc(a,b){var c={};c[a.toLowerCase()]=b.toLowerCase();c["Webkit"+...
function gc (line 19) | function gc(a){if(fd[a])return fd[a];if(!Ra[a])return a;var b=Ra[a],c;fo...
function Me (line 19) | function Me(){if(hc)return hc;var a,b=gd,c=b.length,d,e="value"in qa?qa....
function ic (line 20) | function ic(){return!0}
function jc (line 20) | function jc(){return!1}
function J (line 20) | function J(a,b,c,d){this.dispatchConfig=a;this._targetInst=b;this.native...
function yh (line 20) | function yh(a,b,c,d){if(this.eventPool.length){var e=this.eventPool.pop(...
function zh (line 21) | function zh(a){a instanceof this?void 0:n("279");a.destructor();10>this....
function Ne (line 21) | function Ne(a){a.eventPool=[];a.getPooled=yh;a.release=zh}
function Oe (line 21) | function Oe(a,b){switch(a){case "keyup":return-1!==Ah.indexOf(b.keyCode)...
function Pe (line 21) | function Pe(a){a=a.detail;return"object"===typeof a&&"data"in a?a.data:n...
function Bh (line 21) | function Bh(a,b){switch(a){case "compositionend":return Pe(b);
function Ch (line 22) | function Ch(a,b){if(Sa)return"compositionend"===a||!hd&&Oe(a,b)?(a=Me(),...
function Te (line 23) | function Te(a){if(a=Ue(a)){"function"!==typeof id?n("280"):void 0;var b=...
function Ve (line 23) | function Ve(a){Ta?Ua?Ua.push(a):Ua=[a]:Ta=a}
function We (line 23) | function We(){if(Ta){var a=Ta,b=Ua;Ua=Ta=null;Te(a);if(b)for(a=0;a<b.len...
function Xe (line 23) | function Xe(a,b){if(jd)return a(b);jd=!0;try{return Ye(a,b)}finally{if(j...
function $e (line 23) | function $e(a){var b=a&&a.nodeName&&a.nodeName.toLowerCase();return"inpu...
function kd (line 23) | function kd(a){a=
function af (line 24) | function af(a){if(!ra)return!1;a="on"+a;var b=a in document;b||(b=docume...
function bf (line 24) | function bf(a){var b=a.type;return(a=a.nodeName)&&"input"===a.toLowerCas...
function Eh (line 24) | function Eh(a){var b=bf(a)?"checked":"value",c=Object.getOwnPropertyDesc...
function kc (line 25) | function kc(a){a._valueTracker||(a._valueTracker=Eh(a))}
function cf (line 25) | function cf(a){if(!a)return!1;
function sb (line 26) | function sb(a){if(null===a||"object"!==typeof a)return null;a=df&&a[df]|...
function sa (line 26) | function sa(a){if(null==a)return null;if("function"===typeof a)return a....
function qd (line 27) | function qd(a){var b="";do{a:switch(a.tag){case 3:case 4:case 6:case 7:c...
function Gh (line 28) | function Gh(a){if(hf.call(jf,a))return!0;if(hf.call(kf,a))return!1;if(Hh...
function Ih (line 28) | function Ih(a,b,c,d){if(null!==c&&0===c.type)return!1;switch(typeof b){c...
function Jh (line 29) | function Jh(a,b,c,d){if(null===b||"undefined"===typeof b||Ih(a,b,c,d))re...
function K (line 29) | function K(a,b,c,d,e){this.acceptsBooleans=2===b||3===b||4===b;this.attr...
function rd (line 29) | function rd(a,b,c,d){var e=A.hasOwnProperty(b)?
function ua (line 30) | function ua(a){switch(typeof a){case "boolean":case "number":case "objec...
function sd (line 31) | function sd(a,b){var c=b.checked;return B({},b,{defaultChecked:void 0,de...
function lf (line 31) | function lf(a,b){var c=null==b.defaultValue?"":b.defaultValue,d=null!=b....
function mf (line 31) | function mf(a,b){b=b.checked;null!=b&&rd(a,"checked",b,!1)}
function td (line 31) | function td(a,
function nf (line 32) | function nf(a,b,c){if(b.hasOwnProperty("value")||b.hasOwnProperty("defau...
function ud (line 33) | function ud(a,b,c){if("number"!==b||a.ownerDocument.activeElement!==a)nu...
function of (line 33) | function of(a,b,c){a=J.getPooled(pf.change,a,b,
function Kh (line 34) | function Kh(a){cd(a)}
function mc (line 34) | function mc(a){var b=Da(a);if(cf(b))return a}
function Lh (line 34) | function Lh(a,b){if("change"===a)return b}
function qf (line 34) | function qf(){tb&&(tb.detachEvent("onpropertychange",rf),ub=tb=null)}
function rf (line 34) | function rf(a){"value"===a.propertyName&&mc(ub)&&(a=of(ub,a,kd(a)),Xe(Kh...
function Mh (line 34) | function Mh(a,b,c){"focus"===a?(qf(),tb=b,ub=c,tb.attachEvent("onpropert...
function Nh (line 34) | function Nh(a,b){if("selectionchange"===a||"keyup"===a||"keydown"===a)re...
function Oh (line 34) | function Oh(a,b){if("click"===
function Ph (line 35) | function Ph(a,b){if("input"===a||"change"===a)return mc(b)}
function Qh (line 35) | function Qh(a){var b=this.nativeEvent;return b.getModifierState?b.getMod...
function vd (line 35) | function vd(a){return Qh}
function Ea (line 35) | function Ea(a,b){return a===b&&(0!==a||1/a===1/b)||a!==a&&b!==b}
function vb (line 35) | function vb(a,b){if(Ea(a,b))return!0;if("object"!==typeof a||null===a||"...
function wb (line 36) | function wb(a){var b=a;if(a.alternate)for(;b.return;)b=b.return;else{if(...
function sf (line 36) | function sf(a){2!==wb(a)?n("188"):void 0}
function Th (line 36) | function Th(a){var b=a.alternate;if(!b)return b=wb(a),3===b?n("188"):voi...
function tf (line 37) | function tf(a){a=Th(a);if(!a)return null;for(var b=a;;){if(5===b.tag||6=...
function nc (line 38) | function nc(a){var b=a.keyCode;"charCode"in a?(a=a.charCode,0===a&&13===...
function uf (line 38) | function uf(a,b){var c=a[0];a=a[1];var d="on"+(a[0].toUpperCase()+a.slic...
function Uh (line 38) | function Uh(a){var b=a.targetInst,c=b;do{if(!c){a.ancestors.push(c);
function r (line 39) | function r(a,b){if(!b)return null;var c=(wf(a)?xf:oc).bind(null,a);b.add...
function pc (line 39) | function pc(a,b){if(!b)return null;var c=(wf(a)?xf:oc).bind(null,a);
function xf (line 40) | function xf(a,b){yf(oc,a,b)}
function oc (line 40) | function oc(a,b){if(qc){var c=kd(b);c=dc(c);null===c||"number"!==typeof ...
function zf (line 40) | function zf(a){Object.prototype.hasOwnProperty.call(a,sc)||(a[sc]=Vh++,A...
function xd (line 41) | function xd(a){a=a||("undefined"!==typeof document?document:void 0);if("...
function Bf (line 41) | function Bf(a){for(;a&&a.firstChild;)a=a.firstChild;return a}
function Cf (line 41) | function Cf(a,b){var c=Bf(a);a=0;for(var d;c;){if(3===c.nodeType){d=a+c....
function Df (line 41) | function Df(a,b){return a&&b?a===
function Ef (line 42) | function Ef(){for(var a=window,b=xd();b instanceof a.HTMLIFrameElement;)...
function yd (line 42) | function yd(a){var b=a&&a.nodeName&&a.nodeName.toLowerCase();return b&&(...
function Wh (line 43) | function Wh(){var a=Ef();if(yd(a)){if("selectionStart"in a)var b={start:...
function Xh (line 44) | function Xh(a){var b=Ef(),c=a.focusedElem,d=a.selectionRange;if(b!==c&&c...
function Gf (line 46) | function Gf(a,b){var c=b.window===b?b.document:9===b.nodeType?b:b.ownerD...
function Yh (line 47) | function Yh(a){var b="";da.Children.forEach(a,function(a){null!=a&&(b+=a...
function Bd (line 47) | function Bd(a,b){a=B({children:void 0},b);if(b=Yh(b.children))a.children=
function Xa (line 48) | function Xa(a,b,c,d){a=a.options;if(b){b={};for(var e=0;e<c.length;e++)b...
function Cd (line 48) | function Cd(a,b){null!=b.dangerouslySetInnerHTML?n("91"):void 0;return B...
function If (line 49) | function If(a,b){var c=b.value;null==c&&(c=b.defaultValue,b=b.children,n...
function Jf (line 49) | function Jf(a,b){var c=ua(b.value),d=ua(b.defaultValue);null!=c&&(c=""+c...
function Kf (line 49) | function Kf(a){switch(a){case "svg":return"http://www.w3.org/2000/svg";
function Dd (line 50) | function Dd(a,b){return null==a||"http://www.w3.org/1999/xhtml"===a?Kf(b...
function Lf (line 50) | function Lf(a,b,c){return null==b||"boolean"===typeof b||""===b?"":c||"n...
function Mf (line 50) | function Mf(a,b){a=a.style;for(var c in b)if(b.hasOwnProperty(c)){var d=...
function Ed (line 51) | function Ed(a,b){b&&(Zh[a]&&(null!=b.children||null!=b.dangerouslySetInn...
function Fd (line 51) | function Fd(a,b){if(-1===a.indexOf("-"))return"string"===typeof b.is;swi...
function ha (line 52) | function ha(a,b){a=9===a.nodeType||11===a.nodeType?a:a.ownerDocument;var...
function tc (line 52) | function tc(){}
function Nf (line 52) | function Nf(a,b){switch(a){case "button":case "input":case "select":case...
function Gd (line 53) | function Gd(a,b){return"textarea"===a||"option"===a||"noscript"===a||"st...
function $h (line 53) | function $h(a,b,c,d,e,f){a[ec]=e;"input"===c&&"radio"===e.type&&null!=e....
function Hd (line 54) | function Hd(a){for(a=a.nextSibling;a&&1!==a.nodeType&&3!==a.nodeType;)a=...
function Pf (line 54) | function Pf(a){for(a=a.firstChild;a&&1!==a.nodeType&&3!==a.nodeType;)a=a...
function D (line 54) | function D(a,b){0>Ya||(a.current=
function L (line 55) | function L(a,b,c){Ya++;Id[Ya]=a.current;a.current=b}
function Za (line 55) | function Za(a,b){var c=a.type.contextTypes;if(!c)return va;var d=a.state...
function E (line 55) | function E(a){a=a.childContextTypes;return null!==a&&void 0!==a}
function uc (line 55) | function uc(a){D(M,a);
function Jd (line 56) | function Jd(a){D(M,a);D(F,a)}
function Qf (line 56) | function Qf(a,b,c){F.current!==va?n("168"):void 0;L(F,b,a);L(M,c,a)}
function Rf (line 56) | function Rf(a,b,c){var d=a.stateNode;a=b.childContextTypes;if("function"...
function vc (line 56) | function vc(a){var b=a.stateNode;b=b&&b.__reactInternalMemoizedMergedChi...
function Sf (line 56) | function Sf(a,b,c){var d=a.stateNode;d?void 0:n("169");c?(b=
function Tf (line 57) | function Tf(a){return function(b){try{return a(b)}catch(c){}}}
function ai (line 57) | function ai(a){if("undefined"===typeof __REACT_DEVTOOLS_GLOBAL_HOOK__)re...
function bi (line 57) | function bi(a,b,c,d){this.tag=a;this.key=
function Md (line 58) | function Md(a){a=a.prototype;return!(!a||!a.isReactComponent)}
function ci (line 58) | function ci(a){if("function"===typeof a)return Md(a)?1:0;if(void 0!==a&&
function Ga (line 59) | function Ga(a,b,c){c=a.alternate;null===c?(c=S(a.tag,b,a.key,a.mode),c.e...
function wc (line 60) | function wc(a,b,c,d,e,f){var g=2;d=a;if("function"===typeof a)Md(a)&&(g=...
function wa (line 61) | function wa(a,b,c,d){a=S(7,a,d,b);a.expirationTime=c;return a}
function Uf (line 61) | function Uf(a,b,c,d){a=S(8,a,d,b);b=0===(b&1)?md:ld;a.elementType=b;a.ty...
function Nd (line 61) | function Nd(a,b,c){a=S(6,a,null,b);a.expirationTime=c;return a}
function Od (line 61) | function Od(a,b,c){b=S(4,null!==a.children?
function Bb (line 62) | function Bb(a,b){a.didError=!1;var c=a.earliestPendingTime;0===c?a.earli...
function di (line 62) | function di(a,b){a.didError=!1;if(0===b)a.earliestPendingTime=0,a.latest...
function Vf (line 63) | function Vf(a,b){a.didError=!1;a.latestPingedTime>=b&&(a.latestPingedTim...
function Wf (line 64) | function Wf(a,b){var c=a.earliestPendingTime;a=a.earliestSuspendedTime;c...
function xc (line 64) | function xc(a,b){var c=b.earliestSuspendedTime,d=b.latestSuspendedTime,e...
function P (line 65) | function P(a,b){if(a&&a.defaultProps){b=B({},b);a=a.defaultProps;for(var...
function ei (line 65) | function ei(a){var b=a._result;switch(a._status){case 1:return b;case 2:...
function yc (line 66) | function yc(a,b,c,d){b=a.memoizedState;c=c(d,b);c=null===c||void 0===c?b...
function Xf (line 66) | function Xf(a,b,c,d,e,f,g){a=a.stateNode;return"function"===typeof a.sho...
function Yf (line 66) | function Yf(a,b,c,d){var e=!1;d=va;var f=b.contextType;"object"===typeof...
function Zf (line 67) | function Zf(a,b,c,d){a=b.state;"function"===typeof b.componentWillReceiv...
function Pd (line 68) | function Pd(a,b,c,d){var e=a.stateNode;e.props=c;e.state=a.memoizedState...
function Db (line 69) | function Db(a,b,c){a=c.ref;if(null!==a&&"function"!==typeof a&&"object"!...
function Ac (line 70) | function Ac(a,b){"textarea"!==a.type&&n("31","[object Object]"===Object....
function ag (line 70) | function ag(a){function b(b,
function Ha (line 80) | function Ha(a){a===Eb?n("174"):void 0;return a}
function Qd (line 80) | function Qd(a,b){L(Fb,b,a);L(Gb,a,a);L(U,Eb,a);var c=b.nodeType;switch(c...
function $a (line 81) | function $a(a){D(U,a);D(Gb,a);D(Fb,a)}
function bg (line 81) | function bg(a){Ha(Fb.current);var b=Ha(U.current);var c=Dd(b,a.type);b!=...
function Rd (line 81) | function Rd(a){Gb.current===a&&(D(U,a),D(Gb,a))}
function V (line 81) | function V(){n("321")}
function Sd (line 81) | function Sd(a,b){if(null===b)return!1;for(var c=0;c<b.length&&c<a.length...
function Td (line 81) | function Td(a,b,c,d,e,f){Hb=f;xa=b;W=null!==a?a.memoizedState:null;Dc.cu...
function Vd (line 82) | function Vd(){Dc.current=Ud;Hb=0;ab=G=bb=W=y=xa=null;Kb=0;X=null;Lb=0;Ib...
function cb (line 82) | function cb(){var a={memoizedState:null,baseState:null,queue:null,baseUp...
function Mb (line 83) | function Mb(){if(null!==ab)G=ab,ab=G.next,y=W,W=null!==y?y.next:null;els...
function dg (line 83) | function dg(a,b){return"function"===typeof b?b(a):b}
function eg (line 83) | function eg(a,b,c){b=Mb();c=b.queue;null===c?n("311"):void 0;c.lastRende...
function Wd (line 85) | function Wd(a,b,c,d){a={tag:a,create:b,destroy:c,deps:d,next:null};null=...
function Xd (line 85) | function Xd(a,b,c,d){var e=cb();Lb|=a;e.memoizedState=Wd(b,c,void 0,void...
function Yd (line 85) | function Yd(a,b,c,d){var e=Mb();d=void 0===
function fg (line 86) | function fg(a,b){if("function"===typeof b)return a=a(),b(a),function(){b...
function gg (line 86) | function gg(a,b){}
function hg (line 86) | function hg(a,b,c){25>Jb?void 0:n("301");var d=a.alternate;if(a===xa||nu...
function ig (line 88) | function ig(a,b){var c=S(5,null,null,0);c.elementType="DELETED";c.type="...
function jg (line 88) | function jg(a,b){switch(a.tag){case 5:var c=a.type;b=1!==b.nodeType||c.t...
function kg (line 88) | function kg(a){if(Ia){var b=
function lg (line 89) | function lg(a){for(a=a.return;null!==a&&5!==a.tag&&3!==a.tag&&18!==a.tag...
function Zd (line 89) | function Zd(a){if(a!==la)return!1;if(!Ia)return lg(a),Ia=!0,!1;var b=a.t...
function $d (line 89) | function $d(){gb=la=null;Ia=!1}
function N (line 89) | function N(a,b,c,d){b.child=null===
function mg (line 90) | function mg(a,b,c,d,e){c=c.render;var f=b.ref;ib(b,e);d=Td(a,b,c,d,f,e);...
function ng (line 90) | function ng(a,b,c,d,e,f){if(null===a){var g=c.type;if("function"===typeo...
function og (line 91) | function og(a,b,c,d,e,f){return null!==a&&vb(a.memoizedProps,d)&&a.ref==...
function pg (line 91) | function pg(a,b){var c=b.ref;if(null===a&&null!==c||null!==a&&a.ref!==c)...
function be (line 91) | function be(a,b,c,d,e){var f=E(c)?Fa:F.current;f=Za(b,f);ib(b,e);c=Td(a,...
function qg (line 92) | function qg(a,b,c,d,e){if(E(c)){var f=!0;vc(b)}else f=!1;ib(b,e);if(null...
function ce (line 97) | function ce(a,b,c,d,e,f){pg(a,b);var g=0!==(b.effectTag&
function rg (line 98) | function rg(a){var b=a.stateNode;b.pendingContext?Qf(a,b.pendingContext,...
function sg (line 98) | function sg(a,b,c){var d=b.mode,e=b.pendingProps,f=b.memoizedState;
function ma (line 100) | function ma(a,b,c){null!==a&&(b.contextDependencies=a.contextDependencie...
function hi (line 101) | function hi(a,b,c){var d=b.expirationTime;if(null!==a)if(a.memoizedProps...
function tg (line 109) | function tg(a,b){var c=a.type._context;L(de,c._currentValue,
function ee (line 110) | function ee(a){var b=de.current;D(de,a);a.type._context._currentValue=b}
function ib (line 110) | function ib(a,b){Nb=a;Ob=Ja=null;var c=a.contextDependencies;null!==c&&c...
function T (line 110) | function T(a,b){if(Ob!==a&&!1!==b&&0!==b){if("number"!==typeof b||107374...
function Fc (line 110) | function Fc(a){return{baseState:a,
function fe (line 111) | function fe(a){return{baseState:a.baseState,firstUpdate:a.firstUpdate,la...
function Aa (line 111) | function Aa(a){return{expirationTime:a,tag:ug,payload:null,callback:null...
function Gc (line 111) | function Gc(a,
function na (line 112) | function na(a,b){var c=a.alternate;if(null===c){var d=a.updateQueue;var ...
function vg (line 113) | function vg(a,b){var c=a.updateQueue;c=null===c?a.updateQueue=Fc(a.memoi...
function wg (line 113) | function wg(a,b){var c=a.alternate;null!==c&&b===c.updateQueue&&(b=a.upd...
function xg (line 113) | function xg(a,b,c,d,e,f){switch(c.tag){case yg:return a=c.payload,"funct...
function Cb (line 114) | function Cb(a,b,c,d,e){za=!1;b=wg(a,b);for(var f=b.baseState,g=null,h=0,...
function zg (line 115) | function zg(a,b,c,d){null!==b.firstCapturedUpdate&&
function Ag (line 116) | function Ag(a,b){for(;null!==a;){var c=a.callback;if(null!==c){a.callbac...
function Hc (line 116) | function Hc(a,b){return{value:a,source:b,stack:qd(b)}}
function Pb (line 116) | function Pb(a){a.effectTag|=
function Bg (line 117) | function Bg(a,b){var c=b.source,d=b.stack;null===d&&null!==c&&(d=qd(c));...
function Cg (line 117) | function Cg(a){var b=a.ref;if(null!==b)if("function"===typeof b)try{b(nu...
function Qb (line 117) | function Qb(a,b,c){c=c.updateQueue;c=null!==c?c.lastEffect:null;if(null!...
function ii (line 118) | function ii(a,b){for(var c=a;;){if(5===c.tag){var d=c.stateNode;if(b)d.s...
function Dg (line 119) | function Dg(a){"function"===typeof Ld&&Ld(a);switch(a.tag){case 0:case 1...
function Fg (line 120) | function Fg(a){return 5===a.tag||3===a.tag||4===a.tag}
function Gg (line 120) | function Gg(a){a:{for(var b=a.return;null!==b;){if(Fg(b)){var c=b;break ...
function Eg (line 122) | function Eg(a){for(var b=a,c=!1,d=void 0,e=void 0;;){if(!c){c=b.return;a...
function Hg (line 124) | function Hg(a,b){switch(b.tag){case 0:case 11:case 14:case 15:Qb(Rb,ji,b...
function he (line 125) | function he(a,b,c){c=Aa(c);c.tag=ge;c.payload={element:null};
function Ig (line 126) | function Ig(a,b,c){c=Aa(c);c.tag=ge;var d=a.type.getDerivedStateFromErro...
function mi (line 126) | function mi(a,b){switch(a.tag){case 1:return E(a.type)&&
function Jg (line 127) | function Jg(){if(null!==x)for(var a=x.return;null!==a;){var b=a;switch(b...
function ni (line 128) | function ni(){for(;null!==p;){var a=p.effectTag;a&16&&Ab(p.stateNode,"")...
function oi (line 129) | function oi(){for(;null!==p;){if(p.effectTag&256)a:{var a=p.alternate,b=...
function qi (line 130) | function qi(a,b){for(;null!==p;){var c=p.effectTag;if(c&36){var d=p.alte...
function si (line 131) | function si(a,b){Ic=Jc=ke=null;var c=w;w=!0;do{if(b.effectTag&512){var d...
function eb (line 132) | function eb(){null!==Jc&&ti(Jc);null!==Ic&&Ic()}
function ui (line 132) | function ui(a,b){Lc=Ca=!0;a.current===b?n("177"):void 0;var c=a.pendingC...
function Mg (line 134) | function Mg(a){for(;;){var b=a.alternate,c=a.return,d=a.sibling;if(0===(...
function Qg (line 144) | function Qg(a){var b=hi(a.alternate,a,H);a.memoizedProps=a.pendingProps;...
function Rg (line 144) | function Rg(a,b){Ca?n("243"):void 0;eb();Ca=!0;var c=qe.current;qe.curre...
function Ka (line 150) | function Ka(a,b){for(var c=a.return;null!==c;){switch(c.tag){case 1:var ...
function fb (line 150) | function fb(a,b){var c=zi(),d=void 0;if(0===(b.mode&1))d=
function yi (line 151) | function yi(a,b,c){var d=a.pingCache;null!==d&&d.delete(b);if(null!==Y&&...
function li (line 152) | function li(a,b){var c=a.stateNode;null!==c&&c.delete(b);b=ka();b=fb(b,a...
function Sg (line 152) | function Sg(a,b){a.expirationTime<b&&(a.expirationTime=b);var c=a.altern...
function ya (line 153) | function ya(a,b){a=Sg(a,b);null!==a&&(!Ca&&0!==H&&b>H&&Jg(),Bb(a,b),Ca&&...
function Tg (line 153) | function Tg(a,b,c,d,e){return Mc(se,function(){return a(b,c,d,e)})}
function Ub (line 153) | function Ub(){aa=1073741822-((ue()-ve)/10|0)}
function Ug (line 153) | function Ug(a,b){if(0!==Oc){if(b<Oc)return;null!==Pc&&Vg(Pc)}Oc=b;a=ue()...
function re (line 153) | function re(a,b,c,d,e){a.expirationTime=d;
function Fi (line 154) | function Fi(a,b,c){a.pendingCommitExpirationTime=c;a.finishedWork=b;Ub()...
function wi (line 154) | function wi(a,b){a.expirationTime=b;a.finishedWork=null}
function ka (line 154) | function ka(){if(w)return jb;Qc();if(0===C||1===C)Ub(),jb=aa;return jb}
function Kc (line 154) | function Kc(a,b){null===a.nextScheduledRoot?(a.expirationTime=b,null===I...
function Qc (line 155) | function Qc(){var a=0,b=null;if(null!==I)for(var c=I,d=ba;null!==d;){var...
function Nc (line 156) | function Nc(){return Tc?!0:Gi()?Tc=!0:!1}
function Di (line 156) | function Di(){try{if(!Nc()&&null!==ba){Ub();var a=ba;do{var b=a.expirati...
function Z (line 156) | function Z(a,b){Qc();if(b)for(Ub(),jb=aa;null!==ca&&0!==C&&a<=C&&!(Tc&&a...
function Xg (line 157) | function Xg(a,b){w?n("253"):void 0;ca=a;C=b;Sc(a,b,!1);Z(1073741823,!1)}
function Sc (line 157) | function Sc(a,b,c){w?n("245"):void 0;w=!0;if(c){var d=a.finishedWork;nul...
function Vc (line 158) | function Vc(a,b,c){var d=a.firstBatch;if(null!==d&&d._expirationTime>=c&...
function ie (line 158) | function ie(a){null===ca?n("246"):void 0;ca.expirationTime=0;lb||(lb=!0,...
function Zg (line 158) | function Zg(a,b){var c=z;z=!0;try{return a(b)}finally{(z=
function $g (line 159) | function $g(a,b){if(z&&!Rc){Rc=!0;try{return a(b)}finally{Rc=!1}}return ...
function ah (line 159) | function ah(a,b,c){z||w||0===oa||(Z(oa,!1),oa=0);var d=z;z=!0;try{return...
function bh (line 159) | function bh(a,b,c,d,e){var f=b.current;a:if(c){c=c._reactInternalFiber;b...
function xe (line 160) | function xe(a,b,c,d){var e=b.current,f=ka();e=fb(f,e);return bh(a,b,c,e,d)}
function ye (line 160) | function ye(a){a=a.current;if(!a.child)return null;switch(a.child.tag){c...
function Hi (line 160) | function Hi(a,b,c){var d=
function Vb (line 161) | function Vb(a){var b=1073741822-25*(((1073741822-ka()+500)/25|0)+1);b>=z...
function mb (line 161) | function mb(){this._callbacks=null;this._didCommit=!1;this._onCommit=thi...
function nb (line 161) | function nb(a,b,c){b=S(3,null,null,
function ob (line 162) | function ob(a){return!(!a||1!==a.nodeType&&9!==a.nodeType&&11!==a.nodeTy...
function Ii (line 163) | function Ii(a,b){b||(b=a?9===a.nodeType?a.documentElement:a.firstChild:n...
function Wc (line 163) | function Wc(a,b,c,d,e){var f=c._reactRootContainer;if(f){if("function"==...
function ch (line 164) | function ch(a,b){var c=2<arguments.length&&void 0!==arguments[2]?argumen...
function b (line 169) | function b(){return c.apply(this,
FILE: vendor/react-redux.js
function i (line 1) | function i(e,t){return e(t={exports:{}},t.exports),t.exports}
function u (line 1) | function u(){}
function a (line 1) | function a(){}
function e (line 1) | function e(e,t,r,n,o,i){if(i!==s){var u=Error("Calling PropTypes validat...
function t (line 1) | function t(){return e}
function e (line 1) | function e(e,t){this.store=e,this.parentSub=t,this.unsubscribe=null,this...
function n (line 1) | function n(t){var r;r=e.call(this,t)||this;var n=t.store;r.notifySubscri...
function m (line 1) | function m(){return(m=Object.assign||function(e){for(var t=1;arguments.l...
function v (line 1) | function v(e,t){if(null==e)return{};var r,n,o={},i=Object.keys(e);for(n=...
function b (line 1) | function b(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t...
function m (line 1) | function m(e){return b(e)===f}
function M (line 1) | function M(e){return g.isMemo(e)?x:R[e.$$typeof]||C}
function U (line 1) | function U(e,t){return[t.payload,e[1]+1]}
function H (line 1) | function H(e,r){void 0===r&&(r={});var n=r.getDisplayName,i=void 0===n?f...
function L (line 1) | function L(e,t){return e===t?0!==e||0!==t||1/e==1/t:e!=e&&t!=t}
function K (line 1) | function K(e,t){if(L(e,t))return!0;if("object"!=typeof e||null===e||"obj...
function z (line 1) | function z(e){return function(t,r){var n=e(t,r);function o(){return n}re...
function V (line 1) | function V(e){return null!=e.dependsOnOwnProps?!!e.dependsOnOwnProps:1!=...
function Y (line 1) | function Y(e,t){return function(t,r){var n=function(e,t){return n.depend...
function B (line 1) | function B(e,t,r){return m({},r,e,t)}
function J (line 1) | function J(e,t,r,n){return function(o,i){return r(e(o,i),t(n,i),i)}}
function Q (line 1) | function Q(e,t,r,n,o){var i,s,u,a,c,p=o.areStatesEqual,f=o.areOwnPropsEq...
function X (line 1) | function X(e,t){var r=t.initMapStateToProps,n=t.initMapDispatchToProps,o...
function Z (line 1) | function Z(e,t,r){for(var n=t.length-1;n>=0;n--){var o=t[n](e);if(o)retu...
function ee (line 1) | function ee(e,t){return e===t}
FILE: vendor/react-transition-group.js
function o (line 1) | function o(){return(o=Object.assign||function(e){for(var t=1;t<arguments...
function a (line 1) | function a(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=...
function s (line 1) | function s(e,t){e.prototype=Object.create(t.prototype),e.prototype.const...
function l (line 1) | function l(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.ca...
function c (line 1) | function c(e,t){return e(t={exports:{}},t.exports),t.exports}
function h (line 1) | function h(){}
function e (line 1) | function e(e,t,n,r,i,o){if(o!==f){var a=new Error("Calling PropTypes val...
function t (line 1) | function t(){return e}
function y (line 1) | function y(e,t){return e.replace(new RegExp("(^|\\s)"+t+"(?:\\s|$)","g")...
function t (line 1) | function t(t,n){var r;r=e.call(this,t,n)||this;var i,o=n&&!n.isMounting?...
function T (line 1) | function T(){}
function t (line 1) | function t(){for(var t,n=arguments.length,r=new Array(n),i=0;i<n;i++)r[i...
function _ (line 1) | function _(e){if(void 0===e)throw new ReferenceError("this hasn't been i...
function w (line 1) | function w(e,n){var r=Object.create(null);return e&&t.Children.map(e,fun...
function L (line 1) | function L(e,t,n){return null!=n[t]?n[t]:e.props[t]}
function M (line 1) | function M(e,n,r){var i=w(e.children),o=function(e,t){function n(n){retu...
function n (line 1) | function n(t,n){var r,i=(r=e.call(this,t,n)||this).handleExited.bind(_(_...
function t (line 1) | function t(){for(var t,n=arguments.length,r=new Array(n),i=0;i<n;i++)r[i...
function t (line 1) | function t(){for(var t,n=arguments.length,r=new Array(n),i=0;i<n;i++)r[i...
FILE: vendor/react.js
function N (line 9) | function N(a,b,d,g,p,c,e,h){if(!a){a=void 0;if(void 0===b)a=Error("Minif...
function q (line 10) | function q(a){for(var b=arguments.length-1,d="https://reactjs.org/docs/e...
function t (line 10) | function t(a,b,d){this.props=a;this.context=b;this.refs=ba;this.updater=...
function da (line 10) | function da(){}
function O (line 10) | function O(a,b,d){this.props=a;this.context=b;this.refs=ba;this.updater=d||
function u (line 11) | function u(){if(!x){var a=c.expirationTime;C?P():C=!0;D(ta,a)}}
function Q (line 11) | function Q(){var a=c,b=c.next;if(c===b)c=null;else{var d=c.previous;c=d....
function F (line 12) | function F(){if(-1===k&&null!==c&&1===c.priorityLevel){x=!0;try{do Q();w...
function ta (line 12) | function ta(a){x=!0;var b=G;G=a;try{if(a)for(;null!==c;){var d=l();if(c....
function ea (line 12) | function ea(a,b,d){var g=void 0,p={},c=null,e=null;if(null!=
function ua (line 13) | function ua(a,b){return{$$typeof:y,type:a.type,key:b,ref:a.ref,props:a.p...
function S (line 13) | function S(a){return"object"===
function va (line 14) | function va(a){var b={"=":"=0",":":"=2"};return"$"+(""+a).replace(/[=:]/...
function ia (line 14) | function ia(a,b,d,g){if(I.length){var c=I.pop();c.result=a;c.keyPrefix=b...
function ja (line 14) | function ja(a){a.result=null;a.keyPrefix=null;a.func=null;a.context=null...
function T (line 14) | function T(a,b,d,g){var c=typeof a;if("undefined"===c||"boolean"===c)a=n...
function V (line 16) | function V(a,b,d){return null==a?0:T(a,"",b,d)}
function U (line 16) | function U(a,b){return"object"===typeof a&&null!==a&&null!=a.key?va(a.ke...
function xa (line 16) | function xa(a,b,d){a.func.call(a.context,b,a.count++)}
function ya (line 16) | function ya(a,b,d){var g=a.result,c=a.keyPrefix;a=a.func.call(a.context,...
function W (line 17) | function W(a,b,d,g,c){var e="";null!=d&&(e=(""+d).replace(la,"$&/")+"/")...
function m (line 17) | function m(){var a=ma.current;null===a?q("321"):void 0;return a}
FILE: vendor/redux.js
function __webpack_require__ (line 19) | function __webpack_require__(moduleId) {
function _interopRequireDefault (line 89) | function _interopRequireDefault(obj) { return obj && obj.__esModule ? ob...
function isCrushed (line 95) | function isCrushed() {}
function compose (line 126) | function compose() {
function _interopRequireDefault (line 168) | function _interopRequireDefault(obj) { return obj && obj.__esModule ? ob...
function createStore (line 205) | function createStore(reducer, preloadedState, enhancer) {
function warning (line 430) | function warning(message) {
function isPlainObject (line 505) | function isPlainObject(value) {
function _interopRequireDefault (line 538) | function _interopRequireDefault(obj) { return obj && obj.__esModule ? ob...
function applyMiddleware (line 556) | function applyMiddleware() {
function bindActionCreator (line 593) | function bindActionCreator(actionCreator, dispatch) {
function bindActionCreators (line 620) | function bindActionCreators(actionCreators, dispatch) {
function _interopRequireDefault (line 660) | function _interopRequireDefault(obj) { return obj && obj.__esModule ? ob...
function getUndefinedStateErrorMessage (line 662) | function getUndefinedStateErrorMessage(key, action) {
function getUnexpectedStateShapeWarningMessage (line 669) | function getUnexpectedStateShapeWarningMessage(inputState, reducers, act...
function assertReducerSanity (line 694) | function assertReducerSanity(reducers) {
function combineReducers (line 726) | function combineReducers(reducers) {
function isHostObject (line 811) | function isHostObject(value) {
function overArg (line 838) | function overArg(func, transform) {
function isObjectLike (line 875) | function isObjectLike(value) {
function _interopRequireDefault (line 903) | function _interopRequireDefault(obj) { return obj && obj.__esModule ? ob...
function symbolObservablePonyfill (line 927) | function symbolObservablePonyfill(root) {
Condensed preview — 426 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,475K chars).
[
{
"path": ".eslintignore",
"chars": 20,
"preview": "data/\nlogs/\nvendor/\n"
},
{
"path": ".eslintrc.js",
"chars": 6805,
"preview": "module.exports = {\n // When adding items to this file please check for effects on sub-directories.\n \"parser\": \"babel-e"
},
{
"path": ".gitignore",
"chars": 265,
"preview": "node_modules\nnpm-debug.log\n.DS_Store\n.eslintcache\n*.sw[po]\n*.xpi\n*.pyc\nlogs/\ndist/\nfirefox/\n*.update.rdf\ndata/content/ac"
},
{
"path": ".mcignore",
"chars": 305,
"preview": "npm-debug.log\n.DS_Store\n*.sw[po]\n*.xpi\n*.pyc\n*.update.rdf\n.gitignore\n.eslintcache\n\n/.git/\n/dist/\n/logs/\n/node_modules/\n\n"
},
{
"path": ".nvmrc",
"chars": 5,
"preview": "8.16\n"
},
{
"path": ".prettierrc",
"chars": 66,
"preview": "{\n \"printWidth\": 80,\n \"tabWidth\": 2,\n \"trailingComma\": \"es5\"\n}\n"
},
{
"path": ".sass-lint.yml",
"chars": 771,
"preview": "options:\n merge-default-rules: true\n max-warnings: 0\n\nfiles:\n include: 'content-src/**/*.scss'\n\nrules:\n class-name-f"
},
{
"path": ".taskcluster.yml",
"chars": 961,
"preview": "version: 1\npolicy:\n pullRequests: public\ntasks:\n $if: 'tasks_for in [\"github-push\", \"github-pull-request\"]'\n then:\n "
},
{
"path": ".travis.yml",
"chars": 824,
"preview": "language: node_js\n\nnode_js:\n # when changing this, be sure to edit .nvrmc and package.json too\n - 8\n\npython:\n - \"2.7\""
},
{
"path": "AboutNewTabService.jsm",
"chars": 10895,
"preview": "/*\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was n"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 691,
"preview": "# Community Participation Guidelines\n\nThis repository is governed by Mozilla's code of conduct and etiquette guidelines."
},
{
"path": "LICENSE",
"chars": 16727,
"preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
},
{
"path": "README.md",
"chars": 1927,
"preview": "# Firefox Home (New Tab) [Deprecated Version]\n\nThis repository is no longer updated or used. We're keeping it around for"
},
{
"path": "aboutlibrary/content/aboutlibrary.xhtml",
"chars": 1194,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n# This Source Code Form is subject to the terms of the Mozilla Public\n# Lice"
},
{
"path": "aboutlibrary/jar.mn",
"chars": 256,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "aboutlibrary/moz.build",
"chars": 410,
"preview": "# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-\n# vim: set filetype=python:\n# This Source Code Form is subj"
},
{
"path": "bin/bootstrap",
"chars": 154,
"preview": "#!/bin/sh -x\n\n# bootstrap an activity-stream repo\nln -s ../../hooks/pre-commit .git/hooks/pre-commit\nln -s ../../hooks/p"
},
{
"path": "bin/download-firefox-artifact",
"chars": 2068,
"preview": "#!/usr/bin/env bash -x\n\n# Forked from https://github.com/devtools-html/debugger.html/blob/master/bin/download-firefox-ar"
},
{
"path": "bin/prepare-mochitests-dev",
"chars": 2237,
"preview": "#!/usr/bin/env bash -x -e\n#\n# -e means \"exit on error\", so that we don't have to constantly\n# check exit codes\n#\n# Forke"
},
{
"path": "bin/render-activity-stream-html.js",
"chars": 4778,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "bin/try-runner.js",
"chars": 3384,
"preview": "/* eslint-disable no-console */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2."
},
{
"path": "bin/vendor.js",
"chars": 1445,
"preview": "#!/usr/bin/env node\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy"
},
{
"path": "common/Actions.jsm",
"chars": 15023,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "common/Dedupe.jsm",
"chars": 1150,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "common/PerfService.jsm",
"chars": 4168,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "common/Reducers.jsm",
"chars": 23066,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "components.conf",
"chars": 551,
"preview": "# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-\n# vim: set filetype=python:\n# This Source Code Form is subj"
},
{
"path": "content-src/.eslintrc.js",
"chars": 64,
"preview": "module.exports = {\n rules: {\n \"import/no-commonjs\": 2\n }\n}\n"
},
{
"path": "content-src/aboutlibrary/aboutlibrary.jsx",
"chars": 233,
"preview": "import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\nclass LibraryRouter extends React.PureComponent {\n render"
},
{
"path": "content-src/aboutlibrary/aboutlibrary.scss",
"chars": 238,
"preview": "\n.under-construction {\n background-image: url('chrome://browser/content/illustrations/under-construction.svg');\n backg"
},
{
"path": "content-src/activity-stream.jsx",
"chars": 1077,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/README.md",
"chars": 1286,
"preview": "# Activity Stream Router\n\n## Preferences `browser.newtab.activity-stream.asrouter.*`\n\nName | Used for | Type | Example v"
},
{
"path": "content-src/asrouter/asrouter-content.jsx",
"chars": 13737,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/components/Button/Button.jsx",
"chars": 866,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/components/Button/_Button.scss",
"chars": 1259,
"preview": ".ASRouterButton {\n font-weight: 600;\n font-size: 14px;\n white-space: nowrap;\n border-radius: 2px;\n border: 0;\n fon"
},
{
"path": "content-src/asrouter/components/ConditionalWrapper/ConditionalWrapper.jsx",
"chars": 423,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/components/FxASignupForm/FxASignupForm.jsx",
"chars": 5300,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/components/FxASignupForm/_FxASignupForm.scss",
"chars": 1870,
"preview": ".fxaSignupForm {\n min-width: 260px;\n text-align: center;\n\n a {\n color: $white;\n text-decoration: underline;\n }"
},
{
"path": "content-src/asrouter/components/ImpressionsWrapper/ImpressionsWrapper.jsx",
"chars": 2289,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/components/ModalOverlay/ModalOverlay.jsx",
"chars": 2776,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/components/ModalOverlay/_ModalOverlay.scss",
"chars": 2429,
"preview": ".activity-stream {\n &.modal-open {\n overflow: hidden;\n }\n}\n\n.modalOverlayOuter {\n background: var(--newtab-overlay"
},
{
"path": "content-src/asrouter/components/RichText/RichText.jsx",
"chars": 2284,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/components/SnippetBase/SnippetBase.jsx",
"chars": 3238,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/components/SnippetBase/_SnippetBase.scss",
"chars": 2491,
"preview": ".SnippetBaseContainer {\n position: fixed;\n z-index: 2;\n bottom: 0;\n left: 0;\n right: 0;\n background-color: var(--n"
},
{
"path": "content-src/asrouter/docs/debugging-docs.md",
"chars": 2964,
"preview": "# Using ASRouter Devtools\n\n## How to enable ASRouter devtools\n- In `about:config`, set `browser.newtabpage.activity-stre"
},
{
"path": "content-src/asrouter/docs/experiment-guide.md",
"chars": 2380,
"preview": "# How to run experiments with ASRouter\n\nThis guide will tell you how to run an experiment with ASRouter messages.\nNote t"
},
{
"path": "content-src/asrouter/docs/targeting-attributes.md",
"chars": 15347,
"preview": "# Targeting attributes\n\nWhen you create ASRouter messages such as snippets, contextual feature recommendations, or onboa"
},
{
"path": "content-src/asrouter/docs/targeting-guide.md",
"chars": 953,
"preview": "# Guide to targeting with JEXL\n\nFor a more in-depth explanation of JEXL syntax you can read the [Normady project docs](h"
},
{
"path": "content-src/asrouter/docs/user-actions.md",
"chars": 2940,
"preview": "# User Actions\n\nA subset of actions are available to messages via fields like `button_action` for snippets, or `primary_"
},
{
"path": "content-src/asrouter/rich-text-strings.js",
"chars": 1504,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/schemas/message-format.md",
"chars": 5829,
"preview": "## Activity Stream Router message format\n\nField name | Type | Required | Description | Example / Note\n--- | -"
},
{
"path": "content-src/asrouter/schemas/panel/cfr-fxa-bookmark.schema.json",
"chars": 4484,
"preview": "{\n \"title\": \"CFRFxABookmark\",\n \"description\": \"A message shown in the bookmark panel when user adds or edits a bookmar"
},
{
"path": "content-src/asrouter/schemas/provider-response.schema.json",
"chars": 4482,
"preview": "{\n \"title\": \"ProviderResponse\",\n \"description\": \"A response object for remote providers of AS Router\",\n \"type\": \"obje"
},
{
"path": "content-src/asrouter/template-utils.js",
"chars": 596,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/CFR/templates/ExtensionDoorhanger.schema.json",
"chars": 12475,
"preview": "{\n \"title\": \"ExtensionDoorhanger\",\n \"description\": \"A template with a heading, addon icon, title and description. No m"
},
{
"path": "content-src/asrouter/templates/EOYSnippet/EOYSnippet.jsx",
"chars": 4740,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/EOYSnippet/EOYSnippet.schema.json",
"chars": 4869,
"preview": "{\n \"title\": \"EOYSnippet\",\n \"description\": \"Fundraising Snippet\",\n \"version\": \"1.1.0\",\n \"type\": \"object\",\n \"definiti"
},
{
"path": "content-src/asrouter/templates/EOYSnippet/_EOYSnippet.scss",
"chars": 1030,
"preview": ".EOYSnippetForm {\n margin: 10px 0 8px;\n align-self: start;\n font-size: 14px;\n display: flex;\n align-items: center;\n"
},
{
"path": "content-src/asrouter/templates/FXASignupSnippet/FXASignupSnippet.jsx",
"chars": 1495,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/FXASignupSnippet/FXASignupSnippet.schema.json",
"chars": 6039,
"preview": "{\n \"title\": \"FXASignupSnippet\",\n \"description\": \"A snippet template for FxA sign up/sign in\",\n \"version\": \"1.2.0\",\n "
},
{
"path": "content-src/asrouter/templates/FirstRun/FirstRun.jsx",
"chars": 6622,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/FirstRun/Interrupt.jsx",
"chars": 2411,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/FirstRun/Triplets.jsx",
"chars": 2979,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/FirstRun/addUtmParams.js",
"chars": 984,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/FullPageInterrupt/FullPageInterrupt.jsx",
"chars": 5509,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/FullPageInterrupt/_FullPageInterrupt.scss",
"chars": 4597,
"preview": ".activity-stream {\n &.welcome {\n overflow: hidden;\n }\n\n &:not(.welcome) {\n .fullpage-wrapper {\n display: n"
},
{
"path": "content-src/asrouter/templates/NewsletterSnippet/NewsletterSnippet.jsx",
"chars": 1512,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/NewsletterSnippet/NewsletterSnippet.schema.json",
"chars": 5805,
"preview": "{\n \"title\": \"NewsletterSnippet\",\n \"description\": \"A snippet template for send to device mobile download\",\n \"version\":"
},
{
"path": "content-src/asrouter/templates/OnboardingMessage/OnboardingMessage.jsx",
"chars": 1516,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/OnboardingMessage/OnboardingMessage.schema.json",
"chars": 4072,
"preview": "{\n \"title\": \"OnboardingMessage\",\n \"description\": \"A template with a title, icon, button and description. No markup all"
},
{
"path": "content-src/asrouter/templates/OnboardingMessage/ToolbarBadgeMessage.schema.json",
"chars": 1114,
"preview": "{\n \"title\": \"ToolbarBadgeMessage\",\n \"description\": \"A template that specifies to which element in the browser toolbar "
},
{
"path": "content-src/asrouter/templates/OnboardingMessage/UpdateAction.schema.json",
"chars": 1057,
"preview": "{\n \"title\": \"UpdateActionMessage\",\n \"description\": \"A template for messages that execute predetermined actions.\",\n \"v"
},
{
"path": "content-src/asrouter/templates/OnboardingMessage/WhatsNewMessage.schema.json",
"chars": 2747,
"preview": "{\n \"title\": \"WhatsNewMessage\",\n \"description\": \"A template for the messages that appear in the What's New panel.\",\n \""
},
{
"path": "content-src/asrouter/templates/OnboardingMessage/_OnboardingMessage.scss",
"chars": 4088,
"preview": ".onboardingMessage {\n height: 340px;\n text-align: center;\n padding: 13px;\n font-weight: 200;\n\n // at 850px, img flo"
},
{
"path": "content-src/asrouter/templates/ReturnToAMO/ReturnToAMO.jsx",
"chars": 3029,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/ReturnToAMO/_ReturnToAMO.scss",
"chars": 2114,
"preview": ".ReturnToAMOOverlay,\n.amo + body.hide-main { // sass-lint:disable-line no-qualifying-elements\n background: $grey-10;\n "
},
{
"path": "content-src/asrouter/templates/SendToDeviceSnippet/SendToDeviceSnippet.jsx",
"chars": 2612,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/SendToDeviceSnippet/SendToDeviceSnippet.schema.json",
"chars": 7792,
"preview": "{\n \"title\": \"SendToDeviceSnippet\",\n \"description\": \"A snippet template for send to device mobile download\",\n \"version"
},
{
"path": "content-src/asrouter/templates/SendToDeviceSnippet/isEmailOrPhoneNumber.js",
"chars": 1434,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/SimpleBelowSearchSnippet/SimpleBelowSearchSnippet.jsx",
"chars": 3859,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/SimpleBelowSearchSnippet/SimpleBelowSearchSnippet.schema.json",
"chars": 3371,
"preview": "{\n \"title\": \"SimpleBelowSearchSnippet\",\n \"description\": \"A simple template with an icon, rich text and an optional but"
},
{
"path": "content-src/asrouter/templates/SimpleBelowSearchSnippet/_SimpleBelowSearchSnippet.scss",
"chars": 4857,
"preview": "\n.below-search-snippet {\n margin: 0 auto 16px;\n\n &.withButton {\n padding: 0 25px;\n margin: auto;\n min-height:"
},
{
"path": "content-src/asrouter/templates/SimpleSnippet/SimpleSnippet.jsx",
"chars": 6195,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/SimpleSnippet/SimpleSnippet.schema.json",
"chars": 4762,
"preview": "{\n \"title\": \"SimpleSnippet\",\n \"description\": \"A simple template with an icon, text, and optional button.\",\n \"version\""
},
{
"path": "content-src/asrouter/templates/SimpleSnippet/_SimpleSnippet.scss",
"chars": 2293,
"preview": "$section-header-height: 30px;\n$icon-width: 54px; // width of primary icon + margin\n\n.SimpleSnippet {\n &.tall {\n padd"
},
{
"path": "content-src/asrouter/templates/SubmitFormSnippet/SubmitFormSnippet.jsx",
"chars": 9006,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/SubmitFormSnippet/SubmitFormSnippet.schema.json",
"chars": 7841,
"preview": "{\n \"title\": \"SubmitFormSnippet\",\n \"description\": \"A template with two states: a SimpleSnippet and another that contain"
},
{
"path": "content-src/asrouter/templates/SubmitFormSnippet/_SubmitFormSnippet.scss",
"chars": 2138,
"preview": ".SubmitFormSnippet {\n flex-direction: column;\n flex: 1 1 100%;\n width: 100%;\n\n .disclaimerText {\n margin: 20px 0 "
},
{
"path": "content-src/asrouter/templates/Trailhead/Trailhead.jsx",
"chars": 4908,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/asrouter/templates/Trailhead/_Trailhead.scss",
"chars": 7752,
"preview": ".trailhead {\n $benefit-icon-size: 62px;\n $benefit-icon-spacing: $benefit-icon-size + 12px;\n $benefit-icon-size-small:"
},
{
"path": "content-src/asrouter/templates/template-manifest.jsx",
"chars": 978,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/A11yLinkButton/A11yLinkButton.jsx",
"chars": 544,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/A11yLinkButton/_A11yLinkButton.scss",
"chars": 193,
"preview": "\n.a11y-link-button {\n border: 0;\n padding: 0;\n cursor: pointer;\n text-align: unset;\n color: var(--newtab-link-prima"
},
{
"path": "content-src/components/ASRouterAdmin/ASRouterAdmin.jsx",
"chars": 37215,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/ASRouterAdmin/ASRouterAdmin.scss",
"chars": 3450,
"preview": "\n.asrouter-toggle {\n position: fixed;\n top: 15px;\n right: 48px;\n border: 0;\n background: none;\n z-index: 1;\n bord"
},
{
"path": "content-src/components/ASRouterAdmin/SimpleHashRouter.jsx",
"chars": 915,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/Base/Base.jsx",
"chars": 6188,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/Base/_Base.scss",
"chars": 2638,
"preview": ".outer-wrapper {\n color: var(--newtab-text-primary-color);\n display: flex;\n flex-grow: 1;\n min-height: 100vh;\n padd"
},
{
"path": "content-src/components/Card/Card.jsx",
"chars": 11237,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/Card/_Card.scss",
"chars": 6672,
"preview": ".card-outer {\n @include context-menu-button;\n background: var(--newtab-card-background-color);\n border-radius: $borde"
},
{
"path": "content-src/components/Card/types.js",
"chars": 752,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/CollapsibleSection/CollapsibleSection.jsx",
"chars": 9523,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/CollapsibleSection/_CollapsibleSection.scss",
"chars": 3272,
"preview": ".collapsible-section {\n padding: $section-vertical-padding $section-horizontal-padding;\n transition-delay: 100ms;\n tr"
},
{
"path": "content-src/components/ComponentPerfTimer/ComponentPerfTimer.jsx",
"chars": 5758,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/ConfirmDialog/ConfirmDialog.jsx",
"chars": 2895,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/ConfirmDialog/_ConfirmDialog.scss",
"chars": 1034,
"preview": ".confirmation-dialog {\n .modal {\n box-shadow: 0 2px 2px 0 $black-10;\n left: 0;\n margin: auto;\n position: fi"
},
{
"path": "content-src/components/ContextMenu/ContextMenu.jsx",
"chars": 4775,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/ContextMenu/ContextMenuButton.jsx",
"chars": 1911,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/ContextMenu/_ContextMenu.scss",
"chars": 1196,
"preview": ".context-menu {\n background: var(--newtab-contextmenu-background-color);\n border-radius: $context-menu-border-radius;\n"
},
{
"path": "content-src/components/DiscoveryStreamBase/DiscoveryStreamBase.jsx",
"chars": 14248,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamBase/_DiscoveryStreamBase.scss",
"chars": 1129,
"preview": "$ds-width: 936px;\n\n.discovery-stream.ds-layout {\n $columns: 12;\n --gridColumnGap: 48px;\n --gridRowGap: 24px;\n displa"
},
{
"path": "content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid.jsx",
"chars": 2853,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/CardGrid/_CardGrid.scss",
"chars": 1403,
"preview": "$col4-header-line-height: 20;\n$col4-header-font-size: 14;\n\n.ds-card-grid {\n display: grid;\n grid-gap: 24px;\n\n .ds-car"
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSCard/DSCard.jsx",
"chars": 7224,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss",
"chars": 4266,
"preview": "// Type sizes\n$header-font-size: 17;\n$header-line-height: 24;\n$excerpt-font-size: 14;\n$excerpt-line-height: 20;\n\n.ds-car"
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSContextFooter/DSContextFooter.jsx",
"chars": 1870,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSContextFooter/_DSContextFooter.scss",
"chars": 1882,
"preview": "$status-green: #058B00;\n$status-dark-green: #7C6;\n\n.story-footer {\n color: var(--newtab-text-secondary-color);\n inset-"
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSDismiss/DSDismiss.jsx",
"chars": 1995,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSDismiss/_DSDismiss.scss",
"chars": 1183,
"preview": ".ds-dismiss {\n position: relative;\n overflow: hidden;\n border-radius: 8px;\n transition-delay: 100ms;\n transition-du"
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSEmptyState/DSEmptyState.jsx",
"chars": 2445,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSEmptyState/_DSEmptyState.scss",
"chars": 1766,
"preview": ".section-empty-state {\n border: $border-secondary;\n border-radius: 4px;\n display: flex;\n height: $card-height-compac"
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSImage/DSImage.jsx",
"chars": 4950,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSImage/_DSImage.scss",
"chars": 342,
"preview": ".ds-image {\n display: block;\n position: relative;\n opacity: 0;\n\n &.use-transition {\n transition: opacity 0.8s;\n "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSLinkMenu/DSLinkMenu.jsx",
"chars": 2957,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSLinkMenu/_DSLinkMenu.scss",
"chars": 447,
"preview": ".ds-hero-item,\n.ds-list-item,\n.ds-card {\n @include context-menu-button;\n\n .context-menu {\n opacity: 0;\n }\n\n &.act"
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSMessage/DSMessage.jsx",
"chars": 1136,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSMessage/_DSMessage.scss",
"chars": 768,
"preview": ".ds-message {\n margin: 8px 0 0;\n\n .title {\n display: flex;\n align-items: center;\n\n .glyph {\n @include da"
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSPrivacyModal/DSPrivacyModal.jsx",
"chars": 1646,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSPrivacyModal/_DSPrivacyModal.scss",
"chars": 152,
"preview": ".ds-privacy-modal {\n a:hover {\n text-decoration: underline;\n }\n\n .privacy-notice {\n width: 492px;\n padding: "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSTextPromo/DSTextPromo.jsx",
"chars": 2335,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/DSTextPromo/_DSTextPromo.scss",
"chars": 1470,
"preview": ".ds-dismiss-ds-text-promo {\n width: 744px;\n margin: auto;\n}\n\n.ds-text-promo {\n display: flex;\n max-width: 640px;\n m"
},
{
"path": "content-src/components/DiscoveryStreamComponents/Hero/Hero.jsx",
"chars": 6116,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/Hero/_Hero.scss",
"chars": 4750,
"preview": "$card-header-in-hero-font-size: 14;\n$card-header-in-hero-line-height: 20;\n\n.ds-hero {\n position: relative;\n\n header {\n"
},
{
"path": "content-src/components/DiscoveryStreamComponents/Highlights/Highlights.jsx",
"chars": 790,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/Highlights/_Highlights.scss",
"chars": 720,
"preview": ".ds-highlights {\n .section {\n margin: 0 (-$section-horizontal-padding);\n\n .section-list {\n grid-gap: var(--g"
},
{
"path": "content-src/components/DiscoveryStreamComponents/HorizontalRule/HorizontalRule.jsx",
"chars": 348,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/HorizontalRule/_HorizontalRule.scss",
"chars": 72,
"preview": ".ds-hr {\n @include ds-border-top {\n border: 0;\n };\n\n height: 0;\n}\n"
},
{
"path": "content-src/components/DiscoveryStreamComponents/List/List.jsx",
"chars": 6740,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/List/_List.scss",
"chars": 5591,
"preview": "// Type sizes\n$bordered-spacing: 16px;\n$item-font-size: 14;\n$item-image-size: 80px;\n$item-line-height: 20;\n\n// XXX this "
},
{
"path": "content-src/components/DiscoveryStreamComponents/Navigation/Navigation.jsx",
"chars": 1232,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/Navigation/_Navigation.scss",
"chars": 780,
"preview": ".ds-navigation {\n line-height: 32px;\n padding: 4px 0;\n font-size: 14px;\n font-weight: 600;\n\n &.ds-navigation-center"
},
{
"path": "content-src/components/DiscoveryStreamComponents/SafeAnchor/SafeAnchor.jsx",
"chars": 1754,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/SectionTitle/SectionTitle.jsx",
"chars": 566,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/SectionTitle/_SectionTitle.scss",
"chars": 392,
"preview": ".ds-section-title {\n text-align: center;\n margin-top: 24px;\n\n .title {\n @include dark-theme-only {\n color: $w"
},
{
"path": "content-src/components/DiscoveryStreamComponents/TopSites/TopSites.jsx",
"chars": 4842,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamComponents/TopSites/_TopSites.scss",
"chars": 2666,
"preview": "$top-sites-vertical-space-with-spoc: 20px;\n\n// ds topsites wraps the original topsites, with a few css changes.\n.ds-top-"
},
{
"path": "content-src/components/DiscoveryStreamImpressionStats/ImpressionStats.jsx",
"chars": 6349,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/DiscoveryStreamImpressionStats/_ImpressionStats.scss",
"chars": 112,
"preview": ".impression-observer {\n position: absolute;\n top: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n}\n"
},
{
"path": "content-src/components/ErrorBoundary/ErrorBoundary.jsx",
"chars": 1913,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/ErrorBoundary/_ErrorBoundary.scss",
"chars": 486,
"preview": ".as-error-fallback {\n align-items: center;\n border-radius: $border-radius;\n box-shadow: inset $inner-box-shadow;\n co"
},
{
"path": "content-src/components/FluentOrText/FluentOrText.jsx",
"chars": 1312,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/LinkMenu/LinkMenu.jsx",
"chars": 2700,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/MoreRecommendations/MoreRecommendations.jsx",
"chars": 601,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/MoreRecommendations/_MoreRecommendations.scss",
"chars": 520,
"preview": ".more-recommendations {\n display: flex;\n align-items: center;\n white-space: nowrap;\n line-height: 1.230769231; // (1"
},
{
"path": "content-src/components/PocketLoggedInCta/PocketLoggedInCta.jsx",
"chars": 1226,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/PocketLoggedInCta/_PocketLoggedInCta.scss",
"chars": 917,
"preview": ".pocket-logged-in-cta {\n $max-button-width: 130px;\n $min-button-height: 18px;\n font-size: 13px;\n margin-inline-end: "
},
{
"path": "content-src/components/Search/Search.jsx",
"chars": 6510,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/Search/_Search.scss",
"chars": 8733,
"preview": "$search-height: 48px;\n$search-icon-size: 24px;\n$search-icon-padding: 12px;\n$search-icon-width: 2 * $search-icon-padding "
},
{
"path": "content-src/components/SectionMenu/SectionMenu.jsx",
"chars": 3052,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/Sections/Sections.jsx",
"chars": 12400,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/Sections/_Sections.scss",
"chars": 2982,
"preview": ".sections-list {\n .section-list {\n display: grid;\n grid-gap: $base-gutter;\n grid-template-columns: repeat(auto"
},
{
"path": "content-src/components/TopSites/SearchShortcutsForm.jsx",
"chars": 5395,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/TopSites/TopSite.jsx",
"chars": 21389,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/TopSites/TopSiteForm.jsx",
"chars": 9864,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/TopSites/TopSiteFormInput.jsx",
"chars": 3182,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/TopSites/TopSites.jsx",
"chars": 6864,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/TopSites/TopSitesConstants.js",
"chars": 1105,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/TopSites/_TopSites.scss",
"chars": 13530,
"preview": "$top-sites-size: $grid-unit;\n$top-sites-border-radius: 4px;\n$top-sites-title-height: 30px;\n$top-sites-vertical-space: 8p"
},
{
"path": "content-src/components/Topics/Topics.jsx",
"chars": 801,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/components/Topics/_Topics.scss",
"chars": 320,
"preview": ".topics {\n ul {\n margin: 0;\n padding: 0;\n @media (min-width: $break-point-large) {\n display: inline;\n "
},
{
"path": "content-src/lib/constants.js",
"chars": 601,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/lib/detect-user-session-start.js",
"chars": 2711,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/lib/init-store.js",
"chars": 5199,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/lib/link-menu-options.js",
"chars": 7861,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/lib/screenshot-utils.js",
"chars": 2174,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/lib/section-menu-options.js",
"chars": 2986,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/lib/selectLayoutRender.js",
"chars": 7293,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "content-src/styles/_activity-stream.scss",
"chars": 5057,
"preview": "@import './normalize';\n@import './variables';\n@import './theme';\n@import './icons';\n@import './mixins';\n\nhtml {\n height"
},
{
"path": "content-src/styles/_icons.scss",
"chars": 4783,
"preview": ".icon {\n background-position: center center;\n background-repeat: no-repeat;\n background-size: $icon-size;\n -moz-cont"
},
{
"path": "content-src/styles/_mixins.scss",
"chars": 1161,
"preview": "// Shared styling of article images shown as background\n@mixin image-as-background {\n background-color: var(--newtab-ca"
},
{
"path": "content-src/styles/_normalize.scss",
"chars": 340,
"preview": "html {\n box-sizing: border-box;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n*::-moz-focus-inner {\n border: 0"
},
{
"path": "content-src/styles/_theme.scss",
"chars": 6604,
"preview": "@function textbox-shadow($color) {\n @return 0 0 0 1px $color, 0 0 0 $textbox-shadow-size rgba($color, 0.3);\n}\n\n@mixin t"
},
{
"path": "content-src/styles/_variables.scss",
"chars": 6813,
"preview": "// Photon colors from http://design.firefox.com/photon/visuals/color.html\n$blue-40: #45A1FF;\n$blue-50: #0A84FF;\n$blue-60"
},
{
"path": "content-src/styles/activity-stream-linux.scss",
"chars": 446,
"preview": "// sass-lint:disable no-css-comments\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, "
},
{
"path": "content-src/styles/activity-stream-mac.scss",
"chars": 511,
"preview": "// sass-lint:disable no-css-comments\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, "
},
{
"path": "content-src/styles/activity-stream-windows.scss",
"chars": 448,
"preview": "// sass-lint:disable no-css-comments\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, "
},
{
"path": "contributing.md",
"chars": 9058,
"preview": "# Contributing to Activity Stream\n\nActivity Stream is an enhancement to the functionality of Firefox's about:newtab page"
},
{
"path": "data/content/tippytop/top_sites.json",
"chars": 2374,
"preview": "[\n {\n \"title\": \"aliexpress\",\n \"url\": \"https://www.aliexpress.com/\",\n \"image_url\": \"aliexpress-com@2x.png\"\n },"
},
{
"path": "docs/ISSUE_TEMPLATE.md",
"chars": 284,
"preview": "Please file new bugs in Bugzilla:\nhttps://bugzilla.mozilla.org/enter_bug.cgi?product=Firefox&component=Activity%20Stream"
},
{
"path": "docs/index.rst",
"chars": 2817,
"preview": "======================\nFirefox Home (New Tab)\n======================\n\nAll files related to Firefox Home, which includes "
},
{
"path": "docs/v2-system-addon/1.GETTING_STARTED.md",
"chars": 4847,
"preview": "# Activity Stream Development Guide\n\n## Contents of this guide\n\n- Installation, set-up, and other basics (this page)\n- ["
},
{
"path": "docs/v2-system-addon/data_dictionary.md",
"chars": 15481,
"preview": "# Activity Stream Pings\n\nThe Activity Stream system add-on sends various types of pings to the backend (HTTPS POST) [Ony"
},
{
"path": "docs/v2-system-addon/data_events.md",
"chars": 33964,
"preview": "# Metrics we collect\n\nBy default, the about:newtab, about:welcome and about:home pages in Firefox (the pages you see whe"
},
{
"path": "docs/v2-system-addon/geo_locale.md",
"chars": 1267,
"preview": "# Setting custom `geo`, `locale`, and update channels\n\nThere are instances where you may need to change your local build"
},
{
"path": "docs/v2-system-addon/mochitests.md",
"chars": 4975,
"preview": "We use [mochitests](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Mochitest) to do functional (and possibly "
},
{
"path": "docs/v2-system-addon/preferences.md",
"chars": 7628,
"preview": "# Preferences in Activity Stream\n\n## Preference branch\n\nThe preference branch for activity stream is `browser.newtabpage"
},
{
"path": "docs/v2-system-addon/remote_cfr.md",
"chars": 4694,
"preview": "# Remote CFR Messages\nStarting in Firefox 68, CFR messages will be defined using [Remote Settings](https://remote-settin"
},
{
"path": "docs/v2-system-addon/sections.md",
"chars": 3456,
"preview": "# Sections in Activity Stream\n\nEach section in Activity Stream displays data from a corresponding section feed\nin a stan"
},
{
"path": "docs/v2-system-addon/telemetry.md",
"chars": 1846,
"preview": "# Adding/Changing Telemetry Checklist\n\nAdding telemetry generally involves a few steps:\n\n1. File a \"user story\" bug abou"
},
{
"path": "docs/v2-system-addon/test-merges.md",
"chars": 1182,
"preview": "## bin/test-merges.js documentation\n\nA script intended to be run from cron regularly. It notices when a new PR has been"
}
]
// ... and 226 more files (download for full content)
About this extraction
This page contains the full source code of the mozilla/activity-stream GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 426 files (4.1 MB), approximately 1.1M tokens, and a symbol index with 2173 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.