summaryrefslogtreecommitdiffstats
path: root/application
diff options
context:
space:
mode:
Diffstat (limited to 'application')
-rw-r--r--application/basilisk/app/profile/basilisk.js71
-rw-r--r--application/basilisk/base/content/aboutNetError.xhtml2
-rw-r--r--application/basilisk/base/content/aboutRobots-icon.pngbin9817 -> 0 bytes
-rw-r--r--application/basilisk/base/content/aboutRobots-widget-left.pngbin2224 -> 0 bytes
-rw-r--r--application/basilisk/base/content/aboutRobots.xhtml108
-rw-r--r--application/basilisk/base/content/aboutaccounts/aboutaccounts.css24
-rw-r--r--application/basilisk/base/content/aboutaccounts/aboutaccounts.js543
-rw-r--r--application/basilisk/base/content/aboutaccounts/aboutaccounts.xhtml112
-rw-r--r--application/basilisk/base/content/aboutaccounts/images/fox.pngbin1951 -> 0 bytes
-rw-r--r--application/basilisk/base/content/aboutaccounts/images/graphic_sync_intro.pngbin6441 -> 0 bytes
-rw-r--r--application/basilisk/base/content/aboutaccounts/images/graphic_sync_intro@2x.pngbin12852 -> 0 bytes
-rw-r--r--application/basilisk/base/content/aboutaccounts/main.css166
-rw-r--r--application/basilisk/base/content/aboutaccounts/normalize.css402
-rw-r--r--application/basilisk/base/content/abouthome/aboutHome.css4
-rw-r--r--application/basilisk/base/content/abouthome/aboutHome.xhtml2
-rw-r--r--application/basilisk/base/content/browser-addons.js13
-rw-r--r--application/basilisk/base/content/browser-context.inc30
-rw-r--r--application/basilisk/base/content/browser-doctype.inc2
-rw-r--r--application/basilisk/base/content/browser-fxaccounts.js314
-rw-r--r--application/basilisk/base/content/browser-menubar.inc43
-rw-r--r--application/basilisk/base/content/browser-places.js13
-rw-r--r--application/basilisk/base/content/browser-sets.inc7
-rw-r--r--application/basilisk/base/content/browser-syncui.js599
-rw-r--r--application/basilisk/base/content/browser.css12
-rw-r--r--application/basilisk/base/content/browser.js218
-rw-r--r--application/basilisk/base/content/browser.xul78
-rw-r--r--application/basilisk/base/content/content.js6
-rw-r--r--application/basilisk/base/content/global-scripts.inc2
-rw-r--r--application/basilisk/base/content/newtab/alternativeDefaultSites.json50
-rw-r--r--application/basilisk/base/content/newtab/customize.js8
-rw-r--r--application/basilisk/base/content/newtab/grid.js15
-rw-r--r--application/basilisk/base/content/newtab/newTab.css112
-rw-r--r--application/basilisk/base/content/newtab/newTab.inadjacent.json3209
-rw-r--r--application/basilisk/base/content/newtab/newTab.js1
-rw-r--r--application/basilisk/base/content/newtab/newTab.xhtml1
-rw-r--r--application/basilisk/base/content/newtab/page.js61
-rw-r--r--application/basilisk/base/content/newtab/sites.js105
-rw-r--r--application/basilisk/base/content/nsContextMenu.js39
-rw-r--r--application/basilisk/base/content/sync/customize.css28
-rw-r--r--application/basilisk/base/content/sync/customize.js25
-rw-r--r--application/basilisk/base/content/sync/customize.xul62
-rw-r--r--application/basilisk/base/content/tab-content.js33
-rw-r--r--application/basilisk/base/content/tabbrowser.xml199
-rw-r--r--application/basilisk/base/content/utilityOverlay.js113
-rw-r--r--application/basilisk/base/content/web-panels.xul1
-rw-r--r--application/basilisk/base/jar.mn40
-rw-r--r--application/basilisk/components/about/AboutRedirector.cpp15
-rw-r--r--application/basilisk/components/build/nsModule.cpp5
-rw-r--r--application/basilisk/components/contextualidentity/content/usercontext.css91
-rw-r--r--application/basilisk/components/contextualidentity/jar.mn6
-rw-r--r--application/basilisk/components/customizableui/CustomizableUI.jsm23
-rw-r--r--application/basilisk/components/customizableui/CustomizableWidgets.jsm228
-rw-r--r--application/basilisk/components/customizableui/CustomizeMode.jsm9
-rw-r--r--application/basilisk/components/customizableui/content/panelUI.inc.xul110
-rw-r--r--application/basilisk/components/customizableui/moz.build5
-rw-r--r--application/basilisk/components/distribution.js19
-rw-r--r--application/basilisk/components/feeds/FeedWriter.js7
-rw-r--r--application/basilisk/components/feeds/WebContentConverter.js9
-rw-r--r--application/basilisk/components/moz.build8
-rw-r--r--application/basilisk/components/newtab/NewTabPrefsProvider.jsm2
-rw-r--r--application/basilisk/components/nsBrowserContentHandler.js15
-rw-r--r--application/basilisk/components/nsBrowserGlue.js155
-rw-r--r--application/basilisk/components/places/PlacesUIUtils.jsm6
-rw-r--r--application/basilisk/components/places/moz.build2
-rw-r--r--application/basilisk/components/preferences/containers.js176
-rw-r--r--application/basilisk/components/preferences/containers.xul52
-rw-r--r--application/basilisk/components/preferences/cookies.js39
-rw-r--r--application/basilisk/components/preferences/cookies.xul4
-rw-r--r--application/basilisk/components/preferences/handlers.css4
-rw-r--r--application/basilisk/components/preferences/handlers.xml23
-rw-r--r--application/basilisk/components/preferences/in-content/containers.js73
-rw-r--r--application/basilisk/components/preferences/in-content/containers.xul54
-rw-r--r--application/basilisk/components/preferences/in-content/jar.mn5
-rw-r--r--application/basilisk/components/preferences/in-content/preferences.js3
-rw-r--r--application/basilisk/components/preferences/in-content/preferences.xul19
-rw-r--r--application/basilisk/components/preferences/in-content/privacy.js88
-rw-r--r--application/basilisk/components/preferences/in-content/privacy.xul25
-rw-r--r--application/basilisk/components/preferences/in-content/sync.js451
-rw-r--r--application/basilisk/components/preferences/in-content/sync.xul327
-rw-r--r--application/basilisk/components/preferences/jar.mn2
-rw-r--r--application/basilisk/components/search/moz.build2
-rw-r--r--application/basilisk/components/search/service/SearchStaticData.jsm43
-rw-r--r--application/basilisk/components/search/service/SearchSuggestionController.jsm398
-rw-r--r--application/basilisk/components/search/service/moz.build24
-rw-r--r--application/basilisk/components/search/service/nsSearchService.js4324
-rw-r--r--application/basilisk/components/search/service/nsSearchSuggestions.js197
-rw-r--r--application/basilisk/components/search/service/nsSidebar.js66
-rw-r--r--application/basilisk/components/search/service/toolkitsearch.manifest10
-rw-r--r--application/basilisk/components/sessionstore/ContentRestore.jsm4
-rw-r--r--application/basilisk/components/sessionstore/SessionHistory.jsm3
-rw-r--r--application/basilisk/components/sessionstore/SessionStore.jsm42
-rw-r--r--application/basilisk/components/sessionstore/TabState.jsm4
-rw-r--r--application/basilisk/components/sync/aboutSyncTabs-bindings.xml (renamed from application/basilisk/base/content/sync/aboutSyncTabs-bindings.xml)0
-rw-r--r--application/basilisk/components/sync/aboutSyncTabs.css (renamed from application/basilisk/base/content/sync/aboutSyncTabs.css)0
-rw-r--r--application/basilisk/components/sync/aboutSyncTabs.js (renamed from application/basilisk/base/content/sync/aboutSyncTabs.js)121
-rw-r--r--application/basilisk/components/sync/aboutSyncTabs.xul (renamed from application/basilisk/base/content/sync/aboutSyncTabs.xul)0
-rw-r--r--application/basilisk/components/sync/addDevice.js (renamed from application/basilisk/base/content/sync/addDevice.js)0
-rw-r--r--application/basilisk/components/sync/addDevice.xul (renamed from application/basilisk/base/content/sync/addDevice.xul)2
-rw-r--r--application/basilisk/components/sync/genericChange.js (renamed from application/basilisk/base/content/sync/genericChange.js)15
-rw-r--r--application/basilisk/components/sync/genericChange.xul (renamed from application/basilisk/base/content/sync/genericChange.xul)4
-rw-r--r--application/basilisk/components/sync/jar.mn22
-rw-r--r--application/basilisk/components/sync/key.xhtml (renamed from application/basilisk/base/content/sync/key.xhtml)2
-rw-r--r--application/basilisk/components/sync/moz.build (renamed from application/basilisk/components/contextualidentity/moz.build)3
-rw-r--r--application/basilisk/components/sync/notification.xml129
-rw-r--r--application/basilisk/components/sync/progress.js71
-rw-r--r--application/basilisk/components/sync/progress.xhtml55
-rw-r--r--application/basilisk/components/sync/quota.js (renamed from application/basilisk/base/content/sync/quota.js)0
-rw-r--r--application/basilisk/components/sync/quota.xul (renamed from application/basilisk/base/content/sync/quota.xul)0
-rw-r--r--application/basilisk/components/sync/setup.js (renamed from application/basilisk/base/content/sync/setup.js)35
-rw-r--r--application/basilisk/components/sync/setup.xul (renamed from application/basilisk/base/content/sync/setup.xul)15
-rw-r--r--application/basilisk/components/sync/utils.js (renamed from application/basilisk/base/content/sync/utils.js)29
-rw-r--r--application/basilisk/components/syncedtabs/EventEmitter.jsm45
-rw-r--r--application/basilisk/components/syncedtabs/SyncedTabsDeckComponent.js169
-rw-r--r--application/basilisk/components/syncedtabs/SyncedTabsDeckStore.js60
-rw-r--r--application/basilisk/components/syncedtabs/SyncedTabsDeckView.js116
-rw-r--r--application/basilisk/components/syncedtabs/SyncedTabsListStore.js235
-rw-r--r--application/basilisk/components/syncedtabs/TabListComponent.js138
-rw-r--r--application/basilisk/components/syncedtabs/TabListView.js568
-rw-r--r--application/basilisk/components/syncedtabs/jar.mn7
-rw-r--r--application/basilisk/components/syncedtabs/moz.build17
-rw-r--r--application/basilisk/components/syncedtabs/sidebar.js30
-rw-r--r--application/basilisk/components/syncedtabs/sidebar.xhtml114
-rw-r--r--application/basilisk/components/syncedtabs/util.js23
-rw-r--r--application/basilisk/configure.in7
-rw-r--r--application/basilisk/extensions/pdfjs/content/PdfJs.jsm23
-rw-r--r--application/basilisk/extensions/pdfjs/content/PdfStreamConverter.jsm38
-rw-r--r--application/basilisk/fonts/TwemojiMozilla.ttfbin1057104 -> 1158828 bytes
-rw-r--r--application/basilisk/installer/allowed-dupes.mn2
-rw-r--r--application/basilisk/installer/package-manifest.in9
-rw-r--r--application/basilisk/installer/windows/nsis/installer.nsi31
-rw-r--r--application/basilisk/locales/en-US/chrome/browser-region/region.properties7
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/aboutAccounts.dtd16
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/aboutHome.dtd4
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/aboutRobots.dtd29
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/browser.dtd66
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/browser.properties31
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/newTab.dtd3
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/newTab.properties39
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/preferences/containers.dtd24
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/preferences/containers.properties31
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/preferences/cookies.dtd1
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/preferences/preferences.dtd1
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/preferences/preferences.properties14
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/preferences/privacy.dtd7
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/preferences/sync.dtd73
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/syncBrand.dtd1
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/syncKey.dtd8
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/syncProgress.dtd15
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/syncQuota.properties2
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/syncSetup.dtd18
-rw-r--r--application/basilisk/locales/en-US/chrome/browser/syncSetup.properties28
-rw-r--r--application/basilisk/locales/en-US/installer/custom.properties4
-rw-r--r--application/basilisk/locales/jar.mn15
-rw-r--r--application/basilisk/modules/AboutHome.jsm2
-rw-r--r--application/basilisk/modules/AboutNewTab.jsm1
-rw-r--r--application/basilisk/modules/ContentClick.jsm5
-rw-r--r--application/basilisk/modules/DirectoryLinksProvider.jsm1255
-rw-r--r--application/basilisk/modules/PermissionUI.jsm23
-rw-r--r--application/basilisk/modules/ProcessHangMonitor.jsm2
-rw-r--r--application/basilisk/modules/moz.build1
-rw-r--r--application/basilisk/themes/linux/jar.mn6
-rw-r--r--application/basilisk/themes/linux/syncProgress.css46
-rw-r--r--application/basilisk/themes/linux/syncedtabs/sidebar.css69
-rw-r--r--application/basilisk/themes/osx/jar.mn10
-rw-r--r--application/basilisk/themes/osx/syncProgress.css46
-rw-r--r--application/basilisk/themes/osx/syncedtabs/sidebar.css154
-rw-r--r--application/basilisk/themes/shared/browser.inc2
-rw-r--r--application/basilisk/themes/shared/customizableui/panelUI.inc.css276
-rw-r--r--application/basilisk/themes/shared/incontentprefs/containers.css32
-rw-r--r--application/basilisk/themes/shared/incontentprefs/preferences.inc.css3
-rw-r--r--application/basilisk/themes/shared/jar.inc.mn2
-rw-r--r--application/basilisk/themes/shared/menupanel.inc.css19
-rw-r--r--application/basilisk/themes/shared/newtab/newTab.inc.css100
-rw-r--r--application/basilisk/themes/shared/preferences/containers.css53
-rw-r--r--application/basilisk/themes/shared/syncedtabs/sidebar.inc.css234
-rw-r--r--application/basilisk/themes/shared/toolbarbuttons.inc.css46
-rw-r--r--application/basilisk/themes/windows/jar.mn8
-rw-r--r--application/basilisk/themes/windows/syncProgress.css46
-rw-r--r--application/basilisk/themes/windows/syncedtabs/sidebar.css132
-rw-r--r--application/palemoon/app/blocklist.xml7
-rw-r--r--application/palemoon/app/moz.build1
-rw-r--r--application/palemoon/app/permissions14
-rw-r--r--application/palemoon/app/profile/palemoon.js11
-rw-r--r--application/palemoon/base/content/aboutRobots-icon.pngbin9817 -> 0 bytes
-rw-r--r--application/palemoon/base/content/aboutRobots-widget-left.pngbin2224 -> 0 bytes
-rw-r--r--application/palemoon/base/content/aboutRobots.xhtml108
-rw-r--r--application/palemoon/base/content/baseMenuOverlay.xul14
-rw-r--r--application/palemoon/base/content/browser-appmenu.inc13
-rw-r--r--application/palemoon/base/content/browser-menudragging.js26
-rw-r--r--application/palemoon/base/content/browser-syncui.js26
-rw-r--r--application/palemoon/base/content/browser.js22
-rw-r--r--application/palemoon/base/content/content.js2
-rw-r--r--application/palemoon/base/content/palemoon.xhtml6
-rw-r--r--application/palemoon/base/content/tabbrowser.xml60
-rw-r--r--application/palemoon/base/content/utilityOverlay.js79
-rw-r--r--application/palemoon/base/jar.mn3
-rw-r--r--application/palemoon/branding/official/firefox.icobin105959 -> 107919 bytes
-rw-r--r--application/palemoon/branding/shared/pref/preferences.inc4
-rw-r--r--application/palemoon/components/BrowserComponents.manifest1
-rw-r--r--application/palemoon/components/distribution.js14
-rw-r--r--application/palemoon/components/feeds/FeedWriter.js19
-rw-r--r--application/palemoon/components/feeds/WebContentConverter.js9
-rw-r--r--application/palemoon/components/fuel/fuelApplication.js4
-rw-r--r--application/palemoon/components/newtab/grid.js4
-rw-r--r--application/palemoon/components/newtab/page.js52
-rw-r--r--application/palemoon/components/newtab/sites.js14
-rw-r--r--application/palemoon/components/nsAboutRedirector.js4
-rw-r--r--application/palemoon/components/nsBrowserContentHandler.js15
-rw-r--r--application/palemoon/components/nsBrowserGlue.js15
-rw-r--r--application/palemoon/components/places/PlacesUIUtils.jsm7
-rw-r--r--application/palemoon/components/preferences/newtaburl.js36
-rw-r--r--application/palemoon/components/preferences/preferences.xul2
-rw-r--r--application/palemoon/components/preferences/tabs.js29
-rw-r--r--application/palemoon/components/search/content/search.xml5
-rw-r--r--application/palemoon/config/version.txt2
-rw-r--r--application/palemoon/configure.in4
-rw-r--r--application/palemoon/fonts/TwemojiMozilla.ttfbin1075912 -> 1158828 bytes
-rw-r--r--application/palemoon/installer/package-manifest.in8
-rw-r--r--application/palemoon/installer/windows/nsis/installer.nsi31
-rw-r--r--application/palemoon/locales/en-US/chrome/browser-region/region.properties24
-rw-r--r--application/palemoon/locales/en-US/chrome/browser/aboutRobots.dtd29
-rw-r--r--application/palemoon/locales/en-US/chrome/browser/baseMenuOverlay.dtd2
-rw-r--r--application/palemoon/locales/en-US/chrome/browser/palemoon.dtd17
-rw-r--r--application/palemoon/locales/jar.mn1
-rw-r--r--application/palemoon/themes/linux/browser.css2
-rw-r--r--application/palemoon/themes/osx/browser.css2
-rw-r--r--application/palemoon/themes/windows/browser.css2
227 files changed, 6592 insertions, 13353 deletions
diff --git a/application/basilisk/app/profile/basilisk.js b/application/basilisk/app/profile/basilisk.js
index 24f1c582c..c229f3523 100644
--- a/application/basilisk/app/profile/basilisk.js
+++ b/application/basilisk/app/profile/basilisk.js
@@ -346,18 +346,6 @@ pref("browser.search.order.1", "chrome://browser-region/locale/re
pref("browser.search.order.2", "chrome://browser-region/locale/region.properties");
pref("browser.search.order.3", "chrome://browser-region/locale/region.properties");
-// Market-specific search defaults
-// This is disabled globally, and then enabled for individual locales
-// in firefox-l10n.js (eg. it's enabled for en-US).
-pref("browser.search.geoSpecificDefaults", false);
-pref("browser.search.geoSpecificDefaults.url", "https://search.services.mozilla.com/1/%APP%/%VERSION%/%CHANNEL%/%LOCALE%/%REGION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%");
-
-// US specific default (used as a fallback if the geoSpecificDefaults request fails).
-pref("browser.search.defaultenginename.US", "data:text/plain,browser.search.defaultenginename.US=Google");
-pref("browser.search.order.US.1", "data:text/plain,browser.search.order.US.1=Google");
-pref("browser.search.order.US.2", "data:text/plain,browser.search.order.US.2=Yahoo");
-pref("browser.search.order.US.3", "data:text/plain,browser.search.order.US.3=Bing");
-
// search bar results always open in a new tab
pref("browser.search.openintab", false);
@@ -1052,12 +1040,6 @@ pref("browser.newtabpage.introShown", false);
// Toggles the content of 'about:newtab'. Shows the grid when enabled.
pref("browser.newtabpage.enabled", true);
-// Toggles the enhanced content of 'about:newtab'. Shows sponsored tiles.
-sticky_pref("browser.newtabpage.enhanced", false);
-
-// enables Activity Stream inspired layout
-pref("browser.newtabpage.compact", false);
-
// Disables capturing of page thumbnails
pref("browser.pagethumbnails.capturing_disabled", false);
@@ -1171,53 +1153,11 @@ pref("browser.uiCustomization.debug", false);
// CustomizableUI state of the browser's user interface
pref("browser.uiCustomization.state", "");
-// The remote content URL shown for FxA signup. Must use HTTPS.
-pref("identity.fxaccounts.remote.signup.uri", "https://accounts.firefox.com/signup?service=sync&context=fx_desktop_v3");
-
-// The URL where remote content that forces re-authentication for Firefox Accounts
-// should be fetched. Must use HTTPS.
-pref("identity.fxaccounts.remote.force_auth.uri", "https://accounts.firefox.com/force_auth?service=sync&context=fx_desktop_v3");
-
-// The remote content URL shown for signin in. Must use HTTPS.
-pref("identity.fxaccounts.remote.signin.uri", "https://accounts.firefox.com/signin?service=sync&context=fx_desktop_v3");
-
-// The remote content URL where FxAccountsWebChannel messages originate.
-pref("identity.fxaccounts.remote.webchannel.uri", "https://accounts.firefox.com/");
-
-// The value of the context query parameter passed in some fxa requests when config
-// discovery is enabled.
-pref("identity.fxaccounts.contextParam", "fx_desktop_v3");
-
-// The URL we take the user to when they opt to "manage" their Firefox Account.
-// Note that this will always need to be in the same TLD as the
-// "identity.fxaccounts.remote.signup.uri" pref.
-pref("identity.fxaccounts.settings.uri", "https://accounts.firefox.com/settings?service=sync&context=fx_desktop_v3");
-
-// The remote URL of the FxA Profile Server
-pref("identity.fxaccounts.remote.profile.uri", "https://profile.accounts.firefox.com/v1");
-
-// The remote URL of the FxA OAuth Server
-pref("identity.fxaccounts.remote.oauth.uri", "https://oauth.accounts.firefox.com/v1");
-
-// Whether we display profile images in the UI or not.
-pref("identity.fxaccounts.profile_image.enabled", true);
-
-// Token server used by the FxA Sync identity.
-pref("identity.sync.tokenserver.uri", "https://token.services.mozilla.com/1.0/sync/1.5");
-
// URLs for promo links to mobile browsers. Note that consumers are expected to
// append a value for utm_campaign.
pref("identity.mobilepromo.android", "https://www.mozilla.org/firefox/android/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=");
pref("identity.mobilepromo.ios", "https://www.mozilla.org/firefox/ios/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=");
-// Migrate any existing Firefox Account data from the default profile to the
-// Developer Edition profile.
-#ifdef MOZ_DEV_EDITION
-pref("identity.fxaccounts.migrateToDevEdition", true);
-#else
-pref("identity.fxaccounts.migrateToDevEdition", false);
-#endif
-
// On GTK, we now default to showing the menubar only when alt is pressed:
#ifdef MOZ_WIDGET_GTK
pref("ui.key.menuAccessKeyFocuses", true);
@@ -1293,17 +1233,6 @@ pref("privacy.trackingprotection.ui.enabled", true);
pref("privacy.trackingprotection.ui.enabled", false);
#endif
-// Enable Contextual Identity Containers
-#ifdef NIGHTLY_BUILD
-pref("privacy.userContext.enabled", true);
-pref("privacy.userContext.ui.enabled", true);
-pref("privacy.usercontext.about_newtab_segregation.enabled", true);
-#else
-pref("privacy.userContext.enabled", false);
-pref("privacy.userContext.ui.enabled", false);
-pref("privacy.usercontext.about_newtab_segregation.enabled", false);
-#endif
-
#ifndef RELEASE_OR_BETA
// At the moment, autostart.2 is used, while autostart.1 is unused.
// We leave it here set to false to reset users' defaults and allow
diff --git a/application/basilisk/base/content/aboutNetError.xhtml b/application/basilisk/base/content/aboutNetError.xhtml
index 3296600c8..5ff79ea12 100644
--- a/application/basilisk/base/content/aboutNetError.xhtml
+++ b/application/basilisk/base/content/aboutNetError.xhtml
@@ -362,7 +362,7 @@
// First, find the index of the <a> tag we care about, being
// careful not to use an over-greedy regex.
var re = /<a id="cert_domain_link" title="([^"]+)">/;
- var result = domainRe.exec(desc);
+ var result = re.exec(desc);
if (!result)
return;
diff --git a/application/basilisk/base/content/aboutRobots-icon.png b/application/basilisk/base/content/aboutRobots-icon.png
deleted file mode 100644
index 1c4899aaf..000000000
--- a/application/basilisk/base/content/aboutRobots-icon.png
+++ /dev/null
Binary files differ
diff --git a/application/basilisk/base/content/aboutRobots-widget-left.png b/application/basilisk/base/content/aboutRobots-widget-left.png
deleted file mode 100644
index 3a1e48d5f..000000000
--- a/application/basilisk/base/content/aboutRobots-widget-left.png
+++ /dev/null
Binary files differ
diff --git a/application/basilisk/base/content/aboutRobots.xhtml b/application/basilisk/base/content/aboutRobots.xhtml
deleted file mode 100644
index 23fe3ba17..000000000
--- a/application/basilisk/base/content/aboutRobots.xhtml
+++ /dev/null
@@ -1,108 +0,0 @@
-<?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 [
- <!ENTITY % htmlDTD
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "DTD/xhtml1-strict.dtd">
- %htmlDTD;
- <!ENTITY % netErrorDTD
- SYSTEM "chrome://global/locale/netError.dtd">
- %netErrorDTD;
- <!ENTITY % globalDTD
- SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
- <!ENTITY % aboutrobotsDTD
- SYSTEM "chrome://browser/locale/aboutRobots.dtd">
- %aboutrobotsDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>&robots.pagetitle;</title>
- <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" />
- <link rel="icon" type="image/png" id="favicon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAACGFjVEwAAAASAAAAAJNtBPIAAAAaZmNUTAAAAAAAAAAQAAAAEAAAAAAAAAAALuAD6AABhIDeugAAALhJREFUOI2Nk8sNxCAMRDlGohauXFOMpfTiAlxICqAELltHLqlgctg1InzMRhpFAc%2BLGWTnmoeZYamt78zXdZmaQtQMADlnU0OIAlbmJUBEcO4bRKQY2rUXIPmAGnDuG%2FBx3%2FfvOPVaDUg%2BoAPUf1PArIMCSD5glMEsUGaG%2BkyAFWIBaCsKuA%2BHGCNijLgP133XgOEtaPFMy2vUolEGJoCIzBmoRUR9%2B7rxj16DZaW%2FmgtmxnJ8V3oAnApQwNS5zpcAAAAaZmNUTAAAAAEAAAAQAAAAEAAAAAAAAAAAAB4D6AIB52fclgAAACpmZEFUAAAAAjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9WF%2Bu8QAAABpmY1RMAAAAAwAAABAAAAAQAAAAAAAAAAAAHgPoAgEK8Q9%2FAAAAFmZkQVQAAAAEOI1jYBgFo2AUjAIIAAAEEAAB0xIn4wAAABpmY1RMAAAABQAAABAAAAAQAAAAAAAAAAAAHgPoAgHnO30FAAAAQGZkQVQAAAAGOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVfozYcAAAABpmY1RMAAAABwAAABAAAAAQAAAAAAAAAAAAHgPoAgEKra7sAAAAFmZkQVQAAAAIOI1jYBgFo2AUjAIIAAAEEAABM9s3hAAAABpmY1RMAAAACQAAABAAAAAQAAAAAAAAAAAAHgPoAgHn3p%2BwAAAAKmZkQVQAAAAKOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F1BhPl6AAAAGmZjVEwAAAALAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQpITFkAAAAWZmRBVAAAAAw4jWNgGAWjYBSMAggAAAQQAAHaszpmAAAAGmZjVEwAAAANAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeeCPiMAAABAZmRBVAAAAA44jWNgGJ5gpxrDf2LEcIL%2FpzAVYxPDavP%2FUwz%2FpW79%2F%2F%2F%2FFMP%2FnWoQjC5GOxcgu4QYsVEwCmAAAOE0KxUmBL0KAAAAGmZjVEwAAAAPAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQoU7coAAAAWZmRBVAAAABA4jWNgGAWjYBSMAggAAAQQAAEpOBELAAAAGmZjVEwAAAARAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeYVWtoAAAAqZmRBVAAAABI4jWNgGAVYQXNz839ixHBq3qnG8B9ZAzYx2rlgFIwCcgAA8psX%2FWvpAecAAAAaZmNUTAAAABMAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC4OJMwAAABZmZEFUAAAAFDiNY2AYBaNgFIwCCAAABBAAAcBQHOkAAAAaZmNUTAAAABUAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5kn7SQAAAEBmZEFUAAAAFjiNY2AYnmCnGsN%2FYsRwgv%2BnMBVjE8Nq8%2F9TDP%2Blbv3%2F%2F%2F8Uw%2F%2BdahCMLkY7FyC7hBixUTAKYAAA4TQrFc%2BcEoQAAAAaZmNUTAAAABcAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC98ooAAAABZmZEFUAAAAGDiNY2AYBaNgFIwCCAAABBAAASCZDI4AAAAaZmNUTAAAABkAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5qwZ%2FAAAACpmZEFUAAAAGjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9cjJWbAAAABpmY1RMAAAAGwAAABAAAAAQAAAAAAAAAAAAHgPoAgELOsoVAAAAFmZkQVQAAAAcOI1jYBgFo2AUjAIIAAAEEAAByfEBbAAAABpmY1RMAAAAHQAAABAAAAAQAAAAAAAAAAAAHgPoAgHm8LhvAAAAQGZkQVQAAAAeOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVlxR3%2FgAAABpmY1RMAAAAHwAAABAAAAAQAAAAAAAAAAAAHgPoAgELZmuGAAAAFmZkQVQAAAAgOI1jYBgFo2AUjAIIAAAEEAABHP5cFQAAABpmY1RMAAAAIQAAABAAAAAQAAAAAAAAAAAAHgPoAgHlgtAOAAAAKmZkQVQAAAAiOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F0%2FMvDdAAAAAElFTkSuQmCC"/>
-
- <script type="application/javascript"><![CDATA[
- var buttonClicked = false;
- function robotButton()
- {
- var button = document.getElementById('errorTryAgain');
- if (buttonClicked) {
- button.style.visibility = "hidden";
- } else {
- var newLabel = button.getAttribute("label2");
- button.textContent = newLabel;
- buttonClicked = true;
- }
- }
- ]]></script>
-
- <style type="text/css"><![CDATA[
- #errorPageContainer {
- background-image: none;
- }
-
- #errorPageContainer:before {
- content: url('chrome://browser/content/aboutRobots-icon.png');
- position: absolute;
- }
-
- body[dir=rtl] #icon,
- body[dir=rtl] #errorPageContainer:before {
- transform: scaleX(-1);
- }
- ]]></style>
- </head>
-
- <body dir="&locale.dir;">
-
- <!-- PAGE CONTAINER (for styling purposes only) -->
- <div id="errorPageContainer">
-
- <!-- Error Title -->
- <div id="errorTitle">
- <h1 id="errorTitleText">&robots.errorTitleText;</h1>
- </div>
-
- <!-- LONG CONTENT (the section most likely to require scrolling) -->
- <div id="errorLongContent">
-
- <!-- Short Description -->
- <div id="errorShortDesc">
- <p id="errorShortDescText">&robots.errorShortDescText;</p>
- </div>
-
- <!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
- <div id="errorLongDesc">
- <ul>
- <li>&robots.errorLongDesc1;</li>
- <li>&robots.errorLongDesc2;</li>
- <li>&robots.errorLongDesc3;</li>
- <li>&robots.errorLongDesc4;</li>
- </ul>
- </div>
-
- <!-- Short Description -->
- <div id="errorTrailerDesc">
- <p id="errorTrailerDescText">&robots.errorTrailerDescText;</p>
- </div>
-
- </div>
-
- <!-- Button -->
- <button id="errorTryAgain"
- label2="&robots.dontpress;"
- onclick="robotButton();">&retry.label;</button>
-
- <img src="chrome://browser/content/aboutRobots-widget-left.png"
- style="position: absolute; bottom: -12px; left: -10px;"/>
- <img src="chrome://browser/content/aboutRobots-widget-left.png"
- style="position: absolute; bottom: -12px; right: -10px; transform: scaleX(-1);"/>
- </div>
-
- </body>
-</html>
diff --git a/application/basilisk/base/content/aboutaccounts/aboutaccounts.css b/application/basilisk/base/content/aboutaccounts/aboutaccounts.css
deleted file mode 100644
index a2c5cb8f0..000000000
--- a/application/basilisk/base/content/aboutaccounts/aboutaccounts.css
+++ /dev/null
@@ -1,24 +0,0 @@
-html, body {
- height: 100%;
-}
-
-#remote {
- width: 100%;
- height: 100%;
- border: 0;
- display: none;
-}
-
-#networkError, #manage, #intro, #stage, #configError {
- display: none;
-}
-
-#oldsync {
- background: none;
- border: 0;
- color: #0095dd;
-}
-
-#oldsync:focus {
- outline: 1px dotted #0095dd;
-}
diff --git a/application/basilisk/base/content/aboutaccounts/aboutaccounts.js b/application/basilisk/base/content/aboutaccounts/aboutaccounts.js
deleted file mode 100644
index a05c1ea75..000000000
--- a/application/basilisk/base/content/aboutaccounts/aboutaccounts.js
+++ /dev/null
@@ -1,543 +0,0 @@
-/* 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";
-
-var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/FxAccounts.jsm");
-
-var fxAccountsCommon = {};
-Cu.import("resource://gre/modules/FxAccountsCommon.js", fxAccountsCommon);
-
-// for master-password utilities
-Cu.import("resource://services-sync/util.js");
-
-const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
-const PREF_SYNC_SHOW_CUSTOMIZATION = "services.sync-setup.ui.showCustomizationDialog";
-
-const ACTION_URL_PARAM = "action";
-
-const OBSERVER_TOPICS = [
- fxAccountsCommon.ONVERIFIED_NOTIFICATION,
- fxAccountsCommon.ONLOGOUT_NOTIFICATION,
-];
-
-function log(msg) {
- // dump("FXA: " + msg + "\n");
-}
-
-function error(msg) {
- console.log("Firefox Account Error: " + msg + "\n");
-}
-
-function getPreviousAccountNameHash() {
- try {
- return Services.prefs.getComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString).data;
- } catch (_) {
- return "";
- }
-}
-
-function setPreviousAccountNameHash(acctName) {
- let string = Cc["@mozilla.org/supports-string;1"]
- .createInstance(Ci.nsISupportsString);
- string.data = sha256(acctName);
- Services.prefs.setComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString, string);
-}
-
-function needRelinkWarning(acctName) {
- let prevAcctHash = getPreviousAccountNameHash();
- return prevAcctHash && prevAcctHash != sha256(acctName);
-}
-
-// Given a string, returns the SHA265 hash in base64
-function sha256(str) {
- let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
- .createInstance(Ci.nsIScriptableUnicodeConverter);
- converter.charset = "UTF-8";
- // Data is an array of bytes.
- let data = converter.convertToByteArray(str, {});
- let hasher = Cc["@mozilla.org/security/hash;1"]
- .createInstance(Ci.nsICryptoHash);
- hasher.init(hasher.SHA256);
- hasher.update(data, data.length);
-
- return hasher.finish(true);
-}
-
-function promptForRelink(acctName) {
- let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
- let continueLabel = sb.GetStringFromName("continue.label");
- let title = sb.GetStringFromName("relinkVerify.title");
- let description = sb.formatStringFromName("relinkVerify.description",
- [acctName], 1);
- let body = sb.GetStringFromName("relinkVerify.heading") +
- "\n\n" + description;
- let ps = Services.prompt;
- let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
- (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
- ps.BUTTON_POS_1_DEFAULT;
- let pressed = Services.prompt.confirmEx(window, title, body, buttonFlags,
- continueLabel, null, null, null,
- {});
- return pressed == 0; // 0 is the "continue" button
-}
-
-// If the last fxa account used for sync isn't this account, we display
-// a modal dialog checking they really really want to do this...
-// (This is sync-specific, so ideally would be in sync's identity module,
-// but it's a little more seamless to do here, and sync is currently the
-// only fxa consumer, so...
-function shouldAllowRelink(acctName) {
- return !needRelinkWarning(acctName) || promptForRelink(acctName);
-}
-
-function updateDisplayedEmail(user) {
- let emailDiv = document.getElementById("email");
- if (emailDiv && user) {
- emailDiv.textContent = user.email;
- }
-}
-
-var wrapper = {
- iframe: null,
-
- init: function (url, urlParams) {
- // If a master-password is enabled, we want to encourage the user to
- // unlock it. Things still work if not, but the user will probably need
- // to re-auth next startup (in which case we will get here again and
- // re-prompt)
- Utils.ensureMPUnlocked();
-
- let iframe = document.getElementById("remote");
- this.iframe = iframe;
- this.iframe.QueryInterface(Ci.nsIFrameLoaderOwner);
- let docShell = this.iframe.frameLoader.docShell;
- docShell.QueryInterface(Ci.nsIWebProgress);
- docShell.addProgressListener(this.iframeListener, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
- iframe.addEventListener("load", this);
-
- // Ideally we'd just merge urlParams with new URL(url).searchParams, but our
- // URLSearchParams implementation doesn't support iteration (bug 1085284).
- let urlParamStr = urlParams.toString();
- if (urlParamStr) {
- url += (url.includes("?") ? "&" : "?") + urlParamStr;
- }
- this.url = url;
- // Set the iframe's location with loadURI/LOAD_FLAGS_REPLACE_HISTORY to
- // avoid having a new history entry being added. REPLACE_HISTORY is used
- // to replace the current entry, which is `about:blank`.
- let webNav = iframe.frameLoader.docShell.QueryInterface(Ci.nsIWebNavigation);
- webNav.loadURI(url, Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY, null, null, null);
- },
-
- retry: function () {
- let webNav = this.iframe.frameLoader.docShell.QueryInterface(Ci.nsIWebNavigation);
- webNav.loadURI(this.url, Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY, null, null, null);
- },
-
- iframeListener: {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
- Ci.nsISupportsWeakReference,
- Ci.nsISupports]),
-
- onStateChange: function(aWebProgress, aRequest, aState, aStatus) {
- let failure = false;
-
- // Captive portals sometimes redirect users
- if ((aState & Ci.nsIWebProgressListener.STATE_REDIRECTING)) {
- failure = true;
- } else if ((aState & Ci.nsIWebProgressListener.STATE_STOP)) {
- if (aRequest instanceof Ci.nsIHttpChannel) {
- try {
- failure = aRequest.responseStatus != 200;
- } catch (e) {
- failure = aStatus != Components.results.NS_OK;
- }
- }
- }
-
- // Calling cancel() will raise some OnStateChange notifications by itself,
- // so avoid doing that more than once
- if (failure && aStatus != Components.results.NS_BINDING_ABORTED) {
- aRequest.cancel(Components.results.NS_BINDING_ABORTED);
- setErrorPage("networkError");
- }
- },
-
- onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
- if (aRequest && aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) {
- aRequest.cancel(Components.results.NS_BINDING_ABORTED);
- setErrorPage("networkError");
- }
- },
-
- onProgressChange: function() {},
- onStatusChange: function() {},
- onSecurityChange: function() {},
- },
-
- handleEvent: function (evt) {
- switch (evt.type) {
- case "load":
- this.iframe.contentWindow.addEventListener("FirefoxAccountsCommand", this);
- this.iframe.removeEventListener("load", this);
- break;
- case "FirefoxAccountsCommand":
- this.handleRemoteCommand(evt);
- break;
- }
- },
-
- /**
- * onLogin handler receives user credentials from the jelly after a
- * sucessful login and stores it in the fxaccounts service
- *
- * @param accountData the user's account data and credentials
- */
- onLogin: function (accountData) {
- log("Received: 'login'. Data:" + JSON.stringify(accountData));
-
- if (accountData.customizeSync) {
- Services.prefs.setBoolPref(PREF_SYNC_SHOW_CUSTOMIZATION, true);
- }
- delete accountData.customizeSync;
- // sessionTokenContext is erroneously sent by the content server.
- // https://github.com/mozilla/fxa-content-server/issues/2766
- // To avoid having the FxA storage manager not knowing what to do with
- // it we delete it here.
- delete accountData.sessionTokenContext;
-
- // We need to confirm a relink - see shouldAllowRelink for more
- let newAccountEmail = accountData.email;
- // The hosted code may have already checked for the relink situation
- // by sending the can_link_account command. If it did, then
- // it will indicate we don't need to ask twice.
- if (!accountData.verifiedCanLinkAccount && !shouldAllowRelink(newAccountEmail)) {
- // we need to tell the page we successfully received the message, but
- // then bail without telling fxAccounts
- this.injectData("message", { status: "login" });
- // after a successful login we return to preferences
- openPrefs();
- return;
- }
- delete accountData.verifiedCanLinkAccount;
-
- // Remember who it was so we can log out next time.
- setPreviousAccountNameHash(newAccountEmail);
-
- // A sync-specific hack - we want to ensure sync has been initialized
- // before we set the signed-in user.
- let xps = Cc["@mozilla.org/weave/service;1"]
- .getService(Ci.nsISupports)
- .wrappedJSObject;
- xps.whenLoaded().then(() => {
- updateDisplayedEmail(accountData);
- return fxAccounts.setSignedInUser(accountData);
- }).then(() => {
- // If the user data is verified, we want it to immediately look like
- // they are signed in without waiting for messages to bounce around.
- if (accountData.verified) {
- openPrefs();
- }
- this.injectData("message", { status: "login" });
- // until we sort out a better UX, just leave the jelly page in place.
- // If the account email is not yet verified, it will tell the user to
- // go check their email, but then it will *not* change state after
- // the verification completes (the browser will begin syncing, but
- // won't notify the user). If the email has already been verified,
- // the jelly will say "Welcome! You are successfully signed in as
- // EMAIL", but it won't then say "syncing started".
- }, (err) => this.injectData("message", { status: "error", error: err })
- );
- },
-
- onCanLinkAccount: function(accountData) {
- // We need to confirm a relink - see shouldAllowRelink for more
- let ok = shouldAllowRelink(accountData.email);
- this.injectData("message", { status: "can_link_account", data: { ok: ok } });
- },
-
- /**
- * onSignOut handler erases the current user's session from the fxaccounts service
- */
- onSignOut: function () {
- log("Received: 'sign_out'.");
-
- fxAccounts.signOut().then(
- () => this.injectData("message", { status: "sign_out" }),
- (err) => this.injectData("message", { status: "error", error: err })
- );
- },
-
- handleRemoteCommand: function (evt) {
- log('command: ' + evt.detail.command);
- let data = evt.detail.data;
-
- switch (evt.detail.command) {
- case "login":
- this.onLogin(data);
- break;
- case "can_link_account":
- this.onCanLinkAccount(data);
- break;
- case "sign_out":
- this.onSignOut(data);
- break;
- default:
- log("Unexpected remote command received: " + evt.detail.command + ". Ignoring command.");
- break;
- }
- },
-
- injectData: function (type, content) {
- return fxAccounts.promiseAccountsSignUpURI().then(authUrl => {
- let data = {
- type: type,
- content: content
- };
- this.iframe.contentWindow.postMessage(data, authUrl);
- })
- .catch(e => {
- console.log("Failed to inject data", e);
- setErrorPage("configError");
- });
- },
-};
-
-
-// Button onclick handlers
-function handleOldSync() {
- let chromeWin = window
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem)
- .rootTreeItem
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow)
- .QueryInterface(Ci.nsIDOMChromeWindow);
- let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "old-sync";
- chromeWin.switchToTabHavingURI(url, true);
-}
-
-function getStarted() {
- show("remote");
-}
-
-function retry() {
- show("remote");
- wrapper.retry();
-}
-
-function openPrefs() {
- // Bug 1199303 calls for this tab to always be replaced with Preferences
- // rather than it opening in a different tab.
- window.location = "about:preferences#sync";
-}
-
-function init() {
- fxAccounts.getSignedInUser().then(user => {
- // tests in particular might cause the window to start closing before
- // getSignedInUser has returned.
- if (window.closed) {
- return Promise.resolve();
- }
-
- updateDisplayedEmail(user);
-
- // Ideally we'd use new URL(document.URL).searchParams, but for about: URIs,
- // searchParams is empty.
- let urlParams = new URLSearchParams(document.URL.split("?")[1] || "");
- let action = urlParams.get(ACTION_URL_PARAM);
- urlParams.delete(ACTION_URL_PARAM);
-
- switch (action) {
- case "signin":
- if (user) {
- // asking to sign-in when already signed in just shows manage.
- show("stage", "manage");
- } else {
- return fxAccounts.promiseAccountsSignInURI().then(url => {
- show("remote");
- wrapper.init(url, urlParams);
- });
- }
- break;
- case "signup":
- if (user) {
- // asking to sign-up when already signed in just shows manage.
- show("stage", "manage");
- } else {
- return fxAccounts.promiseAccountsSignUpURI().then(url => {
- show("remote");
- wrapper.init(url, urlParams);
- });
- }
- break;
- case "reauth":
- // ideally we would only show this when we know the user is in a
- // "must reauthenticate" state - but we don't.
- // As the email address will be included in the URL returned from
- // promiseAccountsForceSigninURI, just always show it.
- return fxAccounts.promiseAccountsForceSigninURI().then(url => {
- show("remote");
- wrapper.init(url, urlParams);
- });
- default:
- // No action specified.
- if (user) {
- show("stage", "manage");
- } else {
- // Attempt a migration if enabled or show the introductory page
- // otherwise.
- return migrateToDevEdition(urlParams).then(migrated => {
- if (!migrated) {
- show("stage", "intro");
- // load the remote frame in the background
- return fxAccounts.promiseAccountsSignUpURI().then(uri =>
- wrapper.init(uri, urlParams));
- }
- return Promise.resolve();
- });
- }
- break;
- }
- return Promise.resolve();
- }).catch(err => {
- console.log("Configuration or sign in error", err);
- setErrorPage("configError");
- });
-}
-
-function setErrorPage(errorType) {
- show("stage", errorType);
-}
-
-// Causes the "top-level" element with |id| to be shown - all other top-level
-// elements are hidden. Optionally, ensures that only 1 "second-level" element
-// inside the top-level one is shown.
-function show(id, childId) {
- // top-level items are either <div> or <iframe>
- let allTop = document.querySelectorAll("body > div, iframe");
- for (let elt of allTop) {
- if (elt.getAttribute("id") == id) {
- elt.style.display = 'block';
- } else {
- elt.style.display = 'none';
- }
- }
- if (childId) {
- // child items are all <div>
- let allSecond = document.querySelectorAll("#" + id + " > div");
- for (let elt of allSecond) {
- if (elt.getAttribute("id") == childId) {
- elt.style.display = 'block';
- } else {
- elt.style.display = 'none';
- }
- }
- }
-}
-
-// Migrate sync data from the default profile to the dev-edition profile.
-// Returns a promise of a true value if migration succeeded, or false if it
-// failed.
-function migrateToDevEdition(urlParams) {
- let defaultProfilePath;
- try {
- defaultProfilePath = window.getDefaultProfilePath();
- } catch (e) {} // no default profile.
- let migrateSyncCreds = false;
- if (defaultProfilePath) {
- try {
- migrateSyncCreds = Services.prefs.getBoolPref("identity.fxaccounts.migrateToDevEdition");
- } catch (e) {}
- }
-
- if (!migrateSyncCreds) {
- return Promise.resolve(false);
- }
-
- Cu.import("resource://gre/modules/osfile.jsm");
- let fxAccountsStorage = OS.Path.join(defaultProfilePath, fxAccountsCommon.DEFAULT_STORAGE_FILENAME);
- return OS.File.read(fxAccountsStorage, { encoding: "utf-8" }).then(text => {
- let accountData = JSON.parse(text).accountData;
- updateDisplayedEmail(accountData);
- return fxAccounts.setSignedInUser(accountData);
- }).then(() => {
- return fxAccounts.promiseAccountsForceSigninURI().then(url => {
- show("remote");
- wrapper.init(url, urlParams);
- });
- }).then(null, error => {
- log("Failed to migrate FX Account: " + error);
- show("stage", "intro");
- // load the remote frame in the background
- fxAccounts.promiseAccountsSignUpURI().then(uri => {
- wrapper.init(uri, urlParams)
- }).catch(e => {
- console.log("Failed to load signup page", e);
- setErrorPage("configError");
- });
- }).then(() => {
- // Reset the pref after migration.
- Services.prefs.setBoolPref("identity.fxaccounts.migrateToDevEdition", false);
- return true;
- }).then(null, err => {
- Cu.reportError("Failed to reset the migrateToDevEdition pref: " + err);
- return false;
- });
-}
-
-// Helper function that returns the path of the default profile on disk. Will be
-// overridden in tests.
-function getDefaultProfilePath() {
- let defaultProfile = Cc["@mozilla.org/toolkit/profile-service;1"]
- .getService(Ci.nsIToolkitProfileService)
- .defaultProfile;
- return defaultProfile.rootDir.path;
-}
-
-document.addEventListener("DOMContentLoaded", function onload() {
- document.removeEventListener("DOMContentLoaded", onload, true);
- init();
- var buttonGetStarted = document.getElementById('buttonGetStarted');
- buttonGetStarted.addEventListener('click', getStarted);
-
- var buttonRetry = document.getElementById('buttonRetry');
- buttonRetry.addEventListener('click', retry);
-
- var oldsync = document.getElementById('oldsync');
- oldsync.addEventListener('click', handleOldSync);
-
- var buttonOpenPrefs = document.getElementById('buttonOpenPrefs')
- buttonOpenPrefs.addEventListener('click', openPrefs);
-}, true);
-
-function initObservers() {
- function observe(subject, topic, data) {
- log("about:accounts observed " + topic);
- if (topic == fxAccountsCommon.ONLOGOUT_NOTIFICATION) {
- // All about:account windows get changed to action=signin on logout.
- window.location = "about:accounts?action=signin";
- return;
- }
-
- // must be onverified - we want to open preferences.
- openPrefs();
- }
-
- for (let topic of OBSERVER_TOPICS) {
- Services.obs.addObserver(observe, topic, false);
- }
- window.addEventListener("unload", function(event) {
- log("about:accounts unloading")
- for (let topic of OBSERVER_TOPICS) {
- Services.obs.removeObserver(observe, topic);
- }
- });
-}
-initObservers();
diff --git a/application/basilisk/base/content/aboutaccounts/aboutaccounts.xhtml b/application/basilisk/base/content/aboutaccounts/aboutaccounts.xhtml
deleted file mode 100644
index 475f0e86f..000000000
--- a/application/basilisk/base/content/aboutaccounts/aboutaccounts.xhtml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?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 [
- <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
- %htmlDTD;
- <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
- %brandDTD;
- <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
- <!ENTITY % aboutAccountsDTD SYSTEM "chrome://browser/locale/aboutAccounts.dtd">
- %aboutAccountsDTD;
- <!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
- %syncBrandDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml" dir="&locale.dir;">
- <head>
- <title>&syncBrand.fullName.label;</title>
- <meta name="viewport" content="width=device-width"/>
-
-
- <link rel="icon" type="image/png" id="favicon"
- href="chrome://branding/content/icon32.png"/>
- <link rel="stylesheet"
- href="chrome://browser/content/aboutaccounts/normalize.css"
- type="text/css" />
- <link rel="stylesheet"
- href="chrome://browser/content/aboutaccounts/main.css"
- type="text/css" />
- <link rel="stylesheet"
- href="chrome://browser/content/aboutaccounts/aboutaccounts.css"
- type="text/css" />
- </head>
- <body>
- <div id="stage">
-
- <div id="manage">
- <header>
- <h1>&aboutAccounts.connected;</h1>
- <div id="email"></div>
- </header>
-
- <section>
- <div class="graphic graphic-sync-intro"> </div>
-
- <div class="button-row">
- <button id="buttonOpenPrefs" class="button" href="#" tabindex="0">&aboutAccountsConfig.syncPreferences.label;</button>
- </div>
- </section>
- </div>
-
- <div id="intro">
- <header>
- <h1>&aboutAccounts.welcome;</h1>
- </header>
-
- <section>
- <div class="graphic graphic-sync-intro"> </div>
-
- <div class="description">&aboutAccountsConfig.description;</div>
-
- <div class="button-row">
- <button id="buttonGetStarted" class="button" tabindex="1">&aboutAccountsConfig.startButton.label;</button>
- </div>
-
- <div class="links">
- <button id="oldsync" tabindex="2">&aboutAccountsConfig.useOldSync.label;</button>
- </div>
- </section>
- </div>
-
- <div id="networkError">
- <header>
- <h1>&aboutAccounts.noConnection.title;</h1>
- </header>
-
- <section>
- <div class="graphic graphic-sync-intro"> </div>
-
- <div class="description">&aboutAccounts.noConnection.description;</div>
-
- <div class="button-row">
- <button id="buttonRetry" class="button" tabindex="3">&aboutAccounts.noConnection.retry;</button>
- </div>
- </section>
- </div>
-
- <div id="configError">
- <header>
- <h1>&aboutAccounts.badConfig.title;</h1>
- </header>
-
- <section>
- <div class="graphic graphic-sync-intro"> </div>
-
- <div class="description">&aboutAccounts.badConfig.description;</div>
-
- </section>
- </div>
-
- </div>
-
- <iframe mozframetype="content" id="remote" />
-
- <script type="application/javascript;version=1.8"
- src="chrome://browser/content/utilityOverlay.js"/>
- <script type="text/javascript;version=1.8"
- src="chrome://browser/content/aboutaccounts/aboutaccounts.js" />
- </body>
-</html>
diff --git a/application/basilisk/base/content/aboutaccounts/images/fox.png b/application/basilisk/base/content/aboutaccounts/images/fox.png
deleted file mode 100644
index 83af78d6c..000000000
--- a/application/basilisk/base/content/aboutaccounts/images/fox.png
+++ /dev/null
Binary files differ
diff --git a/application/basilisk/base/content/aboutaccounts/images/graphic_sync_intro.png b/application/basilisk/base/content/aboutaccounts/images/graphic_sync_intro.png
deleted file mode 100644
index ff5f482f0..000000000
--- a/application/basilisk/base/content/aboutaccounts/images/graphic_sync_intro.png
+++ /dev/null
Binary files differ
diff --git a/application/basilisk/base/content/aboutaccounts/images/graphic_sync_intro@2x.png b/application/basilisk/base/content/aboutaccounts/images/graphic_sync_intro@2x.png
deleted file mode 100644
index 89fda0681..000000000
--- a/application/basilisk/base/content/aboutaccounts/images/graphic_sync_intro@2x.png
+++ /dev/null
Binary files differ
diff --git a/application/basilisk/base/content/aboutaccounts/main.css b/application/basilisk/base/content/aboutaccounts/main.css
deleted file mode 100644
index 8f4c3b34e..000000000
--- a/application/basilisk/base/content/aboutaccounts/main.css
+++ /dev/null
@@ -1,166 +0,0 @@
-*,
-*:before,
-*:after {
- box-sizing: border-box;
-}
-
-html {
- background-color: #F2F2F2;
- height: 100%;
-}
-
-body {
- color: #424f59;
- font: message-box;
- font-size: 14px;
- height: 100%;
-}
-
-a {
- color: #0095dd;
- cursor: pointer; /* Use the correct cursor for anchors without an href */
-}
-
-a:active {
- outline: none;
-}
-
-a:focus {
- outline: 1px dotted #0095dd;
-}
-
-
-a.no-underline {
- text-decoration: none;
-}
-
-#stage {
- background:#fff;
- border-radius: 5px;
- box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.25);
- margin: 0 auto;
- min-height: 300px;
- padding: 60px 40px 40px 40px;
- position: relative;
- text-align: center;
- top: 80px;
- width: 420px;
-}
-
-header h1
-{
- font-size: 24px;
- font-weight: 200;
- line-height: 1em;
-}
-
-#intro header h1 {
- margin: 0 0 32px 0;
-}
-
-#manage header h1 {
- margin: 0 0 12px 0;
-}
-
-#manage header #email {
- margin-bottom: 23px;
- color: rgb(138, 155, 168);
- font-size: 19px;
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
-}
-
-.description {
- font-size: 18px;
-}
-
-.button-row {
- margin-top: 45px;
- margin-bottom:20px;
-}
-
-.button-row button,
-.button-row a.button {
- background: #0095dd;
- border: none;
- border-radius: 5px;
- color: #FFFFFF;
- cursor: pointer;
- font-size: 24px;
- padding: 15px 0;
- transition-duration: 150ms;
- transition-property: background-color;
- width: 100%;
-}
-
-.button-row a.button {
- display: inline-block;
- text-decoration: none;
-}
-
-.button-row a.button:active,
-.button-row a.button:hover,
-.button-row a.button:focus,
-.button-row button:active,
-.button-row button:hover,
-.button-row button:focus {
- background: #08c;
-}
-
-
-.graphic-sync-intro {
- background-image: url(images/graphic_sync_intro.png);
- background-repeat: no-repeat;
- background-size: 150px 195px;
- height: 195px;
- margin: 0 auto;
- overflow: hidden;
- text-indent: 100%;
- white-space: nowrap;
- width: 150px;
-}
-
-.description,
-.button-row {
- margin-top: 30px;
-}
-
-.links {
- margin: 20px 0;
-}
-
-@media only screen and (max-width: 500px) {
- html {
- background: #fff;
- }
-
- #stage {
- box-shadow: none;
- margin: 30px auto 0 auto;
- min-height: none;
- min-width: 320px;
- padding: 0 10px;
- width: 100%;
- }
-
- .button-row {
- margin-top: 20px;
- }
-
- .button-row button,
- .button-row a.button {
- padding: 10px 0;
- }
-
-}
-
-/* Retina */
-@media
-only screen and (min-device-pixel-ratio: 2),
-only screen and ( min-resolution: 192dpi),
-only screen and ( min-resolution: 2dppx) {
- .graphic-sync-intro {
- background-image: url(images/graphic_sync_intro@2x.png);
- }
-}
diff --git a/application/basilisk/base/content/aboutaccounts/normalize.css b/application/basilisk/base/content/aboutaccounts/normalize.css
deleted file mode 100644
index c02ab25de..000000000
--- a/application/basilisk/base/content/aboutaccounts/normalize.css
+++ /dev/null
@@ -1,402 +0,0 @@
-/*! normalize.css v2.1.3 | MIT License | git.io/normalize */
-
-/* ==========================================================================
- HTML5 display definitions
- ========================================================================== */
-
-/**
- * Correct `block` display not defined in IE 8/9.
- */
-
-article,
-aside,
-details,
-figcaption,
-figure,
-footer,
-header,
-hgroup,
-main,
-nav,
-section,
-summary {
- display: block;
-}
-
-/**
- * Correct `inline-block` display not defined in IE 8/9.
- */
-
-audio,
-canvas,
-video {
- display: inline-block;
-}
-
-/**
- * Prevent modern browsers from displaying `audio` without controls.
- * Remove excess height in iOS 5 devices.
- */
-
-audio:not([controls]) {
- display: none;
- height: 0;
-}
-
-/**
- * Address `[hidden]` styling not present in IE 8/9.
- * Hide the `template` element in IE, Safari, and Firefox < 22.
- */
-
-[hidden],
-template {
- display: none;
-}
-
-/* ==========================================================================
- Base
- ========================================================================== */
-
-/**
- * 1. Set default font family to sans-serif.
- * 2. Prevent iOS text size adjust after orientation change, without disabling
- * user zoom.
- */
-
-html {
- font-family: sans-serif; /* 1 */
- -ms-text-size-adjust: 100%; /* 2 */
- -webkit-text-size-adjust: 100%; /* 2 */
-}
-
-/**
- * Remove default margin.
- */
-
-body {
- margin: 0;
-}
-
-/* ==========================================================================
- Links
- ========================================================================== */
-
-/**
- * Remove the gray background color from active links in IE 10.
- */
-
-a {
- background: transparent;
-}
-
-/**
- * Address `outline` inconsistency between Chrome and other browsers.
- */
-
-a:focus {
- outline: thin dotted;
-}
-
-/**
- * Improve readability when focused and also mouse hovered in all browsers.
- */
-
-a:active,
-a:hover {
- outline: 0;
-}
-
-/* ==========================================================================
- Typography
- ========================================================================== */
-
-/**
- * Address variable `h1` font-size and margin within `section` and `article`
- * contexts in Firefox 4+, Safari 5, and Chrome.
- */
-
-h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-
-/**
- * Address styling not present in IE 8/9, Safari 5, and Chrome.
- */
-
-abbr[title] {
- border-bottom: 1px dotted;
-}
-
-/**
- * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
- */
-
-b,
-strong {
- font-weight: bold;
-}
-
-/**
- * Address styling not present in Safari 5 and Chrome.
- */
-
-dfn {
- font-style: italic;
-}
-
-/**
- * Address differences between Firefox and other browsers.
- */
-
-hr {
- box-sizing: content-box;
- height: 0;
-}
-
-/**
- * Address styling not present in IE 8/9.
- */
-
-mark {
- background: #ff0;
- color: #000;
-}
-
-/**
- * Correct font family set oddly in Safari 5 and Chrome.
- */
-
-code,
-kbd,
-pre,
-samp {
- font-family: monospace, serif;
- font-size: 1em;
-}
-
-/**
- * Improve readability of pre-formatted text in all browsers.
- */
-
-pre {
- white-space: pre-wrap;
-}
-
-/**
- * Set consistent quote types.
- */
-
-q {
- quotes: "\201C" "\201D" "\2018" "\2019";
-}
-
-/**
- * Address inconsistent and variable font size in all browsers.
- */
-
-small {
- font-size: 80%;
-}
-
-/**
- * Prevent `sub` and `sup` affecting `line-height` in all browsers.
- */
-
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-
-sup {
- top: -0.5em;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-/* ==========================================================================
- Embedded content
- ========================================================================== */
-
-/**
- * Remove border when inside `a` element in IE 8/9.
- */
-
-img {
- border: 0;
-}
-
-/**
- * Correct overflow displayed oddly in IE 9.
- */
-
-svg:not(:root) {
- overflow: hidden;
-}
-
-/* ==========================================================================
- Figures
- ========================================================================== */
-
-/**
- * Address margin not present in IE 8/9 and Safari 5.
- */
-
-figure {
- margin: 0;
-}
-
-/* ==========================================================================
- Forms
- ========================================================================== */
-
-/**
- * Define consistent border, margin, and padding.
- */
-
-fieldset {
- border: 1px solid #c0c0c0;
- margin: 0 2px;
- padding: 0.35em 0.625em 0.75em;
-}
-
-/**
- * 1. Correct `color` not being inherited in IE 8/9.
- * 2. Remove padding so people aren't caught out if they zero out fieldsets.
- */
-
-legend {
- border: 0; /* 1 */
- padding: 0; /* 2 */
-}
-
-/**
- * 1. Correct font family not being inherited in all browsers.
- * 2. Correct font size not being inherited in all browsers.
- * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
- */
-
-button,
-input,
-select,
-textarea {
- font-family: inherit; /* 1 */
- font-size: 100%; /* 2 */
- margin: 0; /* 3 */
-}
-
-/**
- * Address Firefox 4+ setting `line-height` on `input` using `!important` in
- * the UA stylesheet.
- */
-
-button,
-input {
- line-height: normal;
-}
-
-/**
- * Address inconsistent `text-transform` inheritance for `button` and `select`.
- * All other form control elements do not inherit `text-transform` values.
- * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
- * Correct `select` style inheritance in Firefox 4+ and Opera.
- */
-
-button,
-select {
- text-transform: none;
-}
-
-/**
- * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
- * and `video` controls.
- * 2. Correct inability to style clickable `input` types in iOS.
- * 3. Improve usability and consistency of cursor style between image-type
- * `input` and others.
- */
-
-button,
-html input[type="button"], /* 1 */
-input[type="reset"],
-input[type="submit"] {
- -webkit-appearance: button; /* 2 */
- cursor: pointer; /* 3 */
-}
-
-/**
- * Re-set default cursor for disabled elements.
- */
-
-button[disabled],
-html input[disabled] {
- cursor: default;
-}
-
-/**
- * 1. Address box sizing set to `content-box` in IE 8/9/10.
- * 2. Remove excess padding in IE 8/9/10.
- */
-
-input[type="checkbox"],
-input[type="radio"] {
- box-sizing: border-box; /* 1 */
- padding: 0; /* 2 */
-}
-
-/**
- * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
- * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome.
- */
-
-input[type="search"] {
- -webkit-appearance: textfield; /* 1 */
- box-sizing: content-box; /* 2 */
-}
-
-/**
- * Remove inner padding and search cancel button in Safari 5 and Chrome
- * on OS X.
- */
-
-input[type="search"]::-webkit-search-cancel-button,
-input[type="search"]::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-
-/**
- * Remove inner padding and border in Firefox 4+.
- */
-
-button::-moz-focus-inner,
-input::-moz-focus-inner {
- border: 0;
- padding: 0;
-}
-
-/**
- * 1. Remove default vertical scrollbar in IE 8/9.
- * 2. Improve readability and alignment in all browsers.
- */
-
-textarea {
- overflow: auto; /* 1 */
- vertical-align: top; /* 2 */
-}
-
-/* ==========================================================================
- Tables
- ========================================================================== */
-
-/**
- * Remove most spacing between table cells.
- */
-
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
diff --git a/application/basilisk/base/content/abouthome/aboutHome.css b/application/basilisk/base/content/abouthome/aboutHome.css
index bc3f9882c..86f74727f 100644
--- a/application/basilisk/base/content/abouthome/aboutHome.css
+++ b/application/basilisk/base/content/abouthome/aboutHome.css
@@ -283,9 +283,11 @@ body[narrow] #restorePreviousSession {
content: url("chrome://browser/content/abouthome/addons.png");
}
+%ifdef MOZ_SERVICES_SYNC
#sync::before {
content: url("chrome://browser/content/abouthome/sync.png");
}
+%endif
#settings::before {
content: url("chrome://browser/content/abouthome/settings.png");
@@ -369,9 +371,11 @@ body[narrow] #restorePreviousSession::before {
content: url("chrome://browser/content/abouthome/addons@2x.png");
}
+%ifdef MOZ_SERVICES_SYNC
#sync::before {
content: url("chrome://browser/content/abouthome/sync@2x.png");
}
+%endif
#settings::before {
content: url("chrome://browser/content/abouthome/settings@2x.png");
diff --git a/application/basilisk/base/content/abouthome/aboutHome.xhtml b/application/basilisk/base/content/abouthome/aboutHome.xhtml
index 22bf2e7e8..90daad2dc 100644
--- a/application/basilisk/base/content/abouthome/aboutHome.xhtml
+++ b/application/basilisk/base/content/abouthome/aboutHome.xhtml
@@ -54,7 +54,9 @@
<button class="launchButton" id="bookmarks">&abouthome.bookmarksButton.label;</button>
<button class="launchButton" id="history">&abouthome.historyButton.label;</button>
<button class="launchButton" id="addons">&abouthome.addonsButton.label;</button>
+#ifdef MOZ_SERVICES_SYNC
<button class="launchButton" id="sync">&abouthome.syncButton.label;</button>
+#endif
#ifdef XP_WIN
<button class="launchButton" id="settings">&abouthome.preferencesButtonWin.label;</button>
#else
diff --git a/application/basilisk/base/content/browser-addons.js b/application/basilisk/base/content/browser-addons.js
index 1d881536a..733114ba9 100644
--- a/application/basilisk/base/content/browser-addons.js
+++ b/application/basilisk/base/content/browser-addons.js
@@ -145,10 +145,6 @@ const gXPInstallObserver = {
for (let install of installInfo.installs)
install.install();
installInfo = null;
-
- Services.telemetry
- .getHistogramById("SECURITY_UI")
- .add(Ci.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL_CLICK_THROUGH);
};
break;
}
@@ -208,10 +204,6 @@ const gXPInstallObserver = {
options);
removeNotificationOnEnd(popup, installInfo.installs);
-
- Services.telemetry
- .getHistogramById("SECURITY_UI")
- .add(Ci.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL);
},
observe: function (aSubject, aTopic, aData)
@@ -262,8 +254,6 @@ const gXPInstallObserver = {
messageString = gNavigatorBundle.getFormattedString("xpinstallPromptMessage",
[brandShortName]);
- let secHistogram = Components.classes["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry).getHistogramById("SECURITY_UI");
- secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_ADDON_ASKING_PREVENTED);
let popup = PopupNotifications.show(browser, notificationID,
messageString, anchorID,
null, null, options);
@@ -273,17 +263,14 @@ const gXPInstallObserver = {
messageString = gNavigatorBundle.getFormattedString("xpinstallPromptMessage",
[brandShortName]);
- let secHistogram = Components.classes["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry).getHistogramById("SECURITY_UI");
action = {
label: gNavigatorBundle.getString("xpinstallPromptAllowButton"),
accessKey: gNavigatorBundle.getString("xpinstallPromptAllowButton.accesskey"),
callback: function() {
- secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_ADDON_ASKING_PREVENTED_CLICK_THROUGH);
installInfo.install();
}
};
- secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_ADDON_ASKING_PREVENTED);
let popup = PopupNotifications.show(browser, notificationID,
messageString, anchorID,
action, null, options);
diff --git a/application/basilisk/base/content/browser-context.inc b/application/basilisk/base/content/browser-context.inc
index 36e0478af..d400cd0b2 100644
--- a/application/basilisk/base/content/browser-context.inc
+++ b/application/basilisk/base/content/browser-context.inc
@@ -51,23 +51,11 @@
label="&openLinkCmdInCurrent.label;"
accesskey="&openLinkCmdInCurrent.accesskey;"
oncommand="gContextMenu.openLinkInCurrent();"/>
-# label and data-usercontextid are dynamically set.
- <menuitem id="context-openlinkincontainertab"
- accesskey="&openLinkCmdInTab.accesskey;"
- oncommand="gContextMenu.openLinkInTab(event);"/>
+# label is dynamically set.
<menuitem id="context-openlinkintab"
label="&openLinkCmdInTab.label;"
accesskey="&openLinkCmdInTab.accesskey;"
- data-usercontextid="0"
- oncommand="gContextMenu.openLinkInTab(event);"/>
-
- <menu id="context-openlinkinusercontext-menu"
- label="&openLinkCmdInContainerTab.label;"
- accesskey="&openLinkCmdInContainerTab.accesskey;"
- hidden="true">
- <menupopup oncommand="gContextMenu.openLinkInTab(event);"
- onpopupshowing="return gContextMenu.createContainerMenu(event);" />
- </menu>
+ oncommand="gContextMenu.openLinkInTab();"/>
<menuitem id="context-openlink"
label="&openLinkCmd.label;"
@@ -261,13 +249,6 @@
accesskey="&savePageCmd.accesskey2;"
oncommand="gContextMenu.savePageAs();"/>
<menuseparator id="context-sep-sendpagetodevice" hidden="true"/>
- <menu id="context-sendpagetodevice"
- label="&sendPageToDevice.label;"
- accesskey="&sendPageToDevice.accesskey;"
- hidden="true">
- <menupopup id="context-sendpagetodevice-popup"
- onpopupshowing="(() => { let browser = gBrowser || getPanelBrowser(); gFxAccounts.populateSendTabToDevicesMenu(event.target, browser.currentURI.spec, browser.contentTitle); })()"/>
- </menu>
<menuseparator id="context-sep-viewbgimage"/>
<menuitem id="context-viewbgimage"
label="&viewBGImageCmd.label;"
@@ -308,13 +289,6 @@
<menuitem id="context-searchselect"
oncommand="BrowserSearch.loadSearchFromContext(this.searchTerms);"/>
<menuseparator id="context-sep-sendlinktodevice" hidden="true"/>
- <menu id="context-sendlinktodevice"
- label="&sendLinkToDevice.label;"
- accesskey="&sendLinkToDevice.accesskey;"
- hidden="true">
- <menupopup id="context-sendlinktodevice-popup"
- onpopupshowing="gFxAccounts.populateSendTabToDevicesMenu(event.target, gContextMenu.linkURL, gContextMenu.linkTextStr);"/>
- </menu>
<menuseparator id="frame-sep"/>
<menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;">
<menupopup>
diff --git a/application/basilisk/base/content/browser-doctype.inc b/application/basilisk/base/content/browser-doctype.inc
index ad08f4b03..30d70ccea 100644
--- a/application/basilisk/base/content/browser-doctype.inc
+++ b/application/basilisk/base/content/browser-doctype.inc
@@ -19,7 +19,9 @@
#endif
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
%aboutHomeDTD;
+#ifdef MOZ_SERVICES_SYNC
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
%syncBrandDTD;
+#endif
]>
diff --git a/application/basilisk/base/content/browser-fxaccounts.js b/application/basilisk/base/content/browser-fxaccounts.js
deleted file mode 100644
index e1d556bff..000000000
--- a/application/basilisk/base/content/browser-fxaccounts.js
+++ /dev/null
@@ -1,314 +0,0 @@
-/* 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/. */
-
-var gFxAccounts = {
-
- _initialized: false,
- _inCustomizationMode: false,
- _cachedProfile: null,
-
- get weave() {
- delete this.weave;
- return this.weave = Cc["@mozilla.org/weave/service;1"]
- .getService(Ci.nsISupports)
- .wrappedJSObject;
- },
-
- get topics() {
- // Do all this dance to lazy-load FxAccountsCommon.
- delete this.topics;
- return this.topics = [
- "weave:service:ready",
- "weave:service:login:change",
- "weave:service:setup-complete",
- "weave:service:sync:error",
- "weave:ui:login:error",
- this.FxAccountsCommon.ONLOGIN_NOTIFICATION,
- this.FxAccountsCommon.ONLOGOUT_NOTIFICATION,
- this.FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION,
- ];
- },
-
- get panelUIFooter() {
- delete this.panelUIFooter;
- return this.panelUIFooter = document.getElementById("PanelUI-footer-fxa");
- },
-
- get panelUIStatus() {
- delete this.panelUIStatus;
- return this.panelUIStatus = document.getElementById("PanelUI-fxa-status");
- },
-
- get panelUIAvatar() {
- delete this.panelUIAvatar;
- return this.panelUIAvatar = document.getElementById("PanelUI-fxa-avatar");
- },
-
- get panelUILabel() {
- delete this.panelUILabel;
- return this.panelUILabel = document.getElementById("PanelUI-fxa-label");
- },
-
- get panelUIIcon() {
- delete this.panelUIIcon;
- return this.panelUIIcon = document.getElementById("PanelUI-fxa-icon");
- },
-
- get strings() {
- delete this.strings;
- return this.strings = Services.strings.createBundle(
- "chrome://browser/locale/accounts.properties"
- );
- },
-
- get loginFailed() {
- // Referencing Weave.Service will implicitly initialize sync, and we don't
- // want to force that - so first check if it is ready.
- let service = Cc["@mozilla.org/weave/service;1"]
- .getService(Components.interfaces.nsISupports)
- .wrappedJSObject;
- if (!service.ready) {
- return false;
- }
- // LOGIN_FAILED_LOGIN_REJECTED explicitly means "you must log back in".
- // All other login failures are assumed to be transient and should go
- // away by themselves, so aren't reflected here.
- return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED;
- },
-
- init: function () {
- // Bail out if we're already initialized and for pop-up windows.
- if (this._initialized || !window.toolbar.visible) {
- return;
- }
-
- for (let topic of this.topics) {
- Services.obs.addObserver(this, topic, false);
- }
-
- gNavToolbox.addEventListener("customizationstarting", this);
- gNavToolbox.addEventListener("customizationending", this);
-
- EnsureFxAccountsWebChannel();
- this._initialized = true;
-
- this.updateUI();
- },
-
- uninit: function () {
- if (!this._initialized) {
- return;
- }
-
- for (let topic of this.topics) {
- Services.obs.removeObserver(this, topic);
- }
-
- this._initialized = false;
- },
-
- observe: function (subject, topic, data) {
- switch (topic) {
- case this.FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION:
- this._cachedProfile = null;
- // Fallthrough intended
- default:
- this.updateUI();
- break;
- }
- },
-
- handleEvent: function (event) {
- this._inCustomizationMode = event.type == "customizationstarting";
- this.updateAppMenuItem();
- },
-
- updateUI: function () {
- // It's possible someone signed in to FxA after seeing our notification
- // about "Legacy Sync migration" (which now is actually "Legacy Sync
- // auto-disconnect") so kill that notification if it still exists.
- let nb = window.document.getElementById("global-notificationbox");
- let n = nb.getNotificationWithValue(this.SYNC_MIGRATION_NOTIFICATION_TITLE);
- if (n) {
- nb.removeNotification(n, true);
- }
-
- this.updateAppMenuItem();
- },
-
- // Note that updateAppMenuItem() returns a Promise that's only used by tests.
- updateAppMenuItem: function () {
- let profileInfoEnabled = false;
- try {
- profileInfoEnabled = Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled");
- } catch (e) { }
-
- this.panelUIFooter.hidden = false;
-
- // Make sure the button is disabled in customization mode.
- if (this._inCustomizationMode) {
- this.panelUIStatus.setAttribute("disabled", "true");
- this.panelUILabel.setAttribute("disabled", "true");
- this.panelUIAvatar.setAttribute("disabled", "true");
- this.panelUIIcon.setAttribute("disabled", "true");
- } else {
- this.panelUIStatus.removeAttribute("disabled");
- this.panelUILabel.removeAttribute("disabled");
- this.panelUIAvatar.removeAttribute("disabled");
- this.panelUIIcon.removeAttribute("disabled");
- }
-
- let defaultLabel = this.panelUIStatus.getAttribute("defaultlabel");
- let errorLabel = this.panelUIStatus.getAttribute("errorlabel");
- let unverifiedLabel = this.panelUIStatus.getAttribute("unverifiedlabel");
- let settingslabel = this.panelUIStatus.getAttribute("settingslabel");
- // The localization string is for the signed in text, but it's the default text as well
- let defaultTooltiptext = this.panelUIStatus.getAttribute("signedinTooltiptext");
-
- let updateWithUserData = (userData) => {
- // Window might have been closed while fetching data.
- if (window.closed) {
- return;
- }
-
- // Reset the button to its original state.
- this.panelUILabel.setAttribute("label", defaultLabel);
- this.panelUIStatus.setAttribute("tooltiptext", defaultTooltiptext);
- this.panelUIFooter.removeAttribute("fxastatus");
- this.panelUIFooter.removeAttribute("fxaprofileimage");
- this.panelUIAvatar.style.removeProperty("list-style-image");
-
- if (Weave.Status.service == Weave.CLIENT_NOT_CONFIGURED) {
- // Leave the default state
- return;
- }
-
- if (this.loginFailed) {
- this.panelUIFooter.setAttribute("fxastatus", "error");
- this.panelUILabel.setAttribute("label", errorLabel);
- } else {
- this.panelUIFooter.setAttribute("fxastatus", "signedin");
- this.panelUILabel.setAttribute("label", settingslabel);
- this.panelUIStatus.setAttribute("tooltiptext", "");
- }
- }
-
- let updateWithProfile = (profile) => {
- if (profileInfoEnabled) {
- if (profile.displayName) {
- this.panelUILabel.setAttribute("label", profile.displayName);
- }
- if (profile.avatar) {
- this.panelUIFooter.setAttribute("fxaprofileimage", "set");
- let bgImage = "url(\"" + profile.avatar + "\")";
- this.panelUIAvatar.style.listStyleImage = bgImage;
-
- let img = new Image();
- img.onerror = () => {
- // Clear the image if it has trouble loading. Since this callback is asynchronous
- // we check to make sure the image is still the same before we clear it.
- if (this.panelUIAvatar.style.listStyleImage === bgImage) {
- this.panelUIFooter.removeAttribute("fxaprofileimage");
- this.panelUIAvatar.style.removeProperty("list-style-image");
- }
- };
- img.src = profile.avatar;
- }
- }
- }
-
- return fxAccounts.getSignedInUser().then(userData => {
- // userData may be null here when the user is not signed-in, but that's expected
- updateWithUserData(userData);
- // unverified users cause us to spew log errors fetching an OAuth token
- // to fetch the profile, so don't even try in that case.
- if (!userData || !userData.verified || !profileInfoEnabled) {
- return null; // don't even try to grab the profile.
- }
- if (this._cachedProfile) {
- return this._cachedProfile;
- }
- return fxAccounts.getSignedInUserProfile().catch(err => {
- // Not fetching the profile is sad but the FxA logs will already have noise.
- return null;
- });
- }).then(profile => {
- if (!profile) {
- return;
- }
- updateWithProfile(profile);
- this._cachedProfile = profile; // Try to avoid fetching the profile on every UI update
- }).catch(error => {
- // This is most likely in tests, were we quickly log users in and out.
- // The most likely scenario is a user logged out, so reflect that.
- // Bug 995134 calls for better errors so we could retry if we were
- // sure this was the failure reason.
- this.FxAccountsCommon.log.error("Error updating FxA account info", error);
- updateWithUserData(null);
- });
- },
-
- onMenuPanelCommand: function () {
-
- switch (this.panelUIFooter.getAttribute("fxastatus")) {
- case "signedin":
- this.openPreferences();
- break;
- case "error":
- if (this.panelUIFooter.getAttribute("unverified")) {
- this.openPreferences();
- } else {
- this.openSignInAgainPage("menupanel");
- }
- break;
- default:
- this.openPreferences();
- break;
- }
-
- PanelUI.hide();
- },
-
- openPreferences: function () {
- openPreferences("paneSync", { urlParams: { entrypoint: "menupanel" } });
- },
-
- openAccountsPage: function (action, urlParams={}) {
- let params = new URLSearchParams();
- if (action) {
- params.set("action", action);
- }
- for (let name in urlParams) {
- if (urlParams[name] !== undefined) {
- params.set(name, urlParams[name]);
- }
- }
- let url = "about:accounts?" + params;
- switchToTabHavingURI(url, true, {
- replaceQueryString: true
- });
- },
-
- openSignInAgainPage: function (entryPoint) {
- this.openAccountsPage("reauth", { entrypoint: entryPoint });
- },
-
- updateTabContextMenu: function (aPopupMenu) {
- // STUB
- },
-
- initPageContextMenu: function (contextMenu) {
- // STUB
- }
-};
-
-XPCOMUtils.defineLazyGetter(gFxAccounts, "FxAccountsCommon", function () {
- return Cu.import("resource://gre/modules/FxAccountsCommon.js", {});
-});
-
-XPCOMUtils.defineLazyModuleGetter(gFxAccounts, "fxaMigrator",
- "resource://services-sync/FxaMigrator.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "EnsureFxAccountsWebChannel",
- "resource://gre/modules/FxAccountsWebChannel.jsm");
diff --git a/application/basilisk/base/content/browser-menubar.inc b/application/basilisk/base/content/browser-menubar.inc
index 41734711c..b6ab23be5 100644
--- a/application/basilisk/base/content/browser-menubar.inc
+++ b/application/basilisk/base/content/browser-menubar.inc
@@ -11,19 +11,12 @@
style="border:0px;padding:0px;margin:0px;-moz-appearance:none">
<menu id="file-menu" label="&fileMenu.label;"
accesskey="&fileMenu.accesskey;">
- <menupopup id="menu_FilePopup"
- onpopupshowing="updateUserContextUIVisibility();">
+ <menupopup id="menu_FilePopup">
<menuitem id="menu_newNavigatorTab"
label="&tabCmd.label;"
command="cmd_newNavigatorTab"
key="key_newNavigatorTab"
accesskey="&tabCmd.accesskey;"/>
- <menu id="menu_newUserContext"
- label="&newUserContext.label;"
- accesskey="&newUserContext.accesskey;"
- hidden="true">
- <menupopup onpopupshowing="return createUserContextMenu(event);" />
- </menu>
<menuitem id="menu_newNavigator"
label="&newNavigatorCmd.label;"
accesskey="&newNavigatorCmd.accesskey;"
@@ -202,9 +195,6 @@
key="key_gotoHistory"
observes="viewHistorySidebar"
label="&historyButton.label;"/>
- <menuitem id="menu_tabsSidebar"
- observes="viewTabsSidebar"
- label="&syncedTabs.sidebar.label;"/>
</menupopup>
</menu>
<menuseparator/>
@@ -324,11 +314,13 @@
key="key_sanitize"
command="Tools:Sanitize"/>
<menuseparator id="sanitizeSeparator"/>
+#ifdef MOZ_SERVICES_SYNC
<menuitem id="sync-tabs-menuitem"
class="syncTabsMenuItem"
- label="&syncTabsMenu3.label;"
+ label="&syncTabsMenu2.label;"
oncommand="BrowserOpenSyncTabs();"
- hidden="true"/>
+ disabled="true"/>
+#endif
<menuitem id="historyRestoreLastSession"
label="&historyRestoreLastSession.label;"
command="Browser:RestoreLastSession"/>
@@ -447,11 +439,10 @@
accesskey="&toolsMenu.accesskey;"
onpopupshowing="mirrorShow(this)">
<menupopup id="menu_ToolsPopup"
-# We have to use setTimeout() here to avoid a flickering menu bar when opening
-# the Tools menu, see bug 970769. This can be removed once we got rid of the
-# event loop spinning in Weave.Status._authManager.
- onpopupshowing="setTimeout(() => gSyncUI.updateUI());"
- >
+#ifdef MOZ_SERVICES_SYNC
+ onpopupshowing="gSyncUI.updateUI();"
+#endif
+ >
<menuitem id="menu_openDownloads"
label="&downloads.label;"
accesskey="&downloads.accesskey;"
@@ -462,23 +453,19 @@
accesskey="&addons.accesskey;"
key="key_openAddons"
command="Tools:Addons"/>
-
- <!-- only one of sync-setup, sync-syncnowitem or sync-reauthitem will be showing at once -->
+#ifdef MOZ_SERVICES_SYNC
+ <!-- only one of sync-setup or sync-menu will be showing at once -->
<menuitem id="sync-setup"
- label="&syncSignIn.label;"
- accesskey="&syncSignIn.accesskey;"
+ label="&syncSetup.label;"
+ accesskey="&syncSetup.accesskey;"
observes="sync-setup-state"
- oncommand="gSyncUI.openSetup(null, 'menubar')"/>
+ oncommand="gSyncUI.openSetup()"/>
<menuitem id="sync-syncnowitem"
label="&syncSyncNowItem.label;"
accesskey="&syncSyncNowItem.accesskey;"
observes="sync-syncnow-state"
oncommand="gSyncUI.doSync(event);"/>
- <menuitem id="sync-reauthitem"
- label="&syncReAuthItem.label;"
- accesskey="&syncReAuthItem.accesskey;"
- observes="sync-reauth-state"
- oncommand="gSyncUI.openSignInAgainPage('menubar');"/>
+#endif
<menuseparator id="devToolsSeparator"/>
<menu id="webDeveloperMenu"
label="&webDeveloperMenu.label;"
diff --git a/application/basilisk/base/content/browser-places.js b/application/basilisk/base/content/browser-places.js
index 83c737977..87734140f 100644
--- a/application/basilisk/base/content/browser-places.js
+++ b/application/basilisk/base/content/browser-places.js
@@ -804,18 +804,29 @@ HistoryMenu.prototype = {
},
toggleTabsFromOtherComputers: function PHM_toggleTabsFromOtherComputers() {
+ // This is a no-op if MOZ_SERVICES_SYNC isn't defined
+#ifdef MOZ_SERVICES_SYNC
// Enable/disable the Tabs From Other Computers menu. Some of the menus handled
// by HistoryMenu do not have this menuitem.
let menuitem = this._rootElt.getElementsByClassName("syncTabsMenuItem")[0];
if (!menuitem)
return;
- if (!PlacesUIUtils.shouldShowTabsFromOtherComputersMenuitem()) {
+ // If Sync isn't configured yet, then don't show the menuitem.
+ if (Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED ||
+ Weave.Svc.Prefs.get("firstSync", "") == "notReady") {
menuitem.setAttribute("hidden", true);
return;
}
+ // The tabs engine might never be inited (if services.sync.registerEngines
+ // is modified), so make sure we avoid undefined errors.
+ let enabled = Weave.Service.isLoggedIn &&
+ Weave.Service.engineManager.get("tabs") &&
+ Weave.Service.engineManager.get("tabs").enabled;
+ menuitem.setAttribute("disabled", !enabled);
menuitem.setAttribute("hidden", false);
+#endif
},
_onPopupShowing: function HM__onPopupShowing(aEvent) {
diff --git a/application/basilisk/base/content/browser-sets.inc b/application/basilisk/base/content/browser-sets.inc
index 6ea057d93..d6a9310ed 100644
--- a/application/basilisk/base/content/browser-sets.inc
+++ b/application/basilisk/base/content/browser-sets.inc
@@ -163,16 +163,13 @@
<!-- A broadcaster of a number of attributes suitable for "sync now" UI -
A 'syncstatus' attribute is set while actively syncing, and the label
attribute which changes from "sync now" to "syncing" etc. -->
+#ifdef MOZ_SERVICES_SYNC
<broadcaster id="sync-status"/>
<!-- broadcasters of the "hidden" attribute to reflect setup state for
menus -->
<broadcaster id="sync-setup-state"/>
<broadcaster id="sync-syncnow-state" hidden="true"/>
- <broadcaster id="sync-reauth-state" hidden="true"/>
- <broadcaster id="viewTabsSidebar" autoCheck="false" sidebartitle="&syncedTabs.sidebar.label;"
- type="checkbox" group="sidebar"
- sidebarurl="chrome://browser/content/syncedtabs/sidebar.xhtml"
- oncommand="SidebarUI.toggle('viewTabsSidebar');"/>
+#endif
<broadcaster id="workOfflineMenuitemState"/>
<broadcaster id="devtoolsMenuBroadcaster_ErrorConsole"
diff --git a/application/basilisk/base/content/browser-syncui.js b/application/basilisk/base/content/browser-syncui.js
index 3a57140f2..f57472658 100644
--- a/application/basilisk/base/content/browser-syncui.js
+++ b/application/basilisk/base/content/browser-syncui.js
@@ -1,63 +1,37 @@
-/* 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 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/.
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-#ifdef MOZ_SERVICES_CLOUDSYNC
-XPCOMUtils.defineLazyModuleGetter(this, "CloudSync",
- "resource://gre/modules/CloudSync.jsm");
-#endif
-
-XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
- "resource://gre/modules/FxAccounts.jsm");
-
-const MIN_STATUS_ANIMATION_DURATION = 1600;
-
-// gSyncUI handles updating the tools menu and displaying notifications.
+// gSyncUI handles updating the tools menu
var gSyncUI = {
_obs: ["weave:service:sync:start",
- "weave:service:sync:finish",
- "weave:service:sync:error",
+ "weave:service:sync:delayed",
"weave:service:quota:remaining",
"weave:service:setup-complete",
"weave:service:login:start",
"weave:service:login:finish",
- "weave:service:login:error",
"weave:service:logout:finish",
"weave:service:start-over",
- "weave:service:start-over:finish",
"weave:ui:login:error",
"weave:ui:sync:error",
"weave:ui:sync:finish",
"weave:ui:clear-error",
- "weave:engine:sync:finish"
],
_unloaded: false,
- // The last sync start time. Used to calculate the leftover animation time
- // once syncing completes (bug 1239042).
- _syncStartTime: 0,
- _syncAnimationTimer: 0,
-
- init: function () {
- Cu.import("resource://services-common/stringbundle.js");
+ init: function SUI_init() {
// Proceed to set up the UI if Sync has already started up.
// Otherwise we'll do it when Sync is firing up.
- if (this.weaveService.ready) {
+ let xps = Components.classes["@mozilla.org/weave/service;1"]
+ .getService(Components.interfaces.nsISupports)
+ .wrappedJSObject;
+ if (xps.ready) {
this.initUI();
return;
}
- // Sync isn't ready yet, but we can still update the UI with an initial
- // state - we haven't called initUI() yet, but that's OK - that's more
- // about observers for state changes, and will be called once Sync is
- // ready to start sending notifications.
- this.updateUI();
-
Services.obs.addObserver(this, "weave:service:ready", true);
- Services.obs.addObserver(this, "quit-application", true);
// Remove the observer if the window is closed before the observer
// was triggered.
@@ -65,7 +39,6 @@ var gSyncUI = {
gSyncUI._unloaded = true;
window.removeEventListener("unload", onUnload, false);
Services.obs.removeObserver(gSyncUI, "weave:service:ready");
- Services.obs.removeObserver(gSyncUI, "quit-application");
if (Weave.Status.ready) {
gSyncUI._obs.forEach(function(topic) {
@@ -85,161 +58,136 @@ var gSyncUI = {
Services.obs.addObserver(this, topic, true);
}, this);
- // initial label for the sync buttons.
- let broadcaster = document.getElementById("sync-status");
- broadcaster.setAttribute("label", this._stringBundle.GetStringFromName("syncnow.label"));
-
- this.maybeMoveSyncedTabsButton();
-
+ if (gBrowser && Weave.Notifications.notifications.length) {
+ this.initNotifications();
+ }
this.updateUI();
},
+ initNotifications: function SUI_initNotifications() {
+ const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+ let notificationbox = document.createElementNS(XULNS, "notificationbox");
+ notificationbox.id = "sync-notifications";
+ notificationbox.setAttribute("flex", "1");
- // Returns a promise that resolves with true if Sync needs to be configured,
- // false otherwise.
- _needsSetup() {
- // If Sync is configured for FxAccounts then we do that promise-dance.
- if (this.weaveService.fxAccountsEnabled) {
- return fxAccounts.getSignedInUser().then(user => {
- // We want to treat "account needs verification" as "needs setup".
- return !(user && user.verified);
- });
- }
- // We are using legacy sync - check that.
- let firstSync = "";
- try {
- firstSync = Services.prefs.getCharPref("services.sync.firstSync");
- } catch (e) { }
-
- return Promise.resolve(Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED ||
- firstSync == "notReady");
+ let bottombox = document.getElementById("browser-bottombox");
+ bottombox.insertBefore(notificationbox, bottombox.firstChild);
+
+ // Force a style flush to ensure that our binding is attached.
+ notificationbox.clientTop;
+
+ // notificationbox will listen to observers from now on.
+ Services.obs.removeObserver(this, "weave:notification:added");
},
- // Returns a promise that resolves with true if the user currently signed in
- // to Sync needs to be verified, false otherwise.
- _needsVerification() {
- // For callers who care about the distinction between "needs setup" and
- // "needs verification"
- if (this.weaveService.fxAccountsEnabled) {
- return fxAccounts.getSignedInUser().then(user => {
- // If there is no user, they can't be in a "needs verification" state.
- if (!user) {
- return false;
- }
- return !user.verified;
- });
- }
+ _wasDelayed: false,
- // Otherwise we are configured for legacy Sync, which has no verification
- // concept.
- return Promise.resolve(false);
+ _needsSetup: function SUI__needsSetup() {
+ let firstSync = Services.prefs.getCharPref("services.sync.firstSync", "");
+ return Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED ||
+ firstSync == "notReady";
},
- // Note that we don't show login errors in a notification bar here, but do
- // still need to track a login-failed state so the "Tools" menu updates
- // with the correct state.
- _loginFailed: function () {
- // If Sync isn't already ready, we don't want to force it to initialize
- // by referencing Weave.Status - and it isn't going to be accurate before
- // Sync is ready anyway.
- if (!this.weaveService.ready) {
- this.log.debug("_loginFailed has sync not ready, so returning false");
- return false;
+ updateUI: function SUI_updateUI() {
+ let needsSetup = this._needsSetup();
+ document.getElementById("sync-setup-state").hidden = !needsSetup;
+ document.getElementById("sync-syncnow-state").hidden = needsSetup;
+
+ if (!gBrowser) {
+ return;
}
- this.log.debug("_loginFailed has sync state=${sync}",
- { sync: Weave.Status.login});
- return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED;
- },
- // Kick off an update of the UI - does *not* return a promise.
- updateUI() {
- this._promiseUpdateUI().catch(err => {
- this.log.error("updateUI failed", err);
- })
- },
+ let button = document.getElementById("sync-button");
+ if (!button) {
+ return;
+ }
- // Updates the UI - returns a promise.
- _promiseUpdateUI() {
- return this._needsSetup().then(needsSetup => {
- if (!gBrowser)
- return Promise.resolve();
-
- let loginFailed = this._loginFailed();
-
- // Start off with a clean slate
- document.getElementById("sync-reauth-state").hidden = true;
- document.getElementById("sync-setup-state").hidden = true;
- document.getElementById("sync-syncnow-state").hidden = true;
-
-#ifdef MOZ_SERVICES_CLOUDSYNC
- if (CloudSync && CloudSync.ready && CloudSync().adapters.count) {
- document.getElementById("sync-syncnow-state").hidden = false;
- } else if (loginFailed) {
-#else
- if (loginFailed) {
-#endif
- // unhiding this element makes the menubar show the login failure state.
- document.getElementById("sync-reauth-state").hidden = false;
- } else if (needsSetup) {
- document.getElementById("sync-setup-state").hidden = false;
- } else {
- document.getElementById("sync-syncnow-state").hidden = false;
- }
+ button.removeAttribute("status");
+
+ this._updateLastSyncTime();
- return this._updateSyncButtonsTooltip();
- });
+ if (needsSetup) {
+ button.removeAttribute("tooltiptext");
+ button.setAttribute("label", this._stringBundle.GetStringFromName("setupsync.label"));
+ } else {
+ button.setAttribute("label", this._stringBundle.GetStringFromName("syncnow.label"));
+ }
},
+
// Functions called by observers
- onActivityStart() {
+ onActivityStart: function SUI_onActivityStart() {
if (!gBrowser)
return;
- this.log.debug("onActivityStart");
+ let button = document.getElementById("sync-button");
+ if (!button)
+ return;
- clearTimeout(this._syncAnimationTimer);
- this._syncStartTime = Date.now();
+ button.setAttribute("status", "active");
+ button.setAttribute("label", this._stringBundle.GetStringFromName("syncing2.label"));
+ },
- let broadcaster = document.getElementById("sync-status");
- broadcaster.setAttribute("syncstatus", "active");
- broadcaster.setAttribute("label", this._stringBundle.GetStringFromName("syncing2.label"));
- broadcaster.setAttribute("disabled", "true");
+ onSyncDelay: function SUI_onSyncDelay() {
+ // basically, we want to just inform users that stuff is going to take a while
+ let title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title");
+ let description = this._stringBundle.GetStringFromName("error.sync.no_node_found");
+ let buttons = [new Weave.NotificationButton(
+ this._stringBundle.GetStringFromName("error.sync.serverStatusButton.label"),
+ this._stringBundle.GetStringFromName("error.sync.serverStatusButton.accesskey"),
+ function() { gSyncUI.openServerStatus(); return true; }
+ )];
+ let notification = new Weave.Notification(
+ title, description, null, Weave.Notifications.PRIORITY_INFO, buttons);
+ Weave.Notifications.replaceTitle(notification);
+ this._wasDelayed = true;
+ },
- this.updateUI();
+ onLoginFinish: function SUI_onLoginFinish() {
+ // Clear out any login failure notifications
+ let title = this._stringBundle.GetStringFromName("error.login.title");
+ this.clearError(title);
},
- _updateSyncStatus() {
- if (!gBrowser)
- return;
- let broadcaster = document.getElementById("sync-status");
- broadcaster.removeAttribute("syncstatus");
- broadcaster.removeAttribute("disabled");
- broadcaster.setAttribute("label", this._stringBundle.GetStringFromName("syncnow.label"));
- this.updateUI();
+ onSetupComplete: function SUI_onSetupComplete() {
+ this.onLoginFinish();
},
- onActivityStop() {
- if (!gBrowser)
+ onLoginError: function SUI_onLoginError() {
+ // if login fails, any other notifications are essentially moot
+ Weave.Notifications.removeAll();
+
+ // if we haven't set up the client, don't show errors
+ if (this._needsSetup()) {
+ this.updateUI();
return;
- this.log.debug("onActivityStop");
+ }
- let now = Date.now();
- let syncDuration = now - this._syncStartTime;
+ let title = this._stringBundle.GetStringFromName("error.login.title");
- if (syncDuration < MIN_STATUS_ANIMATION_DURATION) {
- let animationTime = MIN_STATUS_ANIMATION_DURATION - syncDuration;
- clearTimeout(this._syncAnimationTimer);
- this._syncAnimationTimer = setTimeout(() => this._updateSyncStatus(), animationTime);
+ let description;
+ if (Weave.Status.sync == Weave.PROLONGED_SYNC_FAILURE) {
+ // Convert to days
+ let lastSync =
+ Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400;
+ description =
+ this._stringBundle.formatStringFromName("error.sync.prolonged_failure", [lastSync], 1);
} else {
- this._updateSyncStatus();
+ let reason = Weave.Utils.getErrorString(Weave.Status.login);
+ description =
+ this._stringBundle.formatStringFromName("error.sync.description", [reason], 1);
}
- },
- onLoginError: function SUI_onLoginError() {
- this.log.debug("onLoginError: login=${login}, sync=${sync}", Weave.Status);
+ let buttons = [];
+ buttons.push(new Weave.NotificationButton(
+ this._stringBundle.GetStringFromName("error.login.prefs.label"),
+ this._stringBundle.GetStringFromName("error.login.prefs.accesskey"),
+ function() { gSyncUI.openPrefs(); return true; }
+ ));
- // We don't show any login errors here; browser-fxaccounts shows them in
- // the hamburger menu.
+ let notification = new Weave.Notification(title, description, null,
+ Weave.Notifications.PRIORITY_WARNING, buttons);
+ Weave.Notifications.replaceTitle(notification);
this.updateUI();
},
@@ -247,6 +195,10 @@ var gSyncUI = {
this.updateUI();
},
+ onStartOver: function SUI_onStartOver() {
+ this.clearError();
+ },
+
onQuotaNotice: function onQuotaNotice(subject, data) {
let title = this._stringBundle.GetStringFromName("warning.sync.quota.label");
let description = this._stringBundle.GetStringFromName("warning.sync.quota.description");
@@ -262,40 +214,26 @@ var gSyncUI = {
Weave.Notifications.replaceTitle(notification);
},
- _getAppName: function () {
- let brand = new StringBundle("chrome://branding/locale/brand.properties");
- return brand.get("brandShortName");
+ openServerStatus: function () {
+ let statusURL = Services.prefs.getCharPref("services.sync.statusURL");
+ window.openUILinkIn(statusURL, "tab");
},
// Commands
- // doSync forces a sync - it *does not* return a promise as it is called
- // via the various UI components.
- doSync() {
- this._needsSetup().then(needsSetup => {
- if (!needsSetup) {
- setTimeout(() => Weave.Service.errorHandler.syncAndReportErrors(), 0);
- }
- Services.obs.notifyObservers(null, "cloudsync:user-sync", null);
- }).catch(err => {
- this.log.error("Failed to force a sync", err);
- });
+ doSync: function SUI_doSync() {
+ setTimeout(function() Weave.Service.errorHandler.syncAndReportErrors(), 0);
},
- // Handle clicking the toolbar button - which either opens the Sync setup
- // pages or forces a sync now. Does *not* return a promise as it is called
- // via the UI.
- handleToolbarButton() {
- this._needsSetup().then(needsSetup => {
- if (needsSetup || this._loginFailed()) {
- this.openSetup();
- } else {
- this.doSync();
- }
- }).catch(err => {
- this.log.error("Failed to handle toolbar button command", err);
- });
+ handleToolbarButton: function SUI_handleStatusbarButton() {
+ if (this._needsSetup())
+ this.openSetup();
+ else
+ this.doSync();
},
+ //XXXzpao should be part of syncCommon.js - which we might want to make a module...
+ // To be fixed in a followup (bug 583366)
+
/**
* Invoke the Sync setup wizard.
*
@@ -304,11 +242,9 @@ var gSyncUI = {
* null -- regular set up wizard
* "pair" -- pair a device first
* "reset" -- reset sync
- * @param entryPoint
- * Indicates the entrypoint from where this method was called.
*/
- openSetup: function SUI_openSetup(wizardType, entryPoint = "syncbutton") {
+ openSetup: function SUI_openSetup(wizardType) {
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
if (win)
win.focus();
@@ -319,7 +255,6 @@ var gSyncUI = {
}
},
- // Open the legacy-sync device pairing UI. Note used for FxA Sync.
openAddDevice: function () {
if (!Weave.Utils.ensureMPUnlocked())
return;
@@ -332,202 +267,181 @@ var gSyncUI = {
"syncAddDevice", "centerscreen,chrome,resizable=no");
},
- openPrefs: function (entryPoint) {
- openPreferences("paneSync", { urlParams: { entrypoint: entryPoint } });
+ openQuotaDialog: function SUI_openQuotaDialog() {
+ let win = Services.wm.getMostRecentWindow("Sync:ViewQuota");
+ if (win)
+ win.focus();
+ else
+ Services.ww.activeWindow.openDialog(
+ "chrome://browser/content/sync/quota.xul", "",
+ "centerscreen,chrome,dialog,modal");
},
- openSignInAgainPage: function (entryPoint = "syncbutton") {
- gFxAccounts.openSignInAgainPage(entryPoint);
+ openPrefs: function SUI_openPrefs() {
+ openPreferences("paneSync");
},
- /* After Sync is initialized we perform a once-only check for the sync
- button being in "customize purgatory" and if so, move it to the panel.
- This is done primarily for profiles created before SyncedTabs landed,
- where the button defaulted to being in that purgatory.
- We use a preference to ensure we only do it once, so people can still
- customize it away and have it stick.
- */
- maybeMoveSyncedTabsButton() {
- const prefName = "browser.migrated-sync-button";
- let migrated = false;
- try {
- migrated = Services.prefs.getBoolPref(prefName);
- } catch (_) {}
- if (migrated) {
+ // Helpers
+ _updateLastSyncTime: function SUI__updateLastSyncTime() {
+ if (!gBrowser)
return;
- }
- if (!CustomizableUI.getPlacementOfWidget("sync-button")) {
- CustomizableUI.addWidgetToArea("sync-button", CustomizableUI.AREA_PANEL);
- }
- Services.prefs.setBoolPref(prefName, true);
- },
- /* Update the tooltip for the sync-status broadcaster (which will update the
- Sync Toolbar button and the Sync spinner in the FxA hamburger area.)
- If Sync is configured, the tooltip is when the last sync occurred,
- otherwise the tooltip reflects the fact that Sync needs to be
- (re-)configured.
- */
- _updateSyncButtonsTooltip: Task.async(function* () {
- if (!gBrowser)
+ let syncButton = document.getElementById("sync-button");
+ if (!syncButton)
return;
- let email;
- try {
- email = Services.prefs.getCharPref("services.sync.username");
- } catch (ex) {}
-
- let needsSetup = yield this._needsSetup();
- let needsVerification = yield this._needsVerification();
- let loginFailed = this._loginFailed();
- // This is a little messy as the Sync buttons are 1/2 Sync related and
- // 1/2 FxA related - so for some strings we use Sync strings, but for
- // others we reach into gFxAccounts for strings.
- let tooltiptext;
- if (needsVerification) {
- // "needs verification"
- tooltiptext = gFxAccounts.strings.formatStringFromName("verifyDescription", [email], 1);
- } else if (needsSetup) {
- // "needs setup".
- tooltiptext = this._stringBundle.GetStringFromName("signInToSync.description");
- } else if (loginFailed) {
- // "need to reconnect/re-enter your password"
- tooltiptext = gFxAccounts.strings.formatStringFromName("reconnectDescription", [email], 1);
- } else {
- // Sync appears configured - format the "last synced at" time.
- try {
- let lastSync = new Date(Services.prefs.getCharPref("services.sync.lastSync"));
- tooltiptext = this.formatLastSyncDate(lastSync);
- }
- catch (e) {
- // pref doesn't exist (which will be the case until we've seen the
- // first successful sync) or is invalid (which should be impossible!)
- // Just leave tooltiptext as the empty string in these cases, which
- // will cause the tooltip to be removed below.
- }
+ let lastSync = Services.prefs.getCharPref("services.sync.lastSync", "");
+ if (!lastSync || this._needsSetup()) {
+ syncButton.removeAttribute("tooltiptext");
+ return;
}
- // We've done all our promise-y work and ready to update the UI - make
- // sure it hasn't been torn down since we started.
- if (!gBrowser)
- return;
+ // Show the day-of-week and time (HH:MM) of last sync
+ let lastSyncDate = new Date(lastSync).toLocaleFormat("%a %H:%M");
+ let lastSyncLabel =
+ this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDate], 1);
- let broadcaster = document.getElementById("sync-status");
- if (broadcaster) {
- if (tooltiptext) {
- broadcaster.setAttribute("tooltiptext", tooltiptext);
- } else {
- broadcaster.removeAttribute("tooltiptext");
- }
- }
- }),
-
- formatLastSyncDate: function(date) {
- let dateFormat;
- let sixDaysAgo = (() => {
- let date = new Date();
- date.setDate(date.getDate() - 6);
- date.setHours(0, 0, 0, 0);
- return date;
- })();
- // It may be confusing for the user to see "Last Sync: Monday" when the last sync was a indeed a Monday but 3 weeks ago
- if (date < sixDaysAgo) {
- dateFormat = {month: 'long', day: 'numeric'};
- } else {
- dateFormat = {weekday: 'long', hour: 'numeric', minute: 'numeric'};
- }
- let lastSyncDateString = date.toLocaleDateString(undefined, dateFormat);
- return this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDateString], 1);
+ syncButton.setAttribute("tooltiptext", lastSyncLabel);
},
- onClientsSynced: function() {
- let broadcaster = document.getElementById("sync-syncnow-state");
- if (broadcaster) {
- if (Weave.Service.clientsEngine.stats.numClients > 1) {
- broadcaster.setAttribute("devices-status", "multi");
- } else {
- broadcaster.setAttribute("devices-status", "single");
- }
+ clearError: function SUI_clearError(errorString) {
+ Weave.Notifications.removeAll(errorString);
+ this.updateUI();
+ },
+
+ onSyncFinish: function SUI_onSyncFinish() {
+ let title = this._stringBundle.GetStringFromName("error.sync.title");
+
+ // Clear out sync failures on a successful sync
+ this.clearError(title);
+
+ if (this._wasDelayed && Weave.Status.sync != Weave.NO_SYNC_NODE_FOUND) {
+ title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title");
+ this.clearError(title);
+ this._wasDelayed = false;
}
},
onSyncError: function SUI_onSyncError() {
- this.log.debug("onSyncError: login=${login}, sync=${sync}", Weave.Status);
let title = this._stringBundle.GetStringFromName("error.sync.title");
- let error = Weave.Utils.getErrorString(Weave.Status.sync);
- let description =
+
+ if (Weave.Status.login != Weave.LOGIN_SUCCEEDED) {
+ this.onLoginError();
+ return;
+ }
+
+ let description;
+ if (Weave.Status.sync == Weave.PROLONGED_SYNC_FAILURE) {
+ // Convert to days
+ let lastSync =
+ Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400;
+ description =
+ this._stringBundle.formatStringFromName("error.sync.prolonged_failure", [lastSync], 1);
+ } else {
+ let error = Weave.Utils.getErrorString(Weave.Status.sync);
+ description =
this._stringBundle.formatStringFromName("error.sync.description", [error], 1);
+ }
let priority = Weave.Notifications.PRIORITY_WARNING;
let buttons = [];
- if (Weave.Status.sync == Weave.OVER_QUOTA) {
- description = this._stringBundle.GetStringFromName("error.sync.quota.description");
+ // Check if the client is outdated in some way
+ let outdated = Weave.Status.sync == Weave.VERSION_OUT_OF_DATE;
+ for (let [engine, reason] in Iterator(Weave.Status.engines))
+ outdated = outdated || reason == Weave.VERSION_OUT_OF_DATE;
+
+ if (outdated) {
+ description = this._stringBundle.GetStringFromName(
+ "error.sync.needUpdate.description");
+ buttons.push(new Weave.NotificationButton(
+ this._stringBundle.GetStringFromName("error.sync.needUpdate.label"),
+ this._stringBundle.GetStringFromName("error.sync.needUpdate.accesskey"),
+ function() {
+ window.openUILinkIn(Services.prefs.getCharPref("services.sync.outdated.url"), "tab");
+ return true;
+ }
+ ));
+ }
+ else if (Weave.Status.sync == Weave.OVER_QUOTA) {
+ description = this._stringBundle.GetStringFromName(
+ "error.sync.quota.description");
buttons.push(new Weave.NotificationButton(
- this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.label"),
- this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.accesskey"),
+ this._stringBundle.GetStringFromName(
+ "error.sync.viewQuotaButton.label"),
+ this._stringBundle.GetStringFromName(
+ "error.sync.viewQuotaButton.accesskey"),
function() { gSyncUI.openQuotaDialog(); return true; } )
);
- // Only show the notification bar on Quota error. the panel will show the rest.
- let notification =
- new Weave.Notification(title, description, null, priority, buttons);
- Weave.Notifications.replaceTitle(notification);
+ }
+ else if (Weave.Status.enforceBackoff) {
+ priority = Weave.Notifications.PRIORITY_INFO;
+ buttons.push(new Weave.NotificationButton(
+ this._stringBundle.GetStringFromName("error.sync.serverStatusButton.label"),
+ this._stringBundle.GetStringFromName("error.sync.serverStatusButton.accesskey"),
+ function() { gSyncUI.openServerStatus(); return true; }
+ ));
+ }
+ else {
+ priority = Weave.Notifications.PRIORITY_INFO;
+ buttons.push(new Weave.NotificationButton(
+ this._stringBundle.GetStringFromName("error.sync.tryAgainButton.label"),
+ this._stringBundle.GetStringFromName("error.sync.tryAgainButton.accesskey"),
+ function() { gSyncUI.doSync(); return true; }
+ ));
+ }
+
+ let notification =
+ new Weave.Notification(title, description, null, priority, buttons);
+ Weave.Notifications.replaceTitle(notification);
+
+ if (this._wasDelayed && Weave.Status.sync != Weave.NO_SYNC_NODE_FOUND) {
+ title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title");
+ Weave.Notifications.removeAll(title);
+ this._wasDelayed = false;
}
this.updateUI();
},
-
observe: function SUI_observe(subject, topic, data) {
- this.log.debug("observed", topic);
if (this._unloaded) {
Cu.reportError("SyncUI observer called after unload: " + topic);
return;
}
- // Unwrap, just like Svc.Obs, but without pulling in that dependency.
- if (subject && typeof subject == "object" &&
- ("wrappedJSObject" in subject) &&
- ("observersModuleSubjectWrapper" in subject.wrappedJSObject)) {
- subject = subject.wrappedJSObject.object;
- }
-
- // First handle "activity" only.
switch (topic) {
case "weave:service:sync:start":
this.onActivityStart();
break;
- case "weave:service:sync:finish":
- case "weave:service:sync:error":
- this.onActivityStop();
- break;
- }
- // Now non-activity state (eg, enabled, errors, etc)
- // Note that sync uses the ":ui:" notifications for errors because sync.
- switch (topic) {
case "weave:ui:sync:finish":
- // Do nothing.
+ this.onSyncFinish();
break;
case "weave:ui:sync:error":
this.onSyncError();
break;
- case "weave:service:setup-complete":
- case "weave:service:login:finish":
- case "weave:service:login:start":
- case "weave:service:start-over":
- this.updateUI();
+ case "weave:service:sync:delayed":
+ this.onSyncDelay();
break;
case "weave:service:quota:remaining":
this.onQuotaNotice();
break;
+ case "weave:service:setup-complete":
+ this.onSetupComplete();
+ break;
+ case "weave:service:login:start":
+ this.onActivityStart();
+ break;
+ case "weave:service:login:finish":
+ this.onLoginFinish();
+ break;
case "weave:ui:login:error":
- case "weave:service:login:error":
this.onLoginError();
break;
case "weave:service:logout:finish":
this.onLogout();
break;
- case "weave:service:start-over:finish":
- this.updateUI();
+ case "weave:service:start-over":
+ this.onStartOver();
break;
case "weave:service:ready":
this.initUI();
@@ -535,16 +449,8 @@ var gSyncUI = {
case "weave:notification:added":
this.initNotifications();
break;
- case "weave:engine:sync:finish":
- if (data != "clients") {
- return;
- }
- this.onClientsSynced();
- break;
- case "quit-application":
- // Stop the animation timer on shutdown, since we can't update the UI
- // after this.
- clearTimeout(this._syncAnimationTimer);
+ case "weave:ui:clear-error":
+ this.clearError();
break;
}
},
@@ -556,19 +462,10 @@ var gSyncUI = {
};
XPCOMUtils.defineLazyGetter(gSyncUI, "_stringBundle", function() {
- // XXXzpao these strings should probably be moved from /services to /browser... (bug 583381)
+ //XXXzpao these strings should probably be moved from /services to /browser... (bug 583381)
// but for now just make it work
return Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService).
createBundle("chrome://weave/locale/services/sync.properties");
});
-XPCOMUtils.defineLazyGetter(gSyncUI, "log", function() {
- return Log.repository.getLogger("browserwindow.syncui");
-});
-
-XPCOMUtils.defineLazyGetter(gSyncUI, "weaveService", function() {
- return Components.classes["@mozilla.org/weave/service;1"]
- .getService(Components.interfaces.nsISupports)
- .wrappedJSObject;
-});
diff --git a/application/basilisk/base/content/browser.css b/application/basilisk/base/content/browser.css
index 517c1c5eb..a2c2559d6 100644
--- a/application/basilisk/base/content/browser.css
+++ b/application/basilisk/base/content/browser.css
@@ -687,6 +687,18 @@ window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#pri
min-width: 1px;
}
+%ifdef MOZ_SERVICES_SYNC
+/* Sync notification UI */
+#sync-notifications {
+ -moz-binding: url("chrome://browser/content/sync/notification.xml#notificationbox");
+ overflow-y: visible !important;
+}
+
+#sync-notifications notification {
+ -moz-binding: url("chrome://browser/content/sync/notification.xml#notification");
+}
+%endif
+
/* History Swipe Animation */
#historySwipeAnimationContainer {
diff --git a/application/basilisk/base/content/browser.js b/application/basilisk/base/content/browser.js
index 336670fa0..1dee19a1d 100644
--- a/application/basilisk/base/content/browser.js
+++ b/application/basilisk/base/content/browser.js
@@ -8,7 +8,6 @@ var Cu = Components.utils;
var Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/ContextualIdentityService.jsm");
Cu.import("resource://gre/modules/NotificationDB.jsm");
// lazy module getters
@@ -47,7 +46,6 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
["Task", "resource://gre/modules/Task.jsm"],
["UpdateUtils", "resource://gre/modules/UpdateUtils.jsm"],
["Weave", "resource://services-sync/main.js"],
- ["fxAccounts", "resource://gre/modules/FxAccounts.jsm"],
#ifdef MOZ_DEVTOOLS
// Note: Do not delete! It is used for: base/content/nsContextMenu.js
["gDevTools", "resource://devtools/client/framework/gDevTools.jsm"],
@@ -104,6 +102,12 @@ XPCOMUtils.defineLazyGetter(this, "PageMenuParent", function() {
return new tmp.PageMenuParent();
});
+#ifdef MOZ_SERVICES_SYNC
+XPCOMUtils.defineLazyModuleGetter(this, "Weave",
+ "resource://services-sync/main.js");
+#endif
+
+
XPCOMUtils.defineLazyGetter(this, "PopupNotifications", function () {
let tmp = {};
Cu.import("resource://gre/modules/PopupNotifications.jsm", tmp);
@@ -209,6 +213,10 @@ var gInitialPages = [
"about:logopage"
];
+#ifdef MOZ_SERVICES_SYNC
+#include browser-syncui.js
+#endif
+
function* browserWindows() {
let windows = Services.wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements())
@@ -827,10 +835,6 @@ function _loadURIWithFlags(browser, uri, params) {
}
try {
if (!mustChangeProcess) {
- if (params.userContextId) {
- browser.webNavigation.setOriginAttributesBeforeLoading({ userContextId: params.userContextId });
- }
-
browser.webNavigation.loadURIWithOptions(uri, flags,
referrer, referrerPolicy,
postData, null, null, triggeringPrincipal);
@@ -856,10 +860,6 @@ function _loadURIWithFlags(browser, uri, params) {
postData: postData
}
- if (params.userContextId) {
- loadParams.userContextId = params.userContextId;
- }
-
LoadInOtherProcess(browser, loadParams);
}
} catch (e) {
@@ -872,10 +872,6 @@ function _loadURIWithFlags(browser, uri, params) {
Cu.reportError(e);
gBrowser.updateBrowserRemotenessByURL(browser, uri);
- if (params.userContextId) {
- browser.webNavigation.setOriginAttributesBeforeLoading({ userContextId: params.userContextId });
- }
-
browser.webNavigation.loadURIWithOptions(uri, flags, referrer, referrerPolicy,
postData, null, null, triggeringPrincipal);
} else {
@@ -939,16 +935,6 @@ addEventListener("DOMContentLoaded", function onDCL() {
let initBrowser =
document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
- // The window's first argument is a tab if and only if we are swapping tabs.
- // We must set the browser's usercontextid before updateBrowserRemoteness(),
- // so that the newly created remote tab child has the correct usercontextid.
- if (window.arguments) {
- let tabToOpen = window.arguments[0];
- if (tabToOpen instanceof XULElement && tabToOpen.hasAttribute("usercontextid")) {
- initBrowser.setAttribute("usercontextid", tabToOpen.getAttribute("usercontextid"));
- }
- }
-
gBrowser.updateBrowserRemoteness(initBrowser, gMultiProcessBrowser);
});
@@ -1133,13 +1119,6 @@ var gBrowserInit = {
// make sure it has a docshell
gBrowser.docShell;
- // We must set usercontextid before updateBrowserRemoteness()
- // so that the newly created remote tab child has correct usercontextid
- if (tabToOpen.hasAttribute("usercontextid")) {
- let usercontextid = tabToOpen.getAttribute("usercontextid");
- gBrowser.selectedBrowser.setAttribute("usercontextid", usercontextid);
- }
-
// If the browser that we're swapping in was remote, then we'd better
// be able to support remote browsers, and then make our selectedTab
// remote.
@@ -1165,9 +1144,8 @@ var gBrowserInit = {
// [3]: postData (nsIInputStream)
// [4]: allowThirdPartyFixup (bool)
// [5]: referrerPolicy (int)
- // [6]: userContextId (int)
- // [7]: originPrincipal (nsIPrincipal)
- // [8]: triggeringPrincipal (nsIPrincipal)
+ // [6]: originPrincipal (nsIPrincipal)
+ // [7]: triggeringPrincipal (nsIPrincipal)
else if (window.arguments.length >= 3) {
let referrerURI = window.arguments[2];
if (typeof(referrerURI) == "string") {
@@ -1179,13 +1157,11 @@ var gBrowserInit = {
}
let referrerPolicy = (window.arguments[5] != undefined ?
window.arguments[5] : Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT);
- let userContextId = (window.arguments[6] != undefined ?
- window.arguments[6] : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID);
loadURI(uriToLoad, referrerURI, window.arguments[3] || null,
- window.arguments[4] || false, referrerPolicy, userContextId,
+ window.arguments[4] || false, referrerPolicy,
// pass the origin principal (if any) and force its use to create
// an initial about:blank viewer if present:
- window.arguments[7], !!window.arguments[7], window.arguments[8]);
+ window.arguments[6], !!window.arguments[6], window.arguments[7]);
window.focus();
}
// Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
@@ -1277,7 +1253,7 @@ var gBrowserInit = {
// Setup click-and-hold gestures access to the session history
// menus if global click-and-hold isn't turned on
- if (!getBoolPref("ui.click_hold_context_menus", false))
+ if (!Services.prefs.getBoolPref("ui.click_hold_context_menus", false))
SetClickAndHoldHandlers();
let NP = {};
@@ -1338,13 +1314,14 @@ var gBrowserInit = {
FullScreen.init();
PointerLock.init();
- // initialize the sync UI
- gSyncUI.init();
- gFxAccounts.init();
-
if (AppConstants.MOZ_DATA_REPORTING)
gDataNotificationInfoBar.init();
+#ifdef MOZ_SERVICES_SYNC
+ // initialize the sync UI
+ gSyncUI.init();
+#endif
+
gBrowserThumbnails.init();
gMenuButtonBadgeManager.init();
@@ -1478,8 +1455,6 @@ var gBrowserInit = {
FullScreen.uninit();
- gFxAccounts.uninit();
-
Services.obs.removeObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed");
try {
@@ -1640,8 +1615,10 @@ if (AppConstants.platform == "macosx") {
// initialize the private browsing UI
gPrivateBrowsingUI.init();
+#ifdef MOZ_SERVICES_SYNC
// initialize the sync UI
gSyncUI.init();
+#endif
};
gBrowserInit.nonBrowserWindowShutdown = function() {
@@ -1868,7 +1845,7 @@ function BrowserGoHome(aEvent) {
case "tabshifted":
case "tab":
urls = homePage.split("|");
- var loadInBackground = getBoolPref("browser.tabs.loadBookmarksInBackground", false);
+ var loadInBackground = Services.prefs.getBoolPref("browser.tabs.loadBookmarksInBackground", false);
gBrowser.loadTabs(urls, loadInBackground);
break;
case "window":
@@ -2070,7 +2047,7 @@ function BrowserTryToCloseWindow()
}
function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy,
- userContextId, originPrincipal, forceAboutBlankViewerInCurrent,
+ originPrincipal, forceAboutBlankViewerInCurrent,
triggeringPrincipal) {
try {
openLinkIn(uri, "current",
@@ -2078,7 +2055,6 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy,
referrerPolicy: referrerPolicy,
postData: postData,
allowThirdPartyFixup: allowThirdPartyFixup,
- userContextId: userContextId,
originPrincipal,
triggeringPrincipal,
forceAboutBlankViewerInCurrent,
@@ -2613,15 +2589,9 @@ var gMenuButtonUpdateBadge = {
cancelObserverRegistered: false,
init: function () {
- try {
- this.enabled = Services.prefs.getBoolPref("app.update.badge");
- } catch (e) {}
+ this.enabled = Services.prefs.getBoolPref("app.update.badge", false);
if (this.enabled) {
- try {
- this.badgeWaitTime = Services.prefs.getIntPref("app.update.badgeWaitTime");
- } catch (e) {
- this.badgeWaitTime = 345600; // 4 days
- }
+ this.badgeWaitTime = Services.prefs.getIntPref("app.update.badgeWaitTime", 345600); // 4 days
Services.obs.addObserver(this, "update-staged", false);
Services.obs.addObserver(this, "update-downloaded", false);
}
@@ -2838,15 +2808,10 @@ var BrowserOnClick = {
},
onCertError: function (browser, elementId, isTopFrame, location, securityInfoAsString) {
- let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
let securityInfo;
switch (elementId) {
case "exceptionDialogButton":
- if (isTopFrame) {
- secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_CLICK_ADD_EXCEPTION);
- }
-
securityInfo = getSecurityInfo(securityInfoAsString);
let sslStatus = securityInfo.QueryInterface(Ci.nsISSLStatusProvider)
.SSLStatus;
@@ -2874,64 +2839,27 @@ var BrowserOnClick = {
break;
case "returnButton":
- if (isTopFrame) {
- secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_GET_ME_OUT_OF_HERE);
- }
goBackFromErrorPage();
break;
-
- case "advancedButton":
- if (isTopFrame) {
- secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_UNDERSTAND_RISKS);
- }
-
- break;
}
},
onAboutBlocked: function (elementId, reason, isTopFrame, location) {
// Depending on what page we are displaying here (malware/phishing/unwanted)
// use the right strings and links for each.
- let bucketName = "";
- let sendTelemetry = false;
- if (reason === 'malware') {
- sendTelemetry = true;
- bucketName = "WARNING_MALWARE_PAGE_";
- } else if (reason === 'phishing') {
- sendTelemetry = true;
- bucketName = "WARNING_PHISHING_PAGE_";
- } else if (reason === 'unwanted') {
- sendTelemetry = true;
- bucketName = "WARNING_UNWANTED_PAGE_";
- }
- let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
- let nsISecTel = Ci.nsISecurityUITelemetry;
- bucketName += isTopFrame ? "TOP_" : "FRAME_";
switch (elementId) {
case "getMeOutButton":
- if (sendTelemetry) {
- secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
- }
getMeOutOfHere();
break;
case "reportButton":
// This is the "Why is this site blocked" button. We redirect
// to the generic page describing phishing/malware protection.
-
- // We log even if malware/phishing/unwanted info URL couldn't be found:
- // the measurement is for how many users clicked the WHY BLOCKED button
- if (sendTelemetry) {
- secHistogram.add(nsISecTel[bucketName + "WHY_BLOCKED"]);
- }
openHelpLink("phishing-malware", false, "current");
break;
case "ignoreWarningButton":
if (gPrefService.getBoolPref("browser.safebrowsing.allowOverride")) {
- if (sendTelemetry) {
- secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]);
- }
this.ignoreWarningButton(reason);
}
break;
@@ -3215,12 +3143,14 @@ var PrintPreviewListener = {
this._chromeState.globalNotificationsOpen = !globalNotificationBox.notificationsHidden;
globalNotificationBox.notificationsHidden = true;
+#ifdef MOZ_SERVICES_SYNC
this._chromeState.syncNotificationsOpen = false;
var syncNotifications = document.getElementById("sync-notifications");
if (syncNotifications) {
this._chromeState.syncNotificationsOpen = !syncNotifications.notificationsHidden;
syncNotifications.notificationsHidden = true;
}
+#endif
},
_showChrome: function () {
if (this._chromeState.notificationsOpen)
@@ -3232,8 +3162,10 @@ var PrintPreviewListener = {
if (this._chromeState.globalNotificationsOpen)
document.getElementById("global-notificationbox").notificationsHidden = false;
+#ifdef MOZ_SERVICES_SYNC
if (this._chromeState.syncNotificationsOpen)
document.getElementById("sync-notifications").notificationsHidden = false;
+#endif
if (this._chromeState.sidebarOpen)
SidebarUI.show(this._sidebarCommand);
@@ -3951,66 +3883,6 @@ function updateEditUIVisibility()
}
/**
- * Opens a new tab with the userContextId specified as an attribute of
- * sourceEvent. This attribute is propagated to the top level originAttributes
- * living on the tab's docShell.
- *
- * @param event
- * A click event on a userContext File Menu option
- */
-function openNewUserContextTab(event)
-{
- openUILinkIn(BROWSER_NEW_TAB_URL, "tab", {
- userContextId: parseInt(event.target.getAttribute('data-usercontextid')),
- });
-}
-
-/**
- * Updates File Menu User Context UI visibility depending on
- * privacy.userContext.enabled pref state.
- */
-function updateUserContextUIVisibility()
-{
- let menu = document.getElementById("menu_newUserContext");
- menu.hidden = !Services.prefs.getBoolPref("privacy.userContext.enabled");
- if (PrivateBrowsingUtils.isWindowPrivate(window)) {
- menu.setAttribute("disabled", "true");
- }
-}
-
-/**
- * Updates the User Context UI indicators if the browser is in a non-default context
- */
-function updateUserContextUIIndicator()
-{
- let hbox = document.getElementById("userContext-icons");
-
- let userContextId = gBrowser.selectedBrowser.getAttribute("usercontextid");
- if (!userContextId) {
- hbox.setAttribute("data-identity-color", "");
- hbox.hidden = true;
- return;
- }
-
- let identity = ContextualIdentityService.getIdentityFromId(userContextId);
- if (!identity) {
- hbox.setAttribute("data-identity-color", "");
- hbox.hidden = true;
- return;
- }
-
- hbox.setAttribute("data-identity-color", identity.color);
-
- let label = document.getElementById("userContext-label");
- label.setAttribute("value", ContextualIdentityService.getUserContextLabel(userContextId));
-
- let indicator = document.getElementById("userContext-indicator");
- indicator.setAttribute("data-identity-icon", identity.icon);
-
- hbox.hidden = false;
-}
-
-/**
* Makes the Character Encoding menu enabled or disabled as appropriate.
* To be called when the View menu or the app menu is opened.
*/
@@ -4690,7 +4562,6 @@ nsBrowserAccess.prototype = {
_openURIInNewTab: function(aURI, aReferrer, aReferrerPolicy, aIsPrivate,
aIsExternal, aForceNotRemote=false,
- aUserContextId=Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID,
aOpener = null, aTriggeringPrincipal = null) {
let win, needToFocusWin;
@@ -4719,7 +4590,6 @@ nsBrowserAccess.prototype = {
triggeringPrincipal: aTriggeringPrincipal,
referrerURI: aReferrer,
referrerPolicy: aReferrerPolicy,
- userContextId: aUserContextId,
fromExternal: aIsExternal,
inBackground: loadInBackground,
forceNotRemote: aForceNotRemote,
@@ -4796,13 +4666,10 @@ nsBrowserAccess.prototype = {
// will do the job of shuttling off the newly opened browser to run in
// the right process once it starts loading a URI.
let forceNotRemote = !!aOpener;
- let userContextId = aOpener && aOpener.document
- ? aOpener.document.nodePrincipal.originAttributes.userContextId
- : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
let openerWindow = (aFlags & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener;
let browser = this._openURIInNewTab(aURI, referrer, referrerPolicy,
isPrivate, isExternal,
- forceNotRemote, userContextId,
+ forceNotRemote,
openerWindow, triggeringPrincipal);
if (browser)
newWindow = browser.contentWindow;
@@ -4834,16 +4701,10 @@ nsBrowserAccess.prototype = {
var isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
- var userContextId = aParams.openerOriginAttributes &&
- ("userContextId" in aParams.openerOriginAttributes)
- ? aParams.openerOriginAttributes.userContextId
- : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID
-
let browser = this._openURIInNewTab(aURI, aParams.referrer,
aParams.referrerPolicy,
aParams.isPrivate,
isExternal, false,
- userContextId, null,
aParams.triggeringPrincipal);
if (browser)
return browser.QueryInterface(Ci.nsIFrameLoaderOwner);
@@ -5400,11 +5261,6 @@ function handleLinkClick(event, href, linkNode) {
triggeringPrincipal: doc.nodePrincipal,
};
- // The new tab/window must use the same userContextId
- if (doc.nodePrincipal.originAttributes.userContextId) {
- params.userContextId = doc.nodePrincipal.originAttributes.userContextId;
- }
-
openLinkIn(href, where, params);
event.preventDefault();
return true;
@@ -5476,8 +5332,6 @@ function handleDroppedLink(event, urlOrLinks, name)
let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange;
- let userContextId = gBrowser.selectedBrowser.getAttribute("usercontextid");
-
// event is null if links are dropped in content process.
// inBackground should be false, as it's loading into current browser.
let inBackground = false;
@@ -5501,7 +5355,6 @@ function handleDroppedLink(event, urlOrLinks, name)
replace: true,
allowThirdPartyFixup: false,
postDatas,
- userContextId,
});
}
});
@@ -6351,9 +6204,14 @@ function checkEmptyPageOrigin(browser = gBrowser.selectedBrowser,
return ssm.isSystemPrincipal(contentPrincipal);
}
+#ifdef MOZ_SERVICES_SYNC
function BrowserOpenSyncTabs() {
- switchToTabHavingURI("about:sync-tabs", true);
+ if (gSyncUI._needsSetup())
+ gSyncUI.openSetup();
+ else
+ switchToTabHavingURI("about:sync-tabs", true);
}
+#endif
/**
* Format a URL
@@ -7653,8 +7511,6 @@ var TabContextMenu = {
this.contextTab.addEventListener("TabAttrModified", this, false);
aPopupMenu.addEventListener("popuphiding", this, false);
-
- gFxAccounts.updateTabContextMenu(aPopupMenu);
},
handleEvent(aEvent) {
switch (aEvent.type) {
diff --git a/application/basilisk/base/content/browser.xul b/application/basilisk/base/content/browser.xul
index be64f1bac..91299de29 100644
--- a/application/basilisk/base/content/browser.xul
+++ b/application/basilisk/base/content/browser.xul
@@ -8,7 +8,6 @@
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/usercontext/usercontext.css" type="text/css"?>
#ifdef MOZ_DEVTOOLS
<?xml-stylesheet href="chrome://devtools/skin/devtools-browser.css" type="text/css"?>
#endif
@@ -101,11 +100,6 @@
tbattr="tabbrowser-multiple"
oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
<menuseparator id="context_sendTabToDevice_separator" hidden="true"/>
- <menu id="context_sendTabToDevice" label="&sendTabToDevice.label;"
- accesskey="&sendTabToDevice.accesskey;" hidden="true">
- <menupopup id="context_sendTabToDevicePopupMenu"
- onpopupshowing="gFxAccounts.populateSendTabToDevicesMenu(event.target, TabContextMenu.contextTab.linkedBrowser.currentURI.spec, TabContextMenu.contextTab.linkedBrowser.contentTitle);"/>
- </menu>
<menuseparator/>
<menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
tbattr="tabbrowser-multiple-visible"
@@ -391,59 +385,6 @@
<tooltip id="dynamic-shortcut-tooltip"
onpopupshowing="UpdateDynamicShortcutTooltipText(this);"/>
-
- <menupopup id="SyncedTabsSidebarContext">
- <menuitem label="&syncedTabs.context.open.label;"
- accesskey="&syncedTabs.context.open.accesskey;"
- id="syncedTabsOpenSelected" where="current"/>
- <menuitem label="&syncedTabs.context.openInNewTab.label;"
- accesskey="&syncedTabs.context.openInNewTab.accesskey;"
- id="syncedTabsOpenSelectedInTab" where="tab"/>
- <menuitem label="&syncedTabs.context.openInNewWindow.label;"
- accesskey="&syncedTabs.context.openInNewWindow.accesskey;"
- id="syncedTabsOpenSelectedInWindow" where="window"/>
- <menuitem label="&syncedTabs.context.openInNewPrivateWindow.label;"
- accesskey="&syncedTabs.context.openInNewPrivateWindow.accesskey;"
- id="syncedTabsOpenSelectedInPrivateWindow" where="window" private="true"/>
- <menuseparator/>
- <menuitem label="&syncedTabs.context.bookmarkSingleTab.label;"
- accesskey="&syncedTabs.context.bookmarkSingleTab.accesskey;"
- id="syncedTabsBookmarkSelected"/>
- <menuitem label="&syncedTabs.context.copy.label;"
- accesskey="&syncedTabs.context.copy.accesskey;"
- id="syncedTabsCopySelected"/>
- <menuseparator/>
- <menuitem label="&syncSyncNowItem.label;"
- accesskey="&syncSyncNowItem.accesskey;"
- id="syncedTabsRefresh"/>
- </menupopup>
- <menupopup id="SyncedTabsSidebarTabsFilterContext"
- class="textbox-contextmenu">
- <menuitem label="&undoCmd.label;"
- accesskey="&undoCmd.accesskey;"
- cmd="cmd_undo"/>
- <menuseparator/>
- <menuitem label="&cutCmd.label;"
- accesskey="&cutCmd.accesskey;"
- cmd="cmd_cut"/>
- <menuitem label="&copyCmd.label;"
- accesskey="&copyCmd.accesskey;"
- cmd="cmd_copy"/>
- <menuitem label="&pasteCmd.label;"
- accesskey="&pasteCmd.accesskey;"
- cmd="cmd_paste"/>
- <menuitem label="&deleteCmd.label;"
- accesskey="&deleteCmd.accesskey;"
- cmd="cmd_delete"/>
- <menuseparator/>
- <menuitem label="&selectAllCmd.label;"
- accesskey="&selectAllCmd.accesskey;"
- cmd="cmd_selectAll"/>
- <menuseparator/>
- <menuitem label="&syncSyncNowItem.label;"
- accesskey="&syncSyncNowItem.accesskey;"
- id="syncedTabsRefreshFilter"/>
- </menupopup>
</popupset>
#ifdef CAN_DRAW_IN_TITLEBAR
@@ -551,12 +492,7 @@
key="key_undoCloseTab"
label="&undoCloseTab.label;"
observes="History:UndoCloseTab"/>
- <menuseparator id="alltabs-popup-separator-1"/>
- <menu id="alltabs_containersTab"
- label="&newUserContext.label;">
- <menupopup id="alltabs_containersMenuTab" />
- </menu>
- <menuseparator id="alltabs-popup-separator-2"/>
+ <menuseparator id="alltabs-popup-separator"/>
</menupopup>
</toolbarbutton>
@@ -970,6 +906,18 @@
type="checkbox"
label="&fullScreenCmd.label;"
tooltip="dynamic-shortcut-tooltip"/>
+
+#ifdef MOZ_SERVICES_SYNC
+ <toolbarbutton id="sync-button"
+ class="toolbarbutton-1 chromeclass-toolbar-additional"
+ label="&syncToolbarButton.label;"
+ oncommand="gSyncUI.handleToolbarButton();"/>>
+
+ <toolbarbutton id="sync-tabs-button"
+ class="toolbarbutton-1 chromeclass-toolbar-additional"
+ label="&syncTabsToolbarButton.label;"
+ oncommand="BrowserOpenSyncTabs();"/>
+#endif
</toolbarpalette>
</toolbox>
diff --git a/application/basilisk/base/content/content.js b/application/basilisk/base/content/content.js
index 5accbdf7b..d2a70ba11 100644
--- a/application/basilisk/base/content/content.js
+++ b/application/basilisk/base/content/content.js
@@ -162,9 +162,6 @@ var handleContentContextMenu = function (event) {
let selectionInfo = BrowserUtils.getSelectionDetails(content);
- let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
- let userContextId = loadContext.originAttributes.userContextId;
-
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
let editFlags = SpellCheckHelper.isEditable(event.target, content);
let spellInfo;
@@ -188,7 +185,7 @@ var handleContentContextMenu = function (event) {
principal, docLocation, charSet, baseURI, referrer,
referrerPolicy, contentType, contentDisposition,
frameOuterWindowID, selectionInfo, disableSetDesktopBg,
- loginFillInfo, parentAllowsMixedContent, userContextId },
+ loginFillInfo, parentAllowsMixedContent },
{ event, popupNode: event.target });
}
else {
@@ -212,7 +209,6 @@ var handleContentContextMenu = function (event) {
disableSetDesktopBackground: disableSetDesktopBg,
loginFillInfo,
parentAllowsMixedContent,
- userContextId,
};
}
}
diff --git a/application/basilisk/base/content/global-scripts.inc b/application/basilisk/base/content/global-scripts.inc
index eef21e15e..db8496cfc 100644
--- a/application/basilisk/base/content/global-scripts.inc
+++ b/application/basilisk/base/content/global-scripts.inc
@@ -27,7 +27,6 @@
<script type="application/javascript" src="chrome://browser/content/browser-safebrowsing.js"/>
#endif
<script type="application/javascript" src="chrome://browser/content/browser-sidebar.js"/>
-<script type="application/javascript" src="chrome://browser/content/browser-syncui.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-tabsintitlebar.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-thumbnails.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-trackingprotection.js"/>
@@ -36,4 +35,3 @@
<script type="application/javascript" src="chrome://browser/content/browser-data-submission-info-bar.js"/>
#endif
-<script type="application/javascript" src="chrome://browser/content/browser-fxaccounts.js"/>
diff --git a/application/basilisk/base/content/newtab/alternativeDefaultSites.json b/application/basilisk/base/content/newtab/alternativeDefaultSites.json
deleted file mode 100644
index 018d3edcc..000000000
--- a/application/basilisk/base/content/newtab/alternativeDefaultSites.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
- "directory": [
- {
- "bgColor": "#ffffff",
- "directoryId": 10000000,
- "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAIX0lEQVR4nO1afXDbZh1+sxbWsbGvsrLbuBt36766sR3sOEgiuU4kx2vTpFGKm0SKsyyOlI8laUZTulLojQEHx4CyAaNnt72yrivklo1YSpxcW7YVbKXHgCvduCvroDt6o6OtLSWN1MRWX/5I4imyJMu2bPNHnrvfSZbf6P09z+/jfV+3ACxhCUsoAEouNWGlMRLri5GuZwUSe1Ug8bcFEjsjUPgHAoX/UyCxkyKJjQoU/iOhCd8WJSvW/8vpXFFsx7PGeaJsVaytul+g8KMiic+IFA7NTNB/rggk/jeRcu26RGFris3JEqIUtkFsdo2KFK6kI52pCSR2UmirZgY9YFmxeaYg1uyqFSj8lMXI5mofRb3rOwEAJcXmDS72ex8QvO43skjv3MeT2DtRX2150cgLzVUDIonF8xBh64KQ2FWRwncPejyFK4tYq/Nmoa1mPE/pnZ1ILe4TFxpdd+SdvOhxrhabXaeLTVjfsHfzSj5K4V8QKfyjnGs3P2UiCt/v/1LeyAsNlXebkbeRSOZ/Q+JCrBH/Yt7IX+qlbhS96dM+Y+dJLC6S+BWRwmazFizf5AEAQPRtHLEhukqMwo8KTfg2oamy8t+e0uvUczwDwDWxhopHBBLvElrc+wUSm/r/IN9a3ZtrbYqUe9eHTc7PZDLvoAcsi/lq2wQSO1M88k93r7ayjzdI76sxEv/5hdryT+foRknM696q9qMg5AEAQHx83WhWtU5i56PtG1E7fYkO+B4SKNd7AoWLBSEv9G3Asol8zOs+ddFTeWc+fDrXgq2MNmEP5+PdKZB/XR4RvRnWe8tjJ8+1ECsL4mA+EQ+vcCg8gHHuPjjZvc5S6guU6/3/POG5rdi+24IEv+KwEgFQ4QFU/rAKTu90pal5fCY60PlQsf22BefHwfUKD2YVfl6ACIAKfx2UX0QNBYj6arqL7bdtSIQBnYy+2iIAzg49Cid9bm3qv11sn21FggeHUwSILGQCgIljd8Kpreq+4Koqts+2QuGBmBL9FLsFSj+sgAKFnyq2v7ZCDoO7dKOvvc7fS3vcW4rts61I8OBxXdI6/UCJADgVvmGVHfMSAelgfUA6VBeQDqmv2nuzZ3rf6Y2r3SM7DB1RwmCnOsLaiGuenbWD/JwAcqI+IEPCL8H6gAwX7omADIn5z/Wqe0Iz1sgI3edSv6EjcR78OEk4jQiJCNhnlwD1ATlBmDqdCUHzcYRf3mXoSCIMXjdK95SeEAbfslUAk4iaEc1EsLnx0vNmAhw3q3mNAFvtFCBd2i8i4bdWAgYCDBkLwIMJw8antTDos12ARSTNM8JK5Amd8URAPmosQAS8Zdr41N/lIQOS0Z2/pkZe0iWoS35+rIY8rPfLvzcWgAdDljMgAr5tlwCEWgArjUxnnJXSmX8eMnQkPrH8OasCJMJgfyEE0KZxMrJ+i2WgyZq6gHTQ0BGFv+abujs//ab4gV0CqEvAar1n0gQXizj9PUNHEmHgTSFt1At4O3eCH+8D0tW2YUmoMkKvfyQzwC/vMHREegN8Tpe4zjIY55fD14+X9tgiwC8mV2ZrHS/LGOGXRd3y8aeKVee/3GrqjBIGMcMsmL/GJu6AW4+1QZRl/mKHADmipD4gz1jJHCIgw9oXJ+8zfVsi/ImXU7bDquvfI2ugZ7wHoiwDUY6BTrbTWRie+ti0d7rGrHTU5UD45StpX5iILPMZrQTD4Q0QG+2GKMckzcF28AXgaYiv7ZNesdokCb90PO0LP2TBpxQezKpFkPmb4Q/ebFlEHOWYZBY8FtriKwDXFDAHhLvr/bJi9TzQtPeycQNUI3HihkML5M9NfB4+caRTl/jHRsvtb333gTzzTUHDPonNZFkkfjVl7Zfr+MRtiMID+McICqtDvfrE2cWfHRxz2j321K155pxE84HLLWb7BK0odX75TEYTBI43hB1ch0HE554h7GJhKrkn/4wPMjfliXMSO4alcsIvx/UanZE17pcGMppkU2iL2zDt9QSZtwqu66/Okdbb88Qd7PydVFYfkGVthLWHHk1JyOteuHRjxpNh3JNjRtE3EgDlGIiwzLlqrq/MbvKtLwkewi/PalPc8PyQPDdIP8lqQvdw92qEZWbNyBqJgnD0VTTI7H74Je/1uRL/8mDr7VWjfYeJkecgdfC/6c8JavPL0+6fitn3JtdIzxbdqLPqiNMmwtAxR7BzZ+mgL2MnHGzHPQhL/wzlmCsLc64PbYPU4Xd1zwN6WdCwT/p61uQXsH6sL5TS/dOUgY4QCZRlxsuD9EDZsM/x4KDnk5ppSsqGfHehw3QjytHfQVj6HaP+U8F1wZbhMf1Dkerzpr3Sn4Ad/5/Yc2T7TQ6OOW2YBWZimAsVRzlaRoL0DMLRV/WW19SVh05+v5nbAxsPCPpZ4Jclwj95b87kF+BgO+5Bg8yFFHKZZkO68XqimoyvGd0FqUNnU/pA1yvTdbaRXwDCtj2CsszFjFLfSjZoRbEiqEqoqtE+6H2VT5LfvPfydtvJJ0V4jb537QhzxjLRdMSsimIhq5q538DNgSnbfqs0FoHrusUd6j2ScdTNyGZTNovfHa8Z6/fmnbwaTq5r+1wj0ziZrjlmvIKYP3ew9Hvk+NOPFpT8AjxHd6ypGOl607Z+YDUL5s4iChpkdq8b7b22KOTVQIPtGxet3bmQtVA6eKhnyBP6hvnPW8UAwvpq1nIdoeS6bpWY0fK3aMfJTCMc/csqtuf+YvNMi68Mt38WDTJPoSx9DGHpmaxLI8hcqBzpCiDB9ibnM87lxeaVLUrKg+1fRVimby3LPItw9G9Rlj6Bssw/EI4+i3DM+0iQPomy9JiD69hdztI7SoPtTWWvddry7w5LWIIx/gdCuvcjoZqlLQAAAABJRU5ErkJggg==",
- "type": "affiliate",
- "title": "Google",
- "url": "https://www.google.com/"
- },
- {
- "bgColor": "#E62117",
- "directoryId": 10000001,
- "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAACd0lEQVR4nO3av0tVYRzH8WOIBEVDUUIGCa32FwQ5OrS42NKeRUOTdGmoqUGiLVBqa5UG+7WUREGiEqhTDkVJEA2iYZBkxKvhHumo96o3uM9z0ucNZ7zn834+XO59znm+WZZIJBKJRCKRSGwCx3AWfbiIaxjEPYzgOd7gLWbwIb8WsFjjWrU9q3U+u1C4/0yeOZ47jOROg6jkrn25e3uji27NbzC9A9n/hWnVNbVut/hOTMZ1bSqT6Ky3+A58jOsXhE/o2Lj4FryILBaSF2gpFtAT2ygCPcUCHse2icDTtcW3YSW2TQRW0JahK7ZJRLoy9Ma2iEhvhoHYFhEZyDAU2yIiwxkeBgj6FSDjXxjN8CpA0A1cxucAWY0wkeFdgKBK/pe7H1fxNUDmTpjLMB8gqLJh631A9dF6IUD2Vsxn+BYgaF0BhSIO4WYgh1osZVgOEFSzgEIRh3EL3wO4FFnOAgVtWUChiKO4gx+BvJSqgEIRx3EXP5stVsoCCkWcxH1N3EeUuoBCEafwshlipS8AJzTxW1DaAnAEtzX5B7F0BeAgrmMphFhpClB9M3UFXwI5oQQFYB8u4H0gl3VE3QninOoxVyyWozwL4AxeB8jdjqWgT4M4jUcB8nbKfKj3AUN4gN8BshphLtQbobIyEeqdYFkZzTAc2yIiw+lcQDoZSmeDe/t0ON+gPIltE4Fnxa3pnp8QacFYbKOAjCnOCOUldKhOUO12Nk+JFUroxFRkwWYypd6cYKGEVvTbfZOil2w3KVqjjHZ047xqKRWbZ4XHVed2Z/2d5a0167vYgHC9z6/df9bWs8L9uXO3RmeFE4lEIpFIJPYKfwAcall+TY3q/wAAAABJRU5ErkJggg==",
- "type": "affiliate",
- "title": "YouTube",
- "url": "https://www.youtube.com/"
- },
- {
- "directoryId": 10000002,
- "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAACT0lEQVR4nO3bzWsTQRgG8PlPHMVLqRVMoQiFehJyUBAFtRCFHspExaaSoFg8CMGPSg+R3kQhh3osIbOlMVrbGKtrsbYESTbB0gqNVGu1WCkWutnXg+ihQjqxi7Oz8w481533+V32iyGEEEIZ76Rho0SZ4ewOG+D3UMatXSx9nPwqb5ySPZC0dPMzhDJelD6IrDCjQijjtvRBJIWGeY3IHkJ2EED2ALKDALIHkB2lAJoujkIwnoNQwoQL96aha3AKQgkTTtyZhKM383D4+gQEoll/AQRiWbg1XILZ+VWwaw6IrE3bgZbejNoAe8+PwEC6DOsbm0Klt679lxQGCESzMD335Z+KKw+wrzcDpcVvOyqvNMCwubjj8soCnBx44Up5ZQGeFZf1BWi7/BhqjthtzpcAseRsQwVrjgNzS9/hZWUFJq3Pf6U5MqoWQHJ8Qbh8aqoKB688cWVfzwBMvP0kVN6srMCec+7t6xmAmfmvQgCRBzOu7usZgHJ1TQjgyI283gCHrj3VG6C9bwwBEAABEEAtgAPRR9A3VKibpdUfQgD9KWvba529+8pbAMF4TqicW+th/r3eAP0pS2+Anvtv9AY4dvu53gCtMfGfI74DWN+wG5rNdwDl6preAGOFj3oDJMcXvAfQHMlAKGHWTeWD2KPw1aFC3et0NPi9wDPvAq/fif0LDMZzru6LALKLIwACIAACIAACIAACIAACIAACIAACIAACIMD/BvDKwUkZAJRx2zNHZyUBFAntTp+WXV4iQCf5c3yecUsXAMq49bv8Txsl6ZCTabOAAAAAAElFTkSuQmCC",
- "title": "Facebook",
- "type": "affiliate",
- "url": "https://www.facebook.com/"
- },
- {
- "bgColor": "#ffffff",
- "directoryId": 10000003,
- "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA/CAYAAABQHc7KAAAEyUlEQVRoge2abYhVRRjHf7veVqSFhIQwa7E3ojXNpSiNgl0S+tAHKUjohbQohUgqKKwMSXpbsATdqOgFU4zKpAzMioploxI/WFBZmhRlL/S2lbpsudvd24dzjve5c58558ycey9B84MB95x5/vM/d+bMzDNHCAQCgUAgEAgE/rf0AOd6lJmKVrdDfI8SfxawIKNcEscfa8TOzBFrlj6Aimd5XnmAbx01TD5xiL3IiH3Y8zm4DXgaGALGMip/DDwHDACXKQ9wA/AiMJyi8T3wAnCvEr841t9tiR2JY/uB443YC4BHgA3ApyntTxD90FuAlaaBU4EfLIHvKIZtnAT8ZtE5O6fGCiNuFJiTM7YNWKe0PQScmRV8ncX4+zkbT1hq0bkyZ/wyI+5ux/bPM+I/ACbnCSyhv8tloMvBQAnYr+h8mDP+PRHzGXCMQ9sA14j4ceAMl+A70HtvjaMJ22jqy4i70Kh/sWO7AO+K+Jdcg6cCh6k3/gfQ6aBTAr5UdN7OiHtL1H3NxXhMN9Fkl2jM89BgPXrv3eKoc71Fx2ZqvqhTJv+kKRkQGjs94gE4PTZgGt9DNMvmpQR8pehst9R/Q9TZ5OG7EzgkNK720DjKNvTeu9RRZ4miMUH9bnCeuH8EOMXD881C40egw0PjKL3oP8Cbjjq2FWGrUW+HuDfg6XmP0NA2W060GYKy97odtbQVoQzMiu+fL66PACd4+O0VGqPANA+NOm5CHwVPOeqUgH2Kzub4/uvi2gOeXrcU8GdlCtG7ZBr/C5juqHWtojMOXCX+HgaO8/B5YqyV6GjZpjf3oI+C+x11JgF7FZ1/xL/v9PS4WmgMempYsW2MfsdtYwTRsqT9mBXgANGIc6WD2lG60EMjk0fRTS931GkHPrdo3ejpbZHQ2B+30XC6iNZm0/Q3RBOcC7Yc4WRPb0NC43ZPjVxsRDe+yFHHHLJJWevhabaIP0z0ujaNWdQmGUn5yEPrPkVnBPe1+0kRv97DhzPb0UdBr6OObZv9kIOGnJzLRPlL0+lFN+6yPe5BH0kV4E/yD+PlIm6bQ/uF2Um98Qlgbs74V5V4WVbl0GgDvsB/BBbiCnTj2lG5yVyqvX+QaOSYOsNk7y8WiPo+c1Ah2tFPesbJTmFfEfX7qU2BZVmRoSPnkMU+D1EUW5L0WErMHKq9P0o149NeqZ+w7wq7qO77f02p11Qmo6/laWnoVlFvnbh+uaJTAW616Dwo6rjmIw3lLnTjminZ+38DM8Q92yv1HfUnOh3AL/H9I7hnpA1lKrXnb0nRkqSXxf0nFC3bK7XMqCdT6o2NeIiirEE3Lvfks6kesI6hf1m2nTt8TW2uIeeLhub8vsxAT5IOUB2+8qTm2RStlYqOnOV7xLXBRj5EUWxJ0hKic/2k98dJ367azh32Es0Tz4hrTcn5fZE9I8s+ajc6m20CgrUWrdVEK0yFJub8RRhEN56UMjk+TVO7xtuK6yFMS1hIuuk82+SETSk6h3A/hmsJ7egfPypEh555ej/hHOzZYktyfl9keiqLzzc+LUlqWc7vSyfRJ3Rpegw4zUOrj/ofoKU5vy/91Jp+vIDWLkPL/J9h/0mmAT9TXa58vvIkzKe6ydpQ3FogEAgEAoFAIBCI+Rf5q90lTPZHIwAAAABJRU5ErkJggg==",
- "title": "Wikipedia",
- "type": "affiliate",
- "url": "https://www.wikipedia.org/"
- },
- {
- "bgColor": "#400090",
- "directoryId": 10000004,
- "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAD3ElEQVR4nO3bS4xecxjH8WmLBVVEx63JBIkEISkhJqURpAsZQioWqpeNSxraYlKpSwiDIRY0aSakqgS9qHRBIhKxYdFFFxWXIGkilYZEUCKj4zLzsfi/LN55zpiZc/lr+/6Ss3nfc57ze77n9r88/y7swxaswgLM7jpMhTlYiNWtnPd1Ga9RfIVtuB+L0J3b/FSFeejDQ9iBvRhrTzYCUKTv8RFewlrcgAtxQsYk5+Ii3IQHsBm78ONkk5oKgIn0Mz7BO3gBA7gHS3EtLsXZre1UnITj2pI5vvV7D85BL67DCvRjEJvwHj7HcBXGqwJwyKoDILeB3OoAyG0gt8oAGMYj0qdnJ17DY3i2vK1CPYmn8Cq2YwgP4rfpBix7BwwE3+aZ2F0ybqQPMSM439NlgpYFMILzAlO9glZXCf2F+cF5LsafZQJX8Q4oujKbK4j9j4aC+EdhT9nAVb0Ebw8MduNABbF/wMlB/LUVxK4MwE84JTC5uoLYK4O48/BrBbEr/Qy+XnCbfloi5h7MCuJurcSxagGMYWFg9qr/SbxQVTeEiq7Ym9OI9UYQ52ipJ1iZ6mgJ3h0Y7zG17usvOC2I01+12ToAHBCMIGHdFGKsCo4/QwJTqerqC2wMEjgGX0zi2KLH6JU6jNYFYBSXBElc/R/HjaE3OO4y1bYs/1WdvcFd4hbilgmOie6cGa1Ytaju7vDSIKHTxc9yUYtvWZ0G6wawH8cGSa0J9r0t2G92K0ZtamJA5PEgsfaOTNHjMlC3uSYADKMnSG6B9GIr6uqehYN1m2tqSGxre4KtJDdhfcF/O5ow1hSAMVweJNmNOcHvlbb3J1KTg6K7MTO62m3Jz1LBQMdk1fSo8IpJALizSUNNA/jWBNPvOFGahG1MOeYFnpgAwHNNm8kB4CDODJI/F380bSbXzNAzAYD1OYzkAjAYABjKYaQDIMdJxQDqnFMsVC4A6wIAgzmMdADkOKkYwKM5jOQCcFcAYCqjxpUpF4Bovu+IB3BfDiO5AIzrFWJlDiO5ACzpABgP4I4cRnIBWBwAWJLDSC4AfR0A4wHcksNILgCLAgB9OYzkAnDFkQ5gDZbj3ta2XCp5bVydYuncBnKrAyC3gdzqAMhtILfqBDCCb6SZ3velatGXsUFa5NC+vdjatrf2/QAfSyUyv9dlsgyAEXyGt/G8VBl+PS7A3PaGTllJCy7n40Zp8GQD3sWXSgCaDIBRqcBxGx7GYmll57hixlySaojPx83SuqW3pLXC0wKwX7oF+3GloILjUJE03X6NtAh8J76LAOzFRtwqKGY63CStX14mLen5+m9Vgqdbrd+9cgAAAABJRU5ErkJggg==",
- "title": "Yahoo!",
- "type": "affiliate",
- "url": "https://www.yahoo.com/"
- },
- {
- "directoryId": 10000005,
- "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAJdklEQVR4nO1ba1QTZwL9iCY8hCDxDUpYOIUDBOVZAlJ5NQXRFlEQ8YGiRaqESlhxeRQ3FAWURRC6FYglqBHTEaI8Eg+CRMRatfKwLNL6oqer1h57XEWYbwJK9sdKixiSmRCCbrnn3D8w351770wy3zd8ADCJSUxiPMHhcPS3bdv2/tq1a9MWL16MODs7t5iamt4zMjLq0dfX76VSqU8sLCzueHt7S+3t7QtjYmLWJyYmzp1o32NGSUmJd0BAQLmRkVEPAEBOhCQS6bm3t7c0MjIyHACgMyEB1AGCILTY2NgUOzu7fwGCoUfj/Pnz/x0XF/fXgoICXW3nIYTs7Owlpqam94CGgo+ktbX1j4mJiY7azIQbMTExu3V0dF6AcQo/RF1dXYggSIj2kuFAfHx8Lhjn4ODVElCxWOygpXjKkZWVxQZaDD9EOp3eXV9fb6yVkKOho6Njgb6+fp8ig9pgfHx8gjZyjgYdX1/fhtHMqSKJRHpOJpNl6o4HAMidnJxatJJUEWpraz3xmBxOExOT30JDQ/+elpZmD14+26uqqubExcVFzJs3T53H5uCJEydMtZN4BKKiovKJmA0KChLu3bt3zmh6Bw4c0F+3bl0BEU0AgLygoCByXAKqgq2tbSdek0FBQTV4dZlM5kW8ugAAOZPJ/IeGIuHH9evXp+no6DzHa7K+vt4Lr3ZiYuIOvLoAALmnp6dQQ7HwIzc31xqvQRsbmy5AYC6fnJzsjlcbACD38/M7p5lUBBEeHp5lbm7+E4lEUnonREdHpxPRLSwsNFWmN5Kurq5XNZNITfj4+EwtLCw0dXFxcebz+UFhYWFbmExm6qZNm/IjIiKyampqDIjonTp1ajp4mwrQNP70BfD5/D9PAcXFxQZcLteOwWCw9u/f/3FwcHC6paVlOfg/K4CUlpbmEB0dvSEkJCTLxsamwtnZuXXmzJmPAACDgEBYRXxjC8jJyfFYtmzZYWNj48dgjCGV8Y0qICsryyQiIiKVTqf/BMYxNHgTC8jPz/+ISqU+AVoKDt6kAnbs2MGeMmXKANByePAmFBAbG5utyJi2OKEFJCcnx+MxqYizZs361d/fvyw9PX0bg8FgZWRk2FZVVc1pampaQERnwgoQi8VLVK0DRpJMJstWrlx5hMPhvMflckmKdN+amSDRdbuenl5fRkaGnyrdt6KAsrKyD4iYpFKpTy9cuPAuHu23ogAmk9lIxGRCQsLneLVLS0tnEdHWegFisXgu0b8ANTc3W+LVT0pKsiSirfUCDh06tJyIQSsrq5tE9PPy8jyI6Gu9gMDAQA5Bg9VE9Hfu3BlFRJ/BYHSMPRUBsNnsfUQMksnkciL6q1ev5hHRNzQ07AHa3D9A9N19QEAA7lfiAAAdOp3eTUQfACBHEMR87MlwgmgBZmZm9wHOK1RUVLSFiPYQd+/eHaOheKrB4XCyiBrk8XguqnTb29vNDAwMeolqAwDkCxcuvKbBiMoREhLyKVGDy5cvr1Cm2d3dPd3Ly+sCUd3h3LNnT7xGg46GoqKiQHUMbt68uZjL5VJG6qWkpPjS6fS76miO4Ivm5maVd9qYUV5ePlPdtb+FhUV3cHBwkbm5efrGjRvz7O3tr2og+O90dHRslUqlUxX5lkq5U7HmJEtUsnTxwG0kEJ7b4Cer32ArlXIVHq8ULBarVpPGNcng4GDP4V6xloxArNq3oq+M9hTlUeSvsfwvPxMuoKGhwWO8N0RRKBSM6Bg6nf4jgiC0zk6Egl3czsYQhxsKQ48g4QIAAMDf3//0eIWn0WiPjh075jx79uyHeMfY2dl1IAgyFwAAZA1rjqE8ihw9rPscrXRp7xO5lckaN6X0t+dt7m/LiYanPI+iPPLgmApoa2t75+W7fY2GX7RoUcvx48fpAAAgEom88NwJLBbr65ycnGlD3gZuli15VhfC6JZy9Ubzj1W6to6pAAAAEAgEDsbGxv/RVHh3d/ezEomEOvwcqamp6crGsNns/NHeLg0HPPOhV98Pf2ynQRHG+ZcFDKpdAAAAFBcX+6qzF3gkly5dqjCIVCrVs7e3v6RozKpVqw6q8idrybCFonfrUB5FDqsWfzv0c1jh2IHyKHIotL0J+lsyY7CqJXmyO4hamw/Ly8vnhIeH51Op1KdEQtNotN9WrFjxpVAodFOmv337dkMmk1k9NI5CoWCZmZk7EQSZouj4bilfT/ZtUjhW4yNCDxv0ozyKHJaZ9Mq+S1sDAACdnQgF8o1RlEeRy5picsDA3dPv9QnMHqI88iAUudYNdJV4q1NEXFyc7q5duzZ4eXmdtLKyukUikV6ZL1Cp1CeOjo6tHh4eRVwudwWfzx/1MzoSXC53alRUVCaLxapjs9kBio55fC3bGPvm0wRUQL/3yjc9n9Yz0HX090zolTSP//2OPIjdEVkDAAB42nmYJjsbWjo0CEMcfoCNkXvR5lh3BAlT2LQqhIWFTZFIJFSJRELdunUrWR0NVXhc/zdj9MxHa6B4qRAemfHasx6rYUnQjn8uGD5G9k3CHpRHkcvqQk+8Joh1lX2AHl9wf+RkAWtYvx9eSvaWSn2Iz5w0jId1O6fJLn8Wila6iVCe/oCiZ3sff8YT7CLnE6BgJQoRhxtoqcmz3l8vK9629+xW6Sx4dnUmLJv55DXxo3MeQ8ThDKxlfS77Pm8F1pxkqegkmsItSZxu75nAhf1NMZFY47ov4MlFzejLz69ClhrB/vObc3uuZM5QpIf9fM4K5VHk/W25sSpP3tdaaArPrBSgJbovlM6m+LQeWO13HqtwO4i1Zn0CRZ5+2Hf7bB5cK8a9P6hbytfDOgqsMJErC7vyWRw87VUERR5X0VJDiGc2h/IocljL+rr3Klfpv9pg9xttsLOrVIcfDtltEQOtcP0CFZg/wGvmjysyvQ8VmP8ChTa3McThBiZya8NEbm3YSUYXFNrcRgXmv8Ay2jOUp0tMd9gdidWHFsiuH2QQCqUOuFwuSXY5ZT1a6dyullkNEiKMLky6NaYTeX2JrRXILqcslIkDk2GFYyP6lSE27oGPzHiKVTiJZdV+qf2dh50mJPRo6Jby9bBLycvRSpcCeNLpe7SEovw7Aw+/MpDBUx5XsNqAbHgp2buzc4KutDp4dHGXEVq3xh02fbwFq2Htg5WuQljlcwFWLOqAJ97p7hOYPewTmD2EQuu76Emn67DauxmtdEawap8ceH5TNFofznxQs5XQBstJTGISk1AX/wUPVWOeSpK50AAAAABJRU5ErkJggg==",
- "title": "Amazon",
- "type": "affiliate",
- "url": "https://www.amazon.com/"
- }
- ]
-}
diff --git a/application/basilisk/base/content/newtab/customize.js b/application/basilisk/base/content/newtab/customize.js
index 39724fa91..bc4903f6c 100644
--- a/application/basilisk/base/content/newtab/customize.js
+++ b/application/basilisk/base/content/newtab/customize.js
@@ -9,7 +9,6 @@ var gCustomize = {
"blank",
"button",
"classic",
- "enhanced",
"panel",
"overlay",
"learn"
@@ -83,13 +82,10 @@ var gCustomize = {
}
switch (event.currentTarget.id) {
case "newtab-customize-blank":
- sendAsyncMessage("NewTab:Customize", {enabled: false, enhanced: false});
+ sendAsyncMessage("NewTab:Customize", {enabled: false});
break;
case "newtab-customize-classic":
- sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: false});
- break;
- case "newtab-customize-enhanced":
- sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: !gAllPages.enhanced});
+ sendAsyncMessage("NewTab:Customize", {enabled: true});
break;
case "newtab-customize-learn":
this.showLearn();
diff --git a/application/basilisk/base/content/newtab/grid.js b/application/basilisk/base/content/newtab/grid.js
index b6f98fa17..726150a6c 100644
--- a/application/basilisk/base/content/newtab/grid.js
+++ b/application/basilisk/base/content/newtab/grid.js
@@ -9,7 +9,6 @@
*/
const GRID_BOTTOM_EXTRA = 7; // title's line-height extends 7px past the margin
const GRID_WIDTH_EXTRA = 1; // provide 1px buffer to allow for rounding error
-const SPONSORED_TAG_BUFFER = 2; // 2px buffer to clip off top of sponsored tag
/**
* This singleton represents the grid that contains all sites.
@@ -142,13 +141,9 @@ var gGrid = {
// Create sites.
let numLinks = Math.min(links.length, cells.length);
- let hasHistoryTiles = false;
for (let i = 0; i < numLinks; i++) {
if (links[i]) {
this.createSite(links[i], cells[i]);
- if (links[i].type == "history") {
- hasHistoryTiles = true;
- }
}
}
@@ -157,9 +152,6 @@ var gGrid = {
this._gridDefaultContent.nextSibling.remove();
}
this._node.appendChild(fragment);
-
- document.getElementById("topsites-heading").textContent =
- hasHistoryTiles ? "Your Top Sites" : "Top Sites";
},
/**
@@ -182,18 +174,15 @@ var gGrid = {
// Create the site's inner HTML code.
site.innerHTML =
- '<span class="newtab-sponsored">' + newTabString("sponsored.button") + '</span>' +
'<a class="newtab-link">' +
' <span class="newtab-thumbnail placeholder"/>' +
' <span class="newtab-thumbnail thumbnail"/>' +
- ' <span class="newtab-thumbnail enhanced-content"/>' +
' <span class="newtab-title"/>' +
'</a>' +
'<input type="button" title="' + newTabString("pin") + '"' +
' class="newtab-control newtab-control-pin"/>' +
'<input type="button" title="' + newTabString("block") + '"' +
- ' class="newtab-control newtab-control-block"/>' +
- '<span class="newtab-suggested"/>';
+ ' class="newtab-control newtab-control-block"/>';
this._siteFragment = document.createDocumentFragment();
this._siteFragment.appendChild(site);
@@ -274,6 +263,6 @@ var gGrid = {
this._node.style.maxWidth = gGridPrefs.gridColumns * this._cellWidth +
GRID_WIDTH_EXTRA + "px";
this._node.style.height = this._computeHeight() + "px";
- this._node.style.maxHeight = this._computeHeight(gridRows) - SPONSORED_TAG_BUFFER + "px";
+ this._node.style.maxHeight = this._computeHeight(gridRows) + "px";
}
};
diff --git a/application/basilisk/base/content/newtab/newTab.css b/application/basilisk/base/content/newtab/newTab.css
index 658ad2ed3..64b3ed7ef 100644
--- a/application/basilisk/base/content/newtab/newTab.css
+++ b/application/basilisk/base/content/newtab/newTab.css
@@ -122,10 +122,6 @@ input[type=button] {
pointer-events: none;
}
-body:not(.compact) #topsites-heading {
- display: none;
-}
-
/*
* If you change the sizes here, make sure you
* change the preferences:
@@ -140,12 +136,6 @@ body:not(.compact) #topsites-heading {
width: 290px;
}
-body.compact .newtab-cell {
- width: 110px;
- height: 110px;
- margin: 12px;
-}
-
/* SITES */
.newtab-site {
position: relative;
@@ -175,16 +165,13 @@ body.compact .newtab-cell {
}
/* TITLES */
-.newtab-sponsored,
-.newtab-title,
-.newtab-suggested {
+.newtab-title {
overflow: hidden;
position: absolute;
right: 0;
text-align: center;
}
-.newtab-sponsored,
.newtab-title {
bottom: 0;
white-space: nowrap;
@@ -192,103 +179,11 @@ body.compact .newtab-cell {
vertical-align: middle;
}
-.newtab-suggested {
- border: 1px solid transparent;
- border-radius: 2px;
- font-size: 12px;
- height: 17px;
- line-height: 17px;
- margin-bottom: -1px;
- padding: 2px 8px;
- display: none;
- margin-left: auto;
- margin-right: auto;
- left: 0;
- top: 215px;
- -moz-user-select: none;
-}
-
-.newtab-suggested-bounds {
- max-height: 34px; /* 34 / 17 = 2 lines maximum */
-}
-
.newtab-title {
left: 0;
padding: 0 4px;
}
-.newtab-sponsored {
- background-color: #FFFFFF;
- border: 1px solid #E2E2E2;
- border-radius: 3px;
- color: #4A4A4A;
- cursor: pointer;
- display: none;
- font-family: Arial;
- font-size: 9px;
- height: 17px;
- left: 0;
- line-height: 6px;
- padding: 4px;
- right: auto;
- top: -15px;
-}
-
-.newtab-site[suggested=true] > .newtab-sponsored {
- background-color: #E2E2E2;
- border: none;
-}
-
-.newtab-site > .newtab-sponsored:-moz-any(:hover, [active]) {
- background-color: #4A90E2;
- border: 0;
- color: white;
-}
-
-.newtab-site > .newtab-sponsored[active] {
- background-color: #000000;
-}
-
-.newtab-sponsored:dir(rtl) {
- right: 0;
- left: auto;
-}
-
-.newtab-site:-moz-any([type=enhanced], [type=sponsored], [suggested]) .newtab-sponsored {
- display: block;
-}
-
-.newtab-site[suggested] .newtab-suggested {
- display: table;
-}
-
-.sponsored-explain,
-.sponsored-explain a,
-.suggested-explain,
-.suggested-explain a {
- color: white;
-}
-
-.sponsored-explain,
-.suggested-explain {
- background-color: rgba(51, 51, 51, 0.95);
- bottom: 30px;
- line-height: 20px;
- padding: 15px 10px;
- position: absolute;
- text-align: start;
-}
-
-.sponsored-explain input,
-.suggested-explain input {
- background-size: 18px;
- height: 18px;
- opacity: 1;
- pointer-events: none;
- position: static;
- width: 18px;
-}
-
/* CONTROLS */
.newtab-control {
position: absolute;
@@ -333,11 +228,6 @@ body.compact .newtab-cell {
margin: 40px 0 15px;
}
-body.compact #newtab-search-container {
- margin-top: 0;
- margin-bottom: 80px;
-}
-
#newtab-search-container[page-disabled] {
opacity: 0;
pointer-events: none;
diff --git a/application/basilisk/base/content/newtab/newTab.inadjacent.json b/application/basilisk/base/content/newtab/newTab.inadjacent.json
deleted file mode 100644
index 53fb542af..000000000
--- a/application/basilisk/base/content/newtab/newTab.inadjacent.json
+++ /dev/null
@@ -1,3209 +0,0 @@
-{
- "domains": [
- "rp5slFCxq/e7hYhXJCd0vQ==",
- "2rEimAJDNX5g8HPZehOrGg==",
- "nvLEpj6ZZF3LWH3wUB6lKg==",
- "9Cqd4Lm3VvXuJxz79Bbqyg==",
- "vNRy4LR+7TOKTixqsr5ybw==",
- "N4zSgsZCo6Z4XRwZ4fu8WQ==",
- "jsDtRfVbMsFg3KkEl2UiZQ==",
- "TckkKpiq0a6J6NTw7uOZqw==",
- "9Or7IAYuuIgZA370w9rNIg==",
- "ul8WvOjCkxTz9LjT4RqTHg==",
- "ZGJrbwb5878Nsqm0z+A7nQ==",
- "5iT64HTeeG5SIFXG7A9o3w==",
- "YSeSEghPe1kV6g8ghFcNAA==",
- "0jIUl1NDmJZQkDY12VDeIQ==",
- "aos6UyDyIw0R1nTK5wTawA==",
- "G1xxubsq65ugK06UT2DO5A==",
- "lbhavoDrDPP/8m0onwo63w==",
- "ObcLsjW0SkdvY0nkZmiTGQ==",
- "FHZ5084LC0nTAzZlnSKN3Q==",
- "cdEr+0Fv5iaVZzalZToseg==",
- "Co8WbNYbCPTFPcHpeK3hRQ==",
- "qXSzhCEhByLQq9N84tqV+Q==",
- "h3ufhRk5IEFaNH11rIACtQ==",
- "fQ1PJ/JwazIaYoy/zy49QQ==",
- "zAJqfbn54Nsm2ddGtkb59A==",
- "ixPM9T8ik/gWGZ7BRIcaig==",
- "/E9pwA3E3hVAZoYq3FmCyw==",
- "U6ygonI8CxpruhpGB2+Q6A==",
- "Igi4voB8oVMVw6WUeDSjZg==",
- "jtuHIJhwoTGzavFpM7ilNw==",
- "eBvTV27n6Gs+ZsBkpVynvw==",
- "sFbzw0AUOGG0NEzkaSxVDg==",
- "yAkIS+Ezj6woEff9YvdO7Q==",
- "IP1+BwG6q60QzDADi8j7oA==",
- "Q/teQEBFepHtwZ7UHa2TEA==",
- "B1vDep5a1Gok5Gnth39+LA==",
- "cyEIyQ2MZaPGf+K1x9Bbkg==",
- "aaM+oEJnF4/nwMWyXJU8rA==",
- "qpDNIpxah8FUiqXm5IRaUg==",
- "ZTeJ35gMPqIv2WWbeNyIEg==",
- "nzoAGQAnC/Xgg5PmOgXqkA==",
- "J5pJDuNi3cqQiyaRJAJk4g==",
- "2vqN53BXhXzPrKYsh6QH1A==",
- "QlrzHNYxCwCBMVENvbXjQA==",
- "Ou2HGn43nmsL3RWSNvMdXw==",
- "3qk9lsvGTMqVMAZW+xihfw==",
- "RncMe42RB2bhmUbYtGVnKQ==",
- "hzNXR6dqPq1+vf4Qh5ByWA==",
- "sRq3S2ZRs3H39cEQHv4Vig==",
- "B4ThUBTVJOUPyOsHxikHXA==",
- "A2lU9GkAdSibLO1JJfFnIA==",
- "ef3HNkSvuWQrAzkuty2iqg==",
- "yKDiRM6bf2xc0QXIwHYuaA==",
- "AdCk4ccJuhA0bIT/61J+RQ==",
- "UXvAZ7ULCVz2f505K0Wkvg==",
- "ueKWblrOwVJNgiOvkXKLBQ==",
- "s8u/jPuBAxu1d18HfV5Z0g==",
- "hUT0Uc5YMUdNZQEGLz4hJw==",
- "6jo/phmMTrEXKrNRsionGQ==",
- "s/Ea/3fkyJ9honzPJkgEQQ==",
- "hgu2/Jf+WrQAHfO+asW2zw==",
- "kiVuTNwZ1r2lqYEZxIHyiQ==",
- "24T5KVrVE2mYwJ5Goj3xJw==",
- "fiWBVlfj97GGjEvf/Q9Spg==",
- "5VWdlvJe7eoXMGkTtHzCUg==",
- "+cFQxKa5RWVtc1z00Jujew==",
- "nVa+rLH5p+yXBksLwQsjRQ==",
- "5tyI6bMdb3tMIi4ewvr/SQ==",
- "S6Roj31yS5bZbSFcd3f4Hg==",
- "uW1Zl8iuEF8ZT/gwCBEqwA==",
- "YwL+FJgxlZ8JVig+9iP5Cw==",
- "ThIYK/mQsp9cMf8+rws/4Q==",
- "w0oSxOhRG6kE9B868aoYVQ==",
- "DJUDGQ0J32dF1kfItyxALg==",
- "34/ab69lPkuAKt6WBxJPpA==",
- "25jH4C9apgqWZGZP15lM6Q==",
- "GxvwleSaSwILD1pG9k9buA==",
- "YRAMt2ArEINo83ms6AqJ0A==",
- "15HyTJNoMYzi3XCkeU5Z7A==",
- "/SqjXGD+TKC90uz1vsjqUw==",
- "karhKOknkhtg/LSFo9BGRA==",
- "+tD1d0t3vfJvc1hUAvTT4Q==",
- "rkaKbtlnyVr53D0rexLqdQ==",
- "fAugw4rtnXzzRXfC1wRgOQ==",
- "RgxoepF/XOwIsGat5r5HpQ==",
- "Y49/EnzVz3ugXCYxFjFN7g==",
- "tHMyzBm/2wNDw7TeNeujbg==",
- "LlqzYV4uZpiJy4ORWPSekA==",
- "M3Huar7/ded9OGgDwJhZgw==",
- "QkNNATSx/PJ1XjgZyTtkUQ==",
- "skVw0v6Wx00sfHAScPK1Bw==",
- "v1gsIvg+C68T9wixMzL2sQ==",
- "hDL75EXhl7BaYnAxkoGwbw==",
- "tReG97snx2ESpXbfllCL7Q==",
- "EiZBXR15dT1TMrkgkzmkvw==",
- "5hRHirfD90/sdp0ILJQU8A==",
- "rabElvtYtG0jW6dxAOHofg==",
- "JpxoTRKWN+SEeBQ453R1YQ==",
- "Faz4Lm0cpjvF0IjVkHiZMg==",
- "jGErFAIoXx+50KFpVIGZiA==",
- "5GzBkduKpUX7u1uwtYIFug==",
- "cRBe0J9/KWRX19N2vPkCiw==",
- "t/7g8t4Kr3/+SCnOn3XFWQ==",
- "sd08c6jUXs5/hxND0fBkPA==",
- "nTxKpqIdnHNdpDk7Dx3TEg==",
- "5l+RALcce+lTDnmXI+Wqqg==",
- "pzJ4QmEBGRNiiX6z0xHh8g==",
- "Vfl3YbqR6JRR7SIdsUA/vA==",
- "cgfhOdB376a4GAcuACADvA==",
- "inAefsQM6tiIhQCMtcPcyA==",
- "FTSULGL8CMhmcc7Cyf/X8A==",
- "9XSWpaZyHEy7V/tuw5uZEw==",
- "+VtM1opKlgb/jrCwc4YjFA==",
- "oF46xheuI/NUxUOnOttzvA==",
- "Qy+lvhDbJCumr6kiPLd1oA==",
- "swps7UEKpIbVBJ9SnPK3zQ==",
- "b7wyIiJvJs+29QePxsdWtQ==",
- "x3iDZxYyuHtG/9rNW5HMYg==",
- "r1dx1g5UOksywvOaQTamfA==",
- "KvVF3Si/fr4JQtr7jCJiog==",
- "spvZ7hhtG5QY7JXs96lBUg==",
- "ECL8mA5B6CswyDH6yJ4hVw==",
- "7Uu+YsdS69dMSDYUr6vTag==",
- "Rnm9pSvQRRbkHpOijraLZw==",
- "aQJqpnXdzqNSFhMn3EJA2Q==",
- "TctnXpd7Wd5ZXKMnOFHAQA==",
- "+lPqG8l6mf2FWVGWflyF/g==",
- "mPmnmL2oRRJmKYjQ6TfN3g==",
- "fyXFcT5ZCawDBg74n1WSpg==",
- "uq5Zrxq10pO1HoPxReT5og==",
- "3eoCsOKXY8RDrHSdlXqmrA==",
- "9nQv2BFG56xsHViN5UpHYw==",
- "RtP/nJgy/ItyuDrpBbAotg==",
- "5E/drRptfHmBhJ7qplujGg==",
- "cUxyZvoqXbQ0a/0I9s6Zbg==",
- "womzqSigwEF30V422YmxKw==",
- "FPvZqDfN8dTFHLVOuYEbUA==",
- "YZMXx+scKXp/v9GaJjb1bA==",
- "bjURu5MRsNIZavG5HV0eZw==",
- "iY0C9uSMEOn8ikT+J7+/Eg==",
- "aXkD6BzsdkMEv7A+eYqQQQ==",
- "dOcOfEDGHYG2kgmrglDkPw==",
- "c7GjtY05Mh+cp6SNuWY3Ig==",
- "lM1uY1oVncHXNzKs/cCEtQ==",
- "7jXnQJkutLsi+r9aYmrMxw==",
- "NgrugWWduj2qdWnEQf9dLA==",
- "faYjmy/yn5iXdS28QCIdWw==",
- "68XbaOvIZpCGb4G1gaKErA==",
- "Yi67HkOLtGYXeL7WD4GPrA==",
- "Puo8gXuUkwcoQViaXwkdSQ==",
- "L202Et5aZh60Vl20LTKNFg==",
- "4agAzQ5+dnTmLZEjsZs26g==",
- "LegGM1ft8Y7Ka3CUxpObvg==",
- "KRdILc1QDOpow5im/qY+Kw==",
- "peMW+rpwmXrSwplVuB/gTA==",
- "Pic1ncr+Zn6wv75zjAdzQA==",
- "ilSPlWYbiPzIC13vQUBlOw==",
- "GUlDufLoTalBqrG/h3mZ6w==",
- "5twANNlT57T9BG4r2D9+Hw==",
- "ENrnM8HlMi+5y8Hsu4Pn4A==",
- "K/DzpLEbz1MpRjA6qyYn4Q==",
- "yN1cHJRHDXoFxFZacL6wsw==",
- "Rc6r+KqIePH+dnj1aNYCsQ==",
- "8u/z5htgqXVU5Dqwd9whJQ==",
- "jV575O42EYoqDNxCm9643Q==",
- "xCxGo0h3lS8N6X+ivKfpjA==",
- "us+2nfpj2gjI7s14Hw0gmA==",
- "bp90A/rbESwVU7eh9xRTfQ==",
- "5QtMXzbTafvKDQOWZP7M8w==",
- "1gFCxPLjQlQGKmSGmHwmJQ==",
- "m+/dnOIe6SaIFhfvg+ybDg==",
- "9Dcg87+RPq9U+swRg4dH3Q==",
- "mnjbL7WFmrWp0RUqS8AMGA==",
- "/0e0E+NFmq8GeE5+y2Gekw==",
- "y11mbpHHtka9Ep8cr2nEvQ==",
- "GdmjRyliw+W21Q+dHO4CWA==",
- "X65wWQTpkg756V/Nfn92kQ==",
- "xj06KvacQOxRSofbhzBNgA==",
- "nVDxVhaa2o38gd1XJgE3aw==",
- "4IV+JOGXrltpkQamBRXMgA==",
- "jIfp8LqaYXT88r/K3a8gNw==",
- "vhT4dDtbMFVyevS6yCGy0g==",
- "zMs7/x8hDt8xj2FFc5+6vA==",
- "1J7u2N62JGb2VrnCRlJIrw==",
- "3hJs9P/RRxB0CO4q0Icb+g==",
- "ZpuVY1ZyoKD3hqosdsfT6Q==",
- "6KIM7C7eWgxZtqZboiJvZQ==",
- "vtb6fdqirkuUkqITAmXTlw==",
- "C/rEVr22mw2u/1dwUx9VTg==",
- "NrY4Q5C67haCWLK8HXHq9g==",
- "X9qvEftCEFWX3gBU5hXy+Q==",
- "0zgw7xNB3xVGaH48TyxaNQ==",
- "g7J9Jy/PJrAGRgVdvA+bEg==",
- "9zb+anAyZVBzuU9rW4cJtg==",
- "6Zc5FzT/m0YIjxEPYA6zDQ==",
- "R2YPNlvCbVK0EodTR7czIw==",
- "gsI6EGgXMtDu+1u364A8mw==",
- "Bg2wBFb1/xaxeEiHfBHX+A==",
- "64aapfVI6dV3LpTK56KZlg==",
- "HdgcJU0W3yVnH69VYStmug==",
- "qTDCcv+LK3JPFB/++t66IQ==",
- "P0HEIXMnAmbvq+QYREwFzw==",
- "aaU7CAmtyE35jNKTkyXOkg==",
- "r9G97WKDiQ48qJHP9LBRNg==",
- "8mPgQhYVDn8KshDDvvf5SA==",
- "GCQiiOLDguXLiYwuLcFPsA==",
- "R2Use39If2C0FVBP7KDerA==",
- "23C4eh3yBb5n/RNZeTyJkA==",
- "2QQtKtBAm2AjJ5c0WQ6BQA==",
- "Qc+XYy2qyWJ5VVwd2PExbw==",
- "zJ7ScHNxr2leCDNNcuDApA==",
- "vFtC0B2oe1gck28JOM1dyg==",
- "bLEntCrCHFy9pg3T3gbBzg==",
- "G3PmmPGHaWHpPW30xQgm3Q==",
- "me61ST+JrXM5k3/a11gRAA==",
- "+LJYVZl1iPrdMU3L5+nxZw==",
- "CLPzjXKGGpJ0VrkSJp7wPQ==",
- "Pc+u0MAzp4lndTz4m6oQ5w==",
- "cwBNvZc0u4bGABo88YUsVQ==",
- "q7m/EtZySBjZNBjQ5m1hKw==",
- "8ZBiwr842ZMKphlqmNngHw==",
- "LMCZqd3UoF/kHHwzTdj7Tw==",
- "0ODJyWKJSfObo+FNdRQkkA==",
- "ViweSJuNWbx5Lc49ETEs/A==",
- "x+8rwkqKCv0juoT5m1A4eg==",
- "pxuSWn1u+bHtRjyh2Z8veA==",
- "GKzs8mlnQQc58CyOBTlfIg==",
- "Owg8qCpjZa+PmbhZew6/sw==",
- "YLz+HA6qIneP+4naavq44Q==",
- "9ajIS45NTicqRANzRhDWFA==",
- "DjeSrUoWW2QAZOAybeLGJg==",
- "qxALQrqHoDq9d91nU0DckA==",
- "yPIeWcW8+3HjDagegrN8bw==",
- "ocpLRASvTgqfkY20YlVFHQ==",
- "RuLeQHP1wHsxhdmYMcgtrQ==",
- "3WwITQML938W9+MUM56a3A==",
- "ZbLVNTQSVZQWTNgC4ZGfQg==",
- "X6Ln4si8G5aKar52ZH/FEQ==",
- "+gbitI/gpxebN/rK7qj8Fw==",
- "7cnUHeaPO8txZGGWHL9tKg==",
- "epY+dsm5EMoXnZCnO4WSHw==",
- "nf8x+F03kOpMhsCSUWEhVg==",
- "VE4sLM5bKlLdk85sslxiLQ==",
- "Hs3vUOOs2TWQdQZHs+FaQQ==",
- "hkOBNoHbno2iNR7t3/d4vg==",
- "Ar9N1VYgE7riwmcrM3bA2Q==",
- "SbMjjI8/P8B9a9H2G0wHEQ==",
- "tU31r8zla146sqczdKXufg==",
- "tFmWYH82I3zb+ymk5dhepA==",
- "XHjrTLXkm/bBY/BewmJcCQ==",
- "FV/D5uSco+Iz8L+5t7E8SA==",
- "yKLLiqzxfrCsr6+Rm6kx1Q==",
- "B6reUwMkQFaCHb9BYZExpw==",
- "5jyuDp82Fux+B0+zlx8EXw==",
- "WGKFTWJac8uehn3N59yHJw==",
- "JQf9UmutPh3tAnu7FDk3nA==",
- "hv5GrLEIjPb4bGOi8RSO0w==",
- "p3V7NfveB6cNxFW7+XQNeQ==",
- "DinJuuBX9OKsK5fUtcaTcQ==",
- "UEMwF4kwgIGxGT4jrBhMPQ==",
- "Y78dviyBS3Jq9zoRD5sZtQ==",
- "zbjXhZaeyMfdTb2zxvmRMg==",
- "kydoXVaNcx1peR5g6i588g==",
- "M2suCoFHJ5fh9oKEpUG3xA==",
- "/VnKh/NDv7y/bfO6CWsLaQ==",
- "S+b37XhKRm8cDwRb1gSsKQ==",
- "jz7QlwxCIzysP39Cgro8jg==",
- "IjmLaf3stWDAwvjzNbJpQA==",
- "cHSj5dpQ04h/WyefjABfmQ==",
- "+gO0bg8LY+py2dLM1sM7Ag==",
- "fSANOaHD0Koaqg7AoieY9A==",
- "vqYHQ3MnHrAIAr1QHwfIag==",
- "Uh1mvZNGehK1AaI4a1auKQ==",
- "HCbHUfsTDl6+bxPjT57lrA==",
- "S7Vjy/gOWp0HozPP1RUOZw==",
- "KPh6TwYpspne4KZA6NyMbw==",
- "cfh5VZFmIqJH/bKboDvtlA==",
- "H1zH9I8RwfEy5DGz3z+dHw==",
- "2ksediOVrh4asSBxKcudTg==",
- "+jVN/3ASc2O44sX6ab8/cg==",
- "uvKYnKE01D5r7kR9UQyo5A==",
- "BB9PTlwKAWkExt3kKC/Wog==",
- "yqQPU4jT9XvRABZgNQXjgg==",
- "6v3eTZtPYBfKFSjfOo2UaA==",
- "49z/15Nx9Og7dN9ebVqIzg==",
- "VjclDY8HN4fSpB263jsEiQ==",
- "vSKsa0JhLCe9QFZKkcj58Q==",
- "PolhKCedOsplEcaX4hQ0YQ==",
- "D0Qt9sRlMaPnOv1xaq+XUg==",
- "gBgJF0PiGEfcUnXF0RO7/w==",
- "sC11Rf/mau3FG5SnON4+vQ==",
- "rKb3TBM4EPx/RErFOFVCnQ==",
- "+n0K7OB2ItzhySZ4rhUrMg==",
- "Epm0d/DvXkOFeM4hoPCBrg==",
- "K8PVQhEJCEH1ghwOdztjRw==",
- "xjA21QjNdThLW3VV7SCnrg==",
- "nE72uQToQFVLOzcu/nMjww==",
- "2Hc5oyl0AYRy2VzcDKy+VA==",
- "Y7XpxIwsGK3Lm/7jX/rRmg==",
- "MK7AqlJIGqK2+K5mCvMXRQ==",
- "mXycPfF5zOvcj1p4hnikWw==",
- "V1fvtnJ0L3sluj9nI5KzRw==",
- "TahqPgS7kEg+y6Df0HBASw==",
- "EKU3OVlT4b/8j3MTBqpMNg==",
- "EdvIAKdRAXj7e42mMlFOGQ==",
- "uPm+cF4Jq08S5pQhYFjU8A==",
- "CnIwpRVC2URVfoiymnsdYQ==",
- "wyx5mnUMgP5wjykjAfTO7w==",
- "OwIGvTh8FPFqa4ijNkguAw==",
- "4ID0PHTzIMZz2rQqDGBVfA==",
- "rlXt6zKE7DswUl0oWGOQUQ==",
- "4NP8EFFJyPcuQKnBSxzKgQ==",
- "bJgsuw29cO2WozqsGZxl7w==",
- "b3q8kjHJPj9DWrz3yNgwjQ==",
- "QGYFMpkv37CS2wmyp42ppg==",
- "Kzs+/IZJO8v4uIv9mlyJ2Q==",
- "ZJY+hujfd58mTKTdsmHoQQ==",
- "R8FxgXWKBpEVbnl41+tWEw==",
- "+CvLiih/gf2ugXAF+LgWqw==",
- "BDbfe/xa9Mz1lVD82ZYRGA==",
- "Dz90OhYEjpaJ/pxwg1Qxhg==",
- "MLHt6Ak288G0RGhCVaOeqA==",
- "r0QffVKB9OD9yGsOtqzlhA==",
- "hK8KhTFcR06onlIJjTji/Q==",
- "wMum67lfk5E1ohUObJgrOg==",
- "JKmZqz9cUnj6eTsWnFaB0A==",
- "rtJdfki8fG6CB36CADp0QA==",
- "cUyqCa7Oue934riyC17F8g==",
- "y4Y4mSSTw/WrIdRpktc5Hw==",
- "r36kVMpF+9J+sfI3GeGqow==",
- "ydVj2odhergi+2zGUwK4/A==",
- "J2NFyb8cXEpZyxWDthYQiA==",
- "qYuo5vY8V3tZx41Kh9/4Dw==",
- "jrfRznO0nAz6tZM1mHOKIA==",
- "JSr/lqDej81xqUvd/O2s7w==",
- "vHGjRRSlZHJIliCwIkCAmQ==",
- "sQAxqWXeiu/Su0pnnXgI9A==",
- "xPe76nHyHmald6kmMQsKdg==",
- "50jASqzGm4VyHJbFv8qVRA==",
- "uuiJ+yB7JLDh2ulthM0mjg==",
- "TI90EuS/bHq/CAlX32UFXg==",
- "JgxNrUlL8wutG04ogKFPvw==",
- "aMa1yVA71/w6Uf1Szc9rMA==",
- "k/Aou2Jmyh8Bu3k8/+ndsQ==",
- "iANKiuMqWzrHSk9nbPe3bQ==",
- "7GgNLBppgAKcgJCDSsRqOQ==",
- "bzVeU2qM9zHuzf7cVIsSZw==",
- "rkeLYwMZ1/pW2EmIibALfA==",
- "91+Yms6Oy/rP0rVjha5z9w==",
- "JgXSPXDqaS1G9NqmJXZG0A==",
- "ZzduJxTnXLD9EPKMn1LI4Q==",
- "6W79FmpUN1ByNtv5IEXY4w==",
- "Y1Nm3omeWX2MXaCjDDYnWQ==",
- "ejfikwrSPMqEHjZAk3DMkA==",
- "WNfDNaWUOqABQ6c6kR+eyw==",
- "4BkqgraeXY7yaI1FE07Evw==",
- "AjHz9GkRTFPjrqBokCDzFw==",
- "T/6gSz2HwWJDFIVrmcm8Ug==",
- "VWy9lB5t4fNCp4O/4n8S4w==",
- "/FdZzSprPnNDPwbhV1C0Cg==",
- "LUWxfy4lfgB5wUrqCOUisw==",
- "r1VGXWeqGeGbfKjigaAS+Q==",
- "ztULoqHvCOE6qV7ocqa4/w==",
- "QCpzCTReHxGm5lcLsgwPCA==",
- "Hst3yfyTB7yBUinvVzYROQ==",
- "gf1Ypna/Tt+TZ08Y+GcvGg==",
- "3rbml1D0gfXnwOs5jRZ3gA==",
- "2vm7g3rk1ACJOTCXkLB3zA==",
- "11FE2kknwYi2Qu0JUKMn3A==",
- "1b2uf+CdVjufqiVpUShvHw==",
- "0a4SafpDIe8V4FlFWYkMHw==",
- "7btpMFgeGkUsiTtsmNxGQA==",
- "dUx1REyXKiDFAABooqrKEA==",
- "knYKU74onR6NkGVjQLezZg==",
- "Scto+9TWxj1eZgvNKo+a9A==",
- "cvZT1pvNbIL8TWg+SoTZdA==",
- "1nXByug2eKq0kR3H3VjnWQ==",
- "tG+rpfJBXlyGXxTmkceiKA==",
- "7W9aF7dxnL+E8lbS/F7brg==",
- "8vr+ERVrM99dp+IGnCWDGQ==",
- "oFNMOKbQXcydxnp8fUNOHw==",
- "uJZGw3IY2nCcdVeWW1geNQ==",
- "q6LG0VzO1oxiogAAU63hyg==",
- "f0H/AFSx2KLZi9kVx5BAZg==",
- "1RQZ2pWSxT+RKyhBigtSFg==",
- "scCQPl0em2Zmv/RQYar60g==",
- "A2ODff+ImIkreJtDPUVrlg==",
- "vRgkZZGVN7YZrlml0vxrKA==",
- "68jPYo3znYoU4uWI7FH3/g==",
- "iJ2nT8w8LuK11IXYqBK+YA==",
- "54XELlPm8gBvx8D5bN3aUg==",
- "PTAm/jGkie7OlgVOvPKpaA==",
- "v7BrkRmK0FfWSHunTRHQFQ==",
- "dVh/XMTUIx1nYN4q1iH1bA==",
- "TSGL3iQYUgVg/O9SBKP9EA==",
- "wTO49YX/ePHMWtcoxUAHpw==",
- "bMb1ia0rElr2ZpZVhva0Jw==",
- "sNmW2b2Ud7dZi3qOF8O8EQ==",
- "3djRJvkZk9O2bZeUTe+7xQ==",
- "I9KNZC1tijiG1T72C4cVqQ==",
- "sQzCwNDlRsSH7iB9cTbBcg==",
- "mk1CKDah7EzDJEdhL22B7w==",
- "lON3WM0uMJ30F8poBMvAjQ==",
- "88PNi9+yn3Bp4/upgxtWGA==",
- "C+Ssp+v1r+00+qiTy2d7kA==",
- "11U5XEwfMI7avx014LfC8g==",
- "xsf0m31Am0W9eLhopAkfnA==",
- "d13Rj3NJdcat0K/kxlHLFw==",
- "UP7NXAE0uxHRXUAWPhto0w==",
- "ZKXxq9yr7NGBOHidht34uQ==",
- "Fd2fYFs8vtjws2kx1gf6Rw==",
- "ojf6uL85EuEYgLvHoGhUrw==",
- "KjnL3x+56r3M2pDj1pPihA==",
- "WdCWezJU4JK43EOZ9YHVdg==",
- "/jH6imhTPZ/tHI4gYz2+HA==",
- "+OLntmlsMBBYPREPnS6iVw==",
- "5lfLJAk1L3QzGMML3fOuSw==",
- "AZs3v4KJYxdi8T1gjVjI2Q==",
- "7pkUY2UzSbGnwLvyRrbxfA==",
- "BjfOelfc1IBgmUxMJFjlbQ==",
- "TcGhAJHRr7eMwGeFgpFBhg==",
- "Y7iDCWYrO1coopM3RZWIPg==",
- "mnalaO6xJucSiZ0+99r3Cg==",
- "plXHHzA8X9QGwWzlJxhLRw==",
- "Zqd6+81TwYuiIgLrToFOTQ==",
- "1Pmnur6TbZ9cmemvu0+dSA==",
- "OaNpzwshdHUZMphQXa6i8w==",
- "WKehT4nGF2T7aKuzABDMlA==",
- "4LvQSicqsgxQFWauqlcEjw==",
- "BMZB1FwvAuEqyrd0rZrEzw==",
- "YfbfE3WyYOW7083Y8sGfwQ==",
- "46FCwqh+eMkf+czjhjworw==",
- "734u4Y1R3u7UNUnD+wWUoA==",
- "yf06Slv9l3IZEjVqvxP2aA==",
- "bIk7Fa6SW7X18hfDjTKowg==",
- "DnF6TYSJxlc+cwdfevLYng==",
- "ionqS0piAOY2LeSReAz4zg==",
- "hlMumZ7RJFpILuKs09ABtw==",
- "NjeDgQ1nzH1XGRnLNqCmSg==",
- "o7y4zQXQAryST2cak4gVbw==",
- "29EybnMEO95Ng4l/qK4NWQ==",
- "udU65VtsvJspYmamiOsgXw==",
- "v1AWe5qb5y3vSKFb7ADeEw==",
- "wK6Srd83eLigZ11Q20XGrg==",
- "GmC+0rNDMIR+YbUudoNUXw==",
- "W4utAK3ws0zjiba/3i91YA==",
- "MlKWxeEh8404vXenBLq4bw==",
- "Gdf4VEDLBrKJNQ8qzDsIyw==",
- "Z9bDWIgcq6XwMoU2ECDR5Q==",
- "VIkS30v268x+M1GCcq/A8A==",
- "iPwX3SbbG9ez9HoHsrHbKw==",
- "yKrsKX4/1B1C0TyvciNz5w==",
- "BophnnMszW5o+ywgb+3Qbw==",
- "eJLrGwPRa6NgWiOrw1pA7w==",
- "eV+RwWPiGEB+76bqvw+hbA==",
- "oad5SwflzN0vfNcyEyF4EA==",
- "Uw6Iw+TP9ZdZGm2b/DAmkg==",
- "9qWLbRLXWIBJUXYjYhY2pg==",
- "dxWv00FN/2Cgmgq9U3NVDQ==",
- "AX1HxQKXD12Yv5HWi39aPQ==",
- "J0NauydfKsACUUEpMhQg8A==",
- "mxug34EekabLz0JynutfBg==",
- "bNq/hj0Cjt4lkLQeVxDVdQ==",
- "nW3zZshjZEoM8KVJoVfnuQ==",
- "ghp8sWGKWw20S/z1tbTxFg==",
- "S4rFuiKLFKZ+cL7ldiTwpg==",
- "8ZqmPJDnQSOFXvNMRQYG2Q==",
- "6XYqR2WvDzx4fWO7BIOTjA==",
- "Uo+FIhw1mfjF6/M8cE1c/Q==",
- "bsHIShcLS134C+dTxFQHyA==",
- "19yQHaBemtlgo2QkU5M6jQ==",
- "sWLcS+m4aWk31BiBF+vfJQ==",
- "BlCgDd7EYDIqnoAiKOXX6Q==",
- "MrxR3cJaDHp0t3jQNThEyg==",
- "cMo6l1EQESx1rIo+R4Vogg==",
- "VOvrzqiZ1EHw+ZzzTWtpsw==",
- "1/ZheMsbojazxt31j/l3iA==",
- "0QxPAqRF8inBuFEEzNmLjA==",
- "UXUNYEOffgW3AdBs7zTMFA==",
- "lOPJhHqCtMRFZfWMX/vFZQ==",
- "rXSbbRABEf4Ymtda45w8Fw==",
- "jfegbZSZWkDoPulFomVntA==",
- "hfcH5Az2M7rp+EjtVpPwsg==",
- "VsXEBIaMkVftkxt1kIh7TA==",
- "M20iX2sUfw5SXaZLZYlTaA==",
- "VUDsc9RMS1fSM43c+Jo9dQ==",
- "itPtn+JaO4i7wz2wOPOmDQ==",
- "rCxoo4TP/+fupXMuIM0sDA==",
- "cSHSg9xJz/3F6kc+hKXkwg==",
- "b4BoZmzVErvuynxirLxn0w==",
- "e4B3HmWjW+6hQzcOLru6Xg==",
- "lTE6u9G/RzvmbuAzq2J2/Q==",
- "897ptlztTjr7yk+pk8MT0Q==",
- "jd6IpPJwOJW1otHKtKZ5Gw==",
- "b4aFwwcWMXsSdgS1AdFOXA==",
- "FltEN+7NKvzt+XAktHpfHA==",
- "ZyDh3vCQWzS5DI1zSasXWA==",
- "kcJ1acgBv6FtUhV8KuWoow==",
- "zgEyxj/sCs63O98sZS94Yw==",
- "/kGxvyEokQsVz0xlKzCn2A==",
- "cxqHS4UbPolcYUwMMzgoOA==",
- "62RHCbpGU8Hb+Ubn+SCTBg==",
- "ePlsM/iOMme2jEUYwi15ng==",
- "0fN+eHlbRS6mVZBbH/B9FQ==",
- "k0XIjxp2vFG7sTrKcfAihA==",
- "0rfG4gRugAwVP0i3AGVxxg==",
- "M98hjSxCwvZ27aBaJTGozQ==",
- "kzGNkWh3fz27cZer4BspUQ==",
- "3CJbrUdW68E3Drhe4ahUnQ==",
- "NGApiVkDSwzO45GT57GDQw==",
- "lMjip5hbCjkD9JQjuhewDg==",
- "GrSbnecYAC3j5gtoKntL0A==",
- "9dbn0Kzwr9adCEfBJh78uQ==",
- "64QzHOYX0A9++FqRzZRHlQ==",
- "YZt6HwCvdI5DRQqndA/hBQ==",
- "6GXHGF62/+jZ7PfIBlMxZw==",
- "PBULPuFXb6V3Di713n3Gug==",
- "8Cm19vJW8ivhFPy0oQXVNA==",
- "zDSQ3NJuUGkVOlvVCATRwA==",
- "6QAtjOK9enNLRhcVa2iaTg==",
- "v/PshI6JjkL9nojLlMNfhg==",
- "yTgN5xFIdz1MzFS6xMl5uQ==",
- "SCO9nQncEcyVXGCtx30Jdg==",
- "7b0oo4+qphu6HRvJq6qkHQ==",
- "ol9xhVTG9e1wNo50JdZbOA==",
- "hIABph+vhtSF5kkZQtOCTA==",
- "k+IBS52XdOe5/hLp28ufnA==",
- "6HnWgYNKohqhoa1tnjjU3A==",
- "HDxGhvdQwGh0aLRYEGFqnw==",
- "LDuBcL5r3PUuzKKZ9x6Kfw==",
- "HPvYV94ufwiNHEImu4OYvQ==",
- "h2cnQQF2/R3Mq2hWdDdrTg==",
- "nqpKfidczdgrNaAyPi7BOQ==",
- "2ywo4t5PPSVUCWDwUlOVwQ==",
- "jZMDIu95ITTjaUX0pk4V5g==",
- "bA2kaTpeXflTElTnQRp6GQ==",
- "lwYQm2ynA3ik2gE1m11IEg==",
- "5ugVOraop5P5z5XLlYPJyQ==",
- "l2NppPcweAtmA1V2CNdk2Q==",
- "DbWQI3H2tcJsVJThszfHGA==",
- "H6HPFAcdHFbQUNrYnB74dA==",
- "H1NJEI+fvOQbI51kaNQQjQ==",
- "53UccFNzMi9mKmdeD82vAw==",
- "lffapwUUgaQOIqLz2QPbAg==",
- "rSvhrHyIlnIBlfNJqemEbw==",
- "BLJk9wA88z6e0IQNrWJIVw==",
- "5m1ijXEW+4RTNGZsDA/rxQ==",
- "GG8a3BlwGrYIwZH9j3cnPA==",
- "HhBHt5lQauNl7EZXpsDHJA==",
- "/XjB6c5fxFGcKVAQ4o+OMw==",
- "+tuUmnRDRWVLA+1k0dcUvg==",
- "SM7E98MyViSSS9G0Pwzwyw==",
- "c5q/8n7Oeffv3B1snHM/lA==",
- "kwlAQhR2jPMmfLTAwcmoxw==",
- "0b/xj6fd0x+aB8EB0LC4SA==",
- "S8jlvuYuankCnvIvMVMzmg==",
- "kZkmDatUOdIqs7GzH3nI1A==",
- "obW3kzv2KBvuckU7F+tfjA==",
- "pa8nkpAAzDKUldWjIvYMYg==",
- "m+eh+ZqS74w2q0vejBkjaw==",
- "LcoJBEPTlSsQwfuoKQUxEw==",
- "KO2XVYyNZadcQv8aCNn5JA==",
- "uvzmRcvgepW6mZbMfYgcNw==",
- "KhUT2buOXavGCpcDOcbOYg==",
- "fo3JL+2kPgDWfP+CCrFlFw==",
- "wIfvvLKC61gOpsddUFjVog==",
- "SPHU6ES1WVm0Mu2LB+YjrA==",
- "LWWfRqgtph1XrpxF4N64TA==",
- "LCvz/h9hbouXCmdWDPGWqg==",
- "PXC6ZpdMH0ATis/jGW12iA==",
- "z920R8eahJPiTsifrPYdxA==",
- "GIHKW6plyLra0BmMOurFgA==",
- "k6OmSlaSZ5CB0i7SD9LczQ==",
- "YZ39RIXpeLAhyMgmW2vfkQ==",
- "bs2QG8yYWxPzhtyMqO6u3A==",
- "pKaTI+TfcV3p/sxbd2e7YQ==",
- "xWYecfzAtXT9WyQ8NYY/hw==",
- "Fz8EI+ZpYlbcttSHs5PfpA==",
- "wfwuxn+Vja1DNwiDwL2pcQ==",
- "wux5Y8AipBnc5tJapTzgEQ==",
- "U+oTpcjhc0E+6UjP11OE/Q==",
- "yTVJKBn72RjakMBXDoBKHg==",
- "0TxcYwG72dT7Tg+eG8pP1w==",
- "imZ+mwiT22sW2M9alcUFfg==",
- "CkDIoAFLlIRXra78bxT/ZA==",
- "4qMSNAxichi3ori/pR+o0w==",
- "zNLlWGW/aKBhUwQZ4DZWoQ==",
- "D31ZticrjGWAO45l5hFh7A==",
- "HdXg64DBy5WcL5fRRiUVOg==",
- "yhI5jHlfFJxu4eV5VJO2zQ==",
- "e9GqAEnk8XI5ix6kJuieNQ==",
- "EC0+iUdSZvmIEzipXgj7Gg==",
- "chwv4+xbEAa93PHg8q9zgQ==",
- "B1VVUbl8pU0Phyl1RYrmBg==",
- "A+DLpIlYyCb9DaarpLN76g==",
- "wHA+D5cObfV3kGORCdEknw==",
- "+Mp+JIyO0XC5urvMyi3wvQ==",
- "vUE8Iw3NyWXURpXyoNJdaw==",
- "ParhxI6RtLETBSwB0vwChQ==",
- "NxSdT2+MUkQN49pyNO2bJw==",
- "JSyhTcHLTfzHsPrxJyiVrA==",
- "PAlx9+U+yQCAc5Fi0BOG0w==",
- "W/0s1x3Qm+wN8DhROk6FrQ==",
- "L3Jt5dHQpWQk74IAuDOL8g==",
- "VWb8U4jF/Ic0+wpoXi/y/g==",
- "1wBuHqS1ciup31WTfm3NPg==",
- "BDNM1u/9mefjuW1YM2DuBg==",
- "SDi5+FoP9bMyKYp+vVv1XA==",
- "23d9B9Gz5kUOi1I//EYsSQ==",
- "/a9O7kWeXa0le45ab3+nVw==",
- "PcoVtZrS1x1Q+6nfm4f80w==",
- "A6TLWhipfymkjPYq8kaoDQ==",
- "lzUQ1o7JAbdJYpmEqi6KnQ==",
- "/2jGyMekNu7U136K+2N3Jg==",
- "ZItMIn1vhGqAlpDHclg0Ig==",
- "Ee4A3lTMLQ7iDQ7b8QP8Qg==",
- "bO55S58bqDiRWXSAIUGJKw==",
- "zeHF6fdeqcOId3fRUGscRw==",
- "BxsDnI8jXr4lBwDbyHaYXw==",
- "ylA6sU7Kaf9fMNIx1+sIlw==",
- "ZWXfE3uGU91WpPMGyknmqw==",
- "f1+fHgR5rDPsCZOzqrHM7Q==",
- "8VqeoQELbCs232+Mu+HblA==",
- "beSrliUu0BOadCWmx+yZyA==",
- "NQVQfN3nIg9ipHiFh4BvfQ==",
- "4wnUAbPT3AHRJrPwTTEjyw==",
- "/cdR1i5TuQvO+u3Ov3b0KQ==",
- "wtyAZIfhomcHe9dLbYoSvA==",
- "ulpDxLeQnIRPnq6oaah2AA==",
- "pdPwUHauXOowaq9hpL2yFw==",
- "1+A9FCGP3bZhk6gU3LQtNg==",
- "raYifKqev8pASjjuV+UTKQ==",
- "+OERSmo7OQUUjudkccSMOA==",
- "FeRovookFQIsXmHXUJhGOw==",
- "USCvrMEm/Wqeu9oX6FrgcQ==",
- "kly/2kE4/7ffbO34WTgoGg==",
- "IindlAnepkazs5DssBCPhA==",
- "Bq82MoMcDjIo/exqd/6UoA==",
- "ocvA1/NbyxM0hanwwY6EiA==",
- "rtd6mqFgGe98mqO0pFGbSw==",
- "nvLEpj6ZZF3LWH3wUB6lKg==",
- "AGd0rcLnQ0n+meYyJur1Pw==",
- "wI7JrSPQwYHpv2lRsQu9nQ==",
- "OnmvXbyT2BYsSDJYZhLScA==",
- "CmBf5qchS1V3C2mS6Rl4bw==",
- "TafM7nTE5d+tBpRCsb8TjQ==",
- "wxkb8evGEaGf/rg/1XUWiA==",
- "y1J+o6DC2sETFsySgpDZyA==",
- "SVLHWPCCH7GPVCF7QApPbw==",
- "HMWOlMmzocOIiJ7yG1YaDQ==",
- "DJmrmNRKARzsTCKSMLmcNA==",
- "/XC/FmMIOdhMTPqmy4DfUA==",
- "63OTPaKM0xCfJOy9EDto+Q==",
- "PxReytUUn/BbxYTFMu1r2Q==",
- "WjDqf1LyFyhdd8qkwWk+MA==",
- "/DiUApY7cVp5W9o24rkgRA==",
- "alJtvTAD7dH/zss/Ek1DMQ==",
- "xLm/bJBonpTs0PwsF0DvRg==",
- "eAOEgF5N80A/oDVnlZYRAw==",
- "LqgzKxbI6WTMz0AMIDJR5w==",
- "MJ1FuK8PXcmnBAG9meU84A==",
- "JLq/DrW2f26NaRwfpDXIEA==",
- "fsrX00onlGvfsuiCc35pGg==",
- "tXVb5f90k9l3e1oK2NGXog==",
- "1JRgSHnfAQFQtSkFTttkqQ==",
- "B0TaUQ6dKhPfSc5V/MjLEQ==",
- "nkbLVLvh3ClKED97+nH+7Q==",
- "avFTp3rS6z5zxQUZQuaBHQ==",
- "lNF8PvUIN02NattcGi5u4g==",
- "bBEndaOStXBpAK79FrgHaw==",
- "dM9up4vKQV5LeX82j//1jQ==",
- "4WO6eT0Rh6sokb29zSJQnQ==",
- "RHKCMAqrPjvUYt13BVcmvw==",
- "Ju4YwtPw+MKzpbC0wJsZow==",
- "tzV7ixFH37ze4zuLILTlfA==",
- "oPlhC4ebXdkIDazeMSn1fQ==",
- "5pje7qyz8BRsa8U4a4rmoA==",
- "7E6V6/zSjbtqraG7Umj+Jw==",
- "8QK7emHS6rAcAF5QQemW/A==",
- "LhqRc9oewY4XaaXTcnXIHQ==",
- "p/7qM5+Lwzw1/lIPY91YxQ==",
- "fy54Milpa7KZH/zgrDmMXQ==",
- "LyPXOoOPMieqINtX8C9Zag==",
- "aD4QvtMlr8Lk/zZgZ6zIMg==",
- "dsueq9eygFXILDC7ZpamuA==",
- "+mJLK+6qq8xFv7O/mbILTw==",
- "nHUpYmfV59fe3RWaXhPs3Q==",
- "VbCoGr8apEcN7xfdaVwVXw==",
- "/2Chaw2M9DzsadFFkCu6WQ==",
- "rKAQxu80Q8g1EEhW5Wh8tg==",
- "RJJqFMeiCZHdsqs72J17MQ==",
- "GF2yvI9UWf1WY7V7HXmKPA==",
- "JyIDGL1m/w+pQDOyyeYupA==",
- "wR2Gxb07nkaPcZHlEjr8iA==",
- "PbDVq2Iw1eeM8c2o/XYdTA==",
- "BL3buzSCV78rCXNEhUhuKQ==",
- "i42XumprV/aDT5R0HcmfIQ==",
- "DuEKxykezAvyaFO2/5ZmKQ==",
- "6ACvJNfryPSjGOK39ov8Qg==",
- "YaUKOTyByjUvp1XaoLiW5Q==",
- "jNcMS2zX1iSZN9uYnb2EIg==",
- "VRnx+kd6VdxChwsfbo1oeQ==",
- "4Qinl7cWmVeLJgah8bcNkw==",
- "Fiy3hkcGZQjNKSQP9vRqyA==",
- "HaSc7MZphCMysTy2JbTJkw==",
- "VhYGC8KYe5Up+UJ2OTLKUw==",
- "K2gk9zWGd0lJFRMQ1AjQ/Q==",
- "NfxVYc3RNWZwzh2RmfXpiA==",
- "JGeqHRQpf4No74aCs+YTfA==",
- "7VHlLw20dWck+I8tCEZilA==",
- "V5HKdaTHjA8IzvHNd9C51g==",
- "9TalxEyFgy6hFCM73hgb7Q==",
- "R/y6+JJP8rzz1KITJ4qWBw==",
- "7bM/pn4G7g7Zl6Xf1r62Lg==",
- "CHsFJfsvZkPWDXkA6ZMsDQ==",
- "uXuPA/2KJbb7ZX+NymN3dw==",
- "o+nYS4TqJc6XOiuUzEpC3A==",
- "8N3mhHt29FZDHn1P2WH1wQ==",
- "uZ2gUA74/7Q33tI2TcGQlg==",
- "8B12CamjOGzJDnQ+RkUf4w==",
- "9FdpxlIFu11qIPdO7WC5nw==",
- "G+sGF13VXPH4Ih6XgFEXxg==",
- "y+1I05LDAYJ09tKMs3zW6g==",
- "gnkadeCgjdmLdlu/AjBZJg==",
- "1I+UVx3krrD4NhzO7dgfHQ==",
- "8LNNoHe6rEQyJ0ebl151Mw==",
- "yOE90OHQdyOfrAgwDvn2gA==",
- "ayBGGPEy++biljvGcwIjXA==",
- "o/Y4U6rWfsUCXJ72p5CUGw==",
- "5kvyy902llnYGQdn2Py04w==",
- "6k2cuk0McTThSMW/QRHfjA==",
- "2XrR2hjDEvx8MQpHk9dnjw==",
- "fv/PW8oexJYWf5De30fdLQ==",
- "861mBNvjIkVgkBiocCUj/Q==",
- "NKGY0ANVZ0gnUtzVx1pKSw==",
- "4DIPP/yWRgRuFqVeqIyxMQ==",
- "cgSEbLqqvDsNUyeA3ryJ6Q==",
- "xbBxUP9JyY0wDgHDipBHeg==",
- "c3WVxyC5ZFtzGeQlH5Gw+w==",
- "ZKeTDCboOgCptrjSfgu0xw==",
- "DjHszpS8Dgocv3oQkW/VZQ==",
- "Iqszlv4R49UevjGxIPMhIA==",
- "uChFnF0oCwARhAOz/d47eA==",
- "0egBaMnAf0CQEXf1pCIKnA==",
- "FnVNxl5AFH1AieYru2ZG+A==",
- "2Ct+pLXrK6Ku1f4qehjurQ==",
- "x2nSgcTjA3oGgI8mMgiqjw==",
- "AUGmvZkpkKBry5bHZn4DJA==",
- "x8kRVzohTdhkryvYeMvkMw==",
- "rXfWkabSPN+23Ei1bdxfmQ==",
- "ElTNyMR4Rg8ApKrPw88WPg==",
- "9jxA/t3TQx8dQ+FBsn/YCg==",
- "I07W2eDQwe6DVsm1zHKM8A==",
- "0p1jMr06OyBoXQuSLYN4aQ==",
- "odGhKtO4bDW5R8SYiI5yCg==",
- "5Q/Y2V0iSVTK8HE8JerEig==",
- "Ily2MKoFI1zr5LxBy93EmQ==",
- "8dUcSkd2qnX5lD9B+fUe+Q==",
- "80UE+Ivby3nwplO/HA7cPw==",
- "sS6QcitMPdvUBLiMXkWQkw==",
- "5VY++KiWgo7jXSdFJsPN3A==",
- "aY6B28XdPnuYnbOy9uSP8A==",
- "ZfRlID+pC1Rr4IY14jolMw==",
- "/YuQw7oAF08KDptxJEBS9g==",
- "16d+fhFlgayu3ttKVV/pbg==",
- "8dBIsHMEAk7aoArLZKDZtg==",
- "wRqaDZVHHurp5whOQ1kDbQ==",
- "lFUq6PGk9dBRtUuiEW7Cug==",
- "FoJZ61VrU8i084pAuoWhDQ==",
- "4mig4AMLUw+T/ect9p4CfA==",
- "Po0lhBfiMaXhl+vYh1D8gA==",
- "z9cd+Qj+ueX34Zf3997MNQ==",
- "1dsKN1nG6upj7kKTKuJWsQ==",
- "UtLYUlQJ02oKcjNR3l+ktg==",
- "O538ibsrI4gkE5tfwjxjmg==",
- "G736AX070whraDxChqUrqw==",
- "THs1r8ZEPChSGrrhrNTlsA==",
- "pVG1hL96/+hQ+58rJJy6/A==",
- "1BjsijOzgHt/0i36ZGffoQ==",
- "6rIWazDEWU5WPZHLkqznuQ==",
- "cdWUm6uLNzR/knuj2x75eA==",
- "nsnX3tKkN1elr18E31tXDw==",
- "0fnruVOCxEczscBuv4yL9A==",
- "SVuEYfQ9FGyVMo1672n0Yg==",
- "ZRWyfXyXqAaOEjkzWl949Q==",
- "S2MAIYeDQeJ1pl9vhtYtUg==",
- "vsRNZx4thFFFPneubKq1Fw==",
- "kuWGANwzNRpG4XmY7KjjNg==",
- "i6r+mZfyhZyqlYv56o0H+w==",
- "wqWqe0KRjZlUIrGgEOG9Mg==",
- "t5wh9JGSkQO78QoQoEqvXA==",
- "AGoVLd0QPcXnTedT5T95JQ==",
- "aRrcmH+Ud3mF1vEXcpEm4w==",
- "C65PZm8rZxJ6tTEb6d08Eg==",
- "oAHVGBSJ2cf4dVnb/KEYmw==",
- "BuDVDLl0OGdomEcr+73XhQ==",
- "bLsStF0DDebpO+xulqGNtg==",
- "xukOAM0QVsA72qEy0yku9A==",
- "LpoayYsTO8WLFLCSh2kf2w==",
- "LEVYAE54618FrlXkDN01Kw==",
- "Jm862vBTCYbv/V4T1t46+Q==",
- "X4kdXUuhcUqMSduqhfLpxA==",
- "cLR0Ry4/N5swqga1R6QDMw==",
- "0klouNfZRHFFpdHi4ZR2hA==",
- "JGx8sTyvr4bLREIhSqpFkw==",
- "ZiJ/kJ9GneF3TIEm08lfvQ==",
- "hP7dSa8lLn9KTE/Z0s4GVQ==",
- "600bwlyhcy754W1E6tuyYg==",
- "U49SfOBeqQV9wzsNkboi8Q==",
- "5DDb7fFJQEb3XTc3YyOTjg==",
- "6uT7LZiWjLnnqnnSEW4e/Q==",
- "tq5xUJt8GtjDIh1b48SthQ==",
- "eJFIQh/TR7JriMzYiTw4Sg==",
- "jdRzkUJrWxrqoyNH9paHfQ==",
- "RKVDdE1AkILTFndYWi9wFg==",
- "AEpTVUQhIEJGlXJB6rS26A==",
- "PD+yHtJxZJ2XEvjIPIJHsQ==",
- "dOS+mVCy3rFX9FvpkTxGXA==",
- "lz+SeifYXxamOLs1FsFmSQ==",
- "QTz21WkhpPjfK8YoBrpo+w==",
- "9wUIeSgNN36SFxy8v2unVg==",
- "ash1r2J6B0PUxJe8P0otVQ==",
- "y7yS9x3yshVhMpDbQtfYOQ==",
- "f07bdNVAe9x+cAMdF1bByQ==",
- "N2KovXW14hN/6+iWa1Yv3g==",
- "2DNbXVgesUa7PgYQ4zX5Lw==",
- "WQznrwqvMhUlM3CzmbhAOQ==",
- "FpWDTLTDmkUhH/Sgo+g1Gg==",
- "OVHqwV8oQMC5KSMzd5VemA==",
- "Bv4mNIC72KppYw/nHQxfpQ==",
- "MI+HSMRh8KTW+Afiaxd/Fw==",
- "10OltdxPXOvfatJuwPVKbQ==",
- "y4/HohCJxtt+cT7nLJB08w==",
- "RhcqXY4OsZlVVF7ZlkTeRw==",
- "/mrqas0eDX+sFUNJvCQY8g==",
- "ZIZx4MehWTVXPN9cVQBmyA==",
- "z20AAnvj7WsfJeOu3vemlA==",
- "dL6n/JsK+Iq6UTbQuo/GOw==",
- "rMm9bHK69h0fcMkMdGgeeA==",
- "ftsf2qztw3NC78ep/CZXWQ==",
- "/n1RLTTVpygre1dl36PDwQ==",
- "/FsJYFNe+7UvsSkiotNJEQ==",
- "Yy2pPhITTmkEwoudXizHqQ==",
- "lizovLQxu6L9sbafNQuShQ==",
- "XV5MYe0Q7YMtoBD6/iMdSw==",
- "5jHgQF4SfO/zy9xy9t+9dw==",
- "16iT/jCcPDrJEfi2bE5F+Q==",
- "syeBfQBUmkXNWCZ1GV8xSA==",
- "sr3UXbMg5zzkRduFx/as7g==",
- "xUXEE7OBBCudsQnuj5ycOA==",
- "ojZY7Gi2QJXE/fp6Wy31iA==",
- "RlNPyhgYOIn28R4vKCVtYA==",
- "KOm8PTa+ICgDrgK9QxCJZw==",
- "DJoy1NSZZw87oxWGlNHhfg==",
- "jEdanvXKyZdZJG6mj/3FWw==",
- "Omr+zPWVucPCSfkgOzLmSQ==",
- "71w3aSvuh2mBLtdqJCN3wA==",
- "xjTMO2mvtpvwQrounD4e8g==",
- "Zz/5VMbw1TqwazReplvsEg==",
- "hIjgi20+km+Ks23NJ4VQ6Q==",
- "00TVKawojyqrJkC7YqT41Q==",
- "YgVpC5d5V6K/BpOD663yQA==",
- "wX70jKLKJApHnhyK0r6t3A==",
- "lacCCRiWdquNm4YRO7FoKA==",
- "cWdlhVZD7NWHUGte24tMjg==",
- "t5U+VMsTtlWAAWSW+00SfQ==",
- "AMfL0rH+g8c0VqOUSgNzQw==",
- "0G93AxGPVwmr66ZOleM90A==",
- "9tiibT8V9VwnPOErWGNT3w==",
- "+dBv88reDrjEz6a2xX3Hzw==",
- "xX6atcCApI08oVLjjLteLg==",
- "+YrqTEJlJCv0A2RHQ8tr1A==",
- "aqcOby9QyEbizPsgO3g0yw==",
- "s/BZAhh1cTV3JCDUQsV8mA==",
- "x9VwDdFPp/rJ+SF16ooWYg==",
- "k/OVIllJvW6BefaLEPq7DA==",
- "rIMXaCaozDvrdpvpWvyZOQ==",
- "qQQwJ/aF87BbnLu3okXxaw==",
- "TIWSM78m0RprwgPGK/e0JA==",
- "r/b5px/UImGNjT/X5sYjuA==",
- "7K8l6KoP0BH82/WMLntfrg==",
- "gEHGeR2F82OgBeAlnYhRSw==",
- "1/SGIab+NnizimUmNDC4wA==",
- "WADmxH7R6B4LR+W6HqQQ6A==",
- "pcoBh5ic7baSD4TZWb3BSw==",
- "es/L9iW8wsyLeC5S4Q8t+g==",
- "D175i+2bZ7aWa4quSSkQpA==",
- "WQMffxULFKJ+bun6NrCURA==",
- "82hTTe1Nr4N2g7zwgGjxkw==",
- "oyYtf08AkWLR52bXm5+sKw==",
- "8uP4HUnSodw88yoiWXOIcw==",
- "x2NpqNnqRihktNzpxmepkQ==",
- "x5zMDuW66467ofgL3spLUQ==",
- "OMO4pqzfcbQ11YO4nkTXfg==",
- "N4/mQFyhDpPzmihjFJJn6w==",
- "NN/ymVQNa17JOTGr6ki3eQ==",
- "htDbVu1xGhCRd8qoMlBoMg==",
- "S47hklz3Ow+n5aY6+qsCoA==",
- "ji+1YHlRvzevs3q5Uw1gfA==",
- "3Y4w0nETru3SiSVUMcWXqw==",
- "XfBOCJwi2dezYzLe316ivw==",
- "kMUdiwM7WR8KGOucLK4Brw==",
- "V/xG5QFyx1pihimKmAo8ZA==",
- "sQskMBELEq86o1SJGQqfzg==",
- "6+jhreeBLfw64tJ+Nhyipw==",
- "8iYdEleTXGM+Wc85/7vU9w==",
- "D7piVoB2NJlBxK5owyo4+g==",
- "hDGa2yLwNvgBd/v6mxmQaQ==",
- "WLsh3UF4WXdHwgnbKEwRlQ==",
- "D5jaV+HtXkSpSxJPmaBDXg==",
- "jCgdKXsBCgf7giUKnr6paQ==",
- "XqW7UBTobbV4lt1yfh0LZw==",
- "EbGG4X18upaiVQmPfwKytg==",
- "dXDPnL1ggEoBqR13aaW9HA==",
- "Vik8tGNxO0xfdV0pFmmFDw==",
- "Swjn3YkWgj0uxbZ1Idtk+A==",
- "JPxEncA4IkfBDvpjHsQzig==",
- "F5FcNti7lUa9DyF2iEpBug==",
- "HJYgUxFZ66fRT8Ka73RaUg==",
- "Jbxl8Nw1vlHO9rtu0q/Fpg==",
- "fmC+85h5WBuk8fDEUWPjtQ==",
- "dZgMquvZmfLqP4EcFaWCiA==",
- "XF/yncdoT4ruPeXCxEhl9Q==",
- "QJEbr3+42P9yiAfrekKdRQ==",
- "Sr9c0ReRpkDYGAiqSy683g==",
- "Nr4zGo5VUrjXbI8Lr4YVWQ==",
- "NDZWIhhixq7NT8baJUR4VQ==",
- "GFRJoPcXlkKSvJRuBOAYHQ==",
- "WHutPin+uUEqtrA7L8878A==",
- "2rhjiY0O0Lo36wTHjmlNyw==",
- "XsF7R12agx/KkRWl0TyXRA==",
- "R6cO8GzYfOGTIi773jtkXw==",
- "zrZWcqQsUE3ocWE0fG+SOA==",
- "uNzpptKjihEfKRo5A1nWmw==",
- "gICaI06E9scnisonpvqCsA==",
- "TA9WjiLAFgJubLN4StPwLw==",
- "sBpytpE38xz0zYeT+0qc2A==",
- "Ej7W3+67kCIng3yulXGpRQ==",
- "nR3ACzeVF5YcLX6Gj6AGyQ==",
- "b0vZfEyuTja2JYMa20Rtbg==",
- "f1h+Vp+xmdZsZIziHrB2+g==",
- "WzjvUJ4jZAEK7sBqw+m07A==",
- "OzMR5D2LriC5yrVd5hchnA==",
- "cw1gBLtxH/m4H7dSM7yvFg==",
- "CZbd+UoTz0Qu1kkCS3k8Xg==",
- "WtT0QAERZSiIt2SFDiAizg==",
- "QsquNcCZL9wv7oZFqm64vQ==",
- "FXzaxi3nAXBc8WZfFElQeA==",
- "Ml3mi1lGS1IspHp3dYYClg==",
- "XGAXhUFjORwKmAq9gGEcRg==",
- "wOhbpTzmFla8R0kI9OiHaA==",
- "qoK2keBg3hdbn7Q24kkVXg==",
- "ZAQHWU6RMg4IadOxuaukyw==",
- "RiahBXX2JbPzt8baPiP/8g==",
- "Qx6rVv9Xj8CBjqikWI9KFA==",
- "ZRnR6i+5WKMRfs3BDRBCJg==",
- "91LQuW6bMSxl10J/UDX23A==",
- "0dIeIM5Zvm5nSVWLy94LWg==",
- "Ja3ECL7ClwDrWMTdcSQ6Ug==",
- "f6iLrMpxKhFxIlfRsFAuew==",
- "iSeH0JFSGK73F470Rhtesw==",
- "DwOTyyCoUfaSShHZx9u6xg==",
- "rdeftHE7gwAT67wwhCmkYQ==",
- "kUhyc3G8Zvx8+q5q5nVEhw==",
- "W8bATujVUT80v2XGJTKXDg==",
- "dMRx4Mf6LrN64tiJuyWmDw==",
- "9cvHJmim9e0pOaoUEtiM6A==",
- "RHToSGASrwEmvzjX6VPvNQ==",
- "V7eji28JSg3vTi30BCS7gw==",
- "4+htiqjEz9oq0YcI/ErBVg==",
- "jKJn4czwUl/6wtZklcMsSg==",
- "bvyB6OEwhwCIfJ6KRhjnRw==",
- "59ipbMH7cKBsF9bNf4PLeQ==",
- "M/cQja3uIk1im9++brbBOA==",
- "AChOz8avRYsvxlbWcorQ3w==",
- "FcKjlHKfQAGoovtpf+DxWQ==",
- "y+cl1/Knb9MZPz8nBB0M+w==",
- "b8BZV1NfBdLi70ir4vYvZg==",
- "aFJuE/s+Kbge4ppn+wulkA==",
- "CWBGcRFYwZ0va6115vV/oQ==",
- "glnqaRfwm6NxivtB2nySzw==",
- "mPk1IsU5DmDFA/Ym5+1ojw==",
- "LGwcvetzQ3QqKjNh5vA8vw==",
- "yctId8ltkl3+xqi9bj+RqA==",
- "spJI3xFUlpCDqzg0XCxopA==",
- "V8m51xgUgywRoV6BGKUrgg==",
- "rgcXxjx3pDLotH7TTfAoZw==",
- "/TSsi/AwKHtP6kQaeReI3w==",
- "8dbyfox/isKLsnVjQNsEXg==",
- "MOrAbuJTyGKPC6MgYJlx5Q==",
- "uNWFZlP7DA96sf+LWiAhtQ==",
- "hNHqznsrIVRSQdII6crkww==",
- "GT6WUDXiheKAM7tPg3he9A==",
- "JC8Q+8yOJ52NvtVeyHo68w==",
- "HMQarkPWOUDIg5+5ja2dBQ==",
- "nknBKPgb7US42v8A0fTl/w==",
- "fDOUzPTU2ndpbH0vgkgrJQ==",
- "GTNttXfMniNhrbhn92Aykg==",
- "D2JcY4zWwqaCKebLM8lPiQ==",
- "/c34NtdUZAHWIwGl3JM8Tw==",
- "/G26n5Xoviqldr5sg/Jl3w==",
- "GF0lY77rx1NQzAsZpFtXIQ==",
- "BMOi5JmFUg5sCkbTTffXHw==",
- "R+beucURp/H5jLs4kW6wmg==",
- "xfYZ6qhWNBqqJ0PdWRjOwA==",
- "Ahpi9+nl13kPTdzL+jgqMw==",
- "oIU19xAvLJwQSZzIH577aA==",
- "50xwiYvGQytEDyVgeeOnMg==",
- "M0ESOGwJ4WZ4Ons1ljP0bQ==",
- "fS471/rN4K2m10mUwGFuLg==",
- "RrE3B3X/SJi3CqCUlTYwaw==",
- "oDca3JEdRb4vONT9GUUsaQ==",
- "pHo1O5zrCHCiLvopP2xaWw==",
- "7sCJ4RxbxRqVnF4MBoKfuQ==",
- "7R5rFaXCxM3moIUtoCfM2g==",
- "4rrSL6N0wyucuxeRELfAmw==",
- "9Gkw+hvsR/tFY1cO89topg==",
- "aw4CzX8pYbPVMuNrGCEcWg==",
- "KyLQxi5UP+qOiyZl0PoHNQ==",
- "T1pMWdoNDpIsHF8nKuOn2A==",
- "Qv6wWP4PpycDGxe7EZNSCw==",
- "ZJc7GV0Yb6MrXkpDVIuc8g==",
- "aXrbsro7KLV8s4I4NMi4Eg==",
- "7k5rBuh8FbTTI4TP87wBPQ==",
- "NRyFx6jqO/oo9ojvbYzsAg==",
- "P7eMlOz9YUcJO+pJy0Kpkw==",
- "jpjpNjL1IKzJdGqWujhxCw==",
- "9k1u/5TgPmXrsx3/NsYUhg==",
- "c1wbFbN7AdUERO/xVPJlgw==",
- "Yw4ztKv6yqxK9U1L0noFXg==",
- "GnJKlRzmgKN9vWyGfMq3aA==",
- "91VcAVv7YDzkC1XtluPigw==",
- "h1NNwMy0RjQmLloSw1hvdg==",
- "pzC8Y0Vj9MPBy3YXR32z6w==",
- "UTmTgvl+vGiCDQpLXyVgOg==",
- "CzWhuxwYbNB/Ffj/uSCtbw==",
- "VOB+9Bcfu8aHKGdNO0iMRw==",
- "X2Tawm2Cra6H7WtXi1Z4Qw==",
- "6cTETZ9iebhWl+4W5CB+YQ==",
- "X4hrgqMIcApsjA9qOWBoCw==",
- "1buQEv2YlH/ljTgH0uJEtw==",
- "FH5Z60RXXUiDk+dSZBxD3g==",
- "FI2WhaSMb3guFLe3e9il8Q==",
- "O/EizzJSuFY8MpusBRn7Tg==",
- "b6rrRA0W247O+FfvDHbVCQ==",
- "ng1Q0A7ljho3TUWWYl46sw==",
- "1Ym0lyBJ9aFjhJb/GdUPvQ==",
- "+OXdvbTxHtSoLg7bZMho4w==",
- "cuQslgfqD2VOMhAdnApHrA==",
- "pCQmlnn3BxhsV2GwqjRhXg==",
- "6PzjncEw2wHZg7SP7SQk9w==",
- "nqtQI1bSM7DCO9P1jGV97Q==",
- "O1ckWUwuhD44MswpaD6/rw==",
- "RUmhye56tQu9xXs4SRJpOQ==",
- "llujnWE17U8MIHmx4SbrSA==",
- "UwqBVd4Wfias4ElOjk2BzQ==",
- "kBAB2PSjXwqoQOXNrv80AA==",
- "w1zN28mSrI/gqHsgs4ME3A==",
- "301utVPZ93AnPLYbsiJggw==",
- "qIFpKKwUmztsBpJgMaVvSg==",
- "QmcURiMzmVeUNaYPSOtTTg==",
- "x/MpsQvziUpW40nNUHDS5Q==",
- "t1O9jSNjg4DTIv/Za4NbtA==",
- "1B5gxGQSGzVKoNd5Ol4N7g==",
- "81iQLU+YwxNwq4of6e9z7A==",
- "x0eIHCvQLd2jdDaXwSWTYQ==",
- "96ORaz1JRHY1Gk8H74+C2g==",
- "bNDKcFu8T5Y6OoLSV+o/Sw==",
- "WrJMOuXSLKKzgmIDALkyNw==",
- "+gpHnUj2GWocP74t5XWz4w==",
- "z5DveTu377UW8IHnsiUGZg==",
- "irnD9K8bsT+up/JUrxPw6A==",
- "ginkFyNVMwkZLE49AbfqfA==",
- "2hEzujfG3mR5uQJXbvOPTQ==",
- "E9yeifEZtpqlD0N3pomnGw==",
- "OpC/sL320wl5anx6AVEL+A==",
- "D7wN7b5u5PKkMaLJBP9Ksw==",
- "83WGpQGWyt6mCV+emaomog==",
- "X6ulLp4noBgefQTsbuIbYQ==",
- "BH+rkZWQjTp7au6vtll/CQ==",
- "Ex3x5HeDPhgO2S9jjCFy4g==",
- "YNqIHCmBp/EbCgaPKJ7phw==",
- "312g8iTB9oJgk/OqcgR7Cw==",
- "LcF0OqPWrcpHby8RwXz1Yg==",
- "gaEtlJtD6ZjF5Ftx0IFt0A==",
- "bvbMJZMHScwjJALxEyGIyg==",
- "StoXC7TBzyRViPzytAlzyQ==",
- "XqFSbgvgZn0CpaZoZiRauQ==",
- "AqHVaj3JcR44hnMzUPvVYg==",
- "jTg9Y6EfpON4CRFOq0QovA==",
- "q/siBRjx6wNu+OTvpFKDwA==",
- "goSgZ8N5UbT5NMnW3PjIlQ==",
- "9onh6QKp70glZk9cX3s34A==",
- "o5XVEpdP4OXH0NEO4Yfc/A==",
- "a5gZ5uuRrXEAjgaoh7PXAg==",
- "PaROi5U16Tk35p0EKX5JpA==",
- "dtnE401dC0zRWU0S/QOTAg==",
- "7J3FoFGuTIW36q0PZkgBiw==",
- "hiYg+aVzdBUDCG0CXz9kCw==",
- "vhdFtKVH4bVatb4n8KzeXw==",
- "DWKsPfKDAtfuwgmc2dKUNg==",
- "M2JMnViESVHTZaru6LDM6w==",
- "G/PA+kt0N+jXDVKjR/054A==",
- "6rqK8sjLPJUIp7ohkEwfZg==",
- "wajwXfWz2J+O+NVaj6j2UQ==",
- "C4QEzQKGxyRi2rjwioHttA==",
- "N/HgDydvaXuJvTCBhG/KtA==",
- "6erpZS36qZRXeZ9RN9L+kw==",
- "bbBsi6tXMVWyq3SDVTIXUg==",
- "aySnrShOW4/xRSzl/dtSKQ==",
- "rxfACPLtKXbYua18l3WlUw==",
- "L4+C6I7ausPl6JbIbmozAg==",
- "R3ijnutzvK6IKV3AKHQZSA==",
- "leDlMcM+B1mDE8k5SWtUeg==",
- "KGI/cXVz6v6CfL8H6akcUQ==",
- "NtwqUO3SKZE/9MXLbTJo/g==",
- "dJHKDkfMFJeoULg7U4wwDQ==",
- "IEz72W2/W8xBx5aCobUFOQ==",
- "wUYhs4j3W9nIywu1HIv2JA==",
- "GzbeM7snhe+M+J7X+gAsQw==",
- "3/1puZTGSrD9qNKPGaUZww==",
- "eKQCVzLuzoCLcB4im8147A==",
- "CCK+6Dr72G3WlNCzV7nmqw==",
- "CJoZn5wdTXbhrWO5LkiW0g==",
- "bJ1cZW7KsXmoLw0BcoppJg==",
- "OlpA9HsF8MBh7b45WZSSlg==",
- "JZRjdJLgZ+S0ieWVDj8IJg==",
- "uhT12XY79CtbwhcSfAmAXQ==",
- "isep9d+Q7DEUf0W7CJJYzw==",
- "K9A87aMlJC8XB9LuFM913g==",
- "uqe3rFveJ2JIkcZQ3ZMXHQ==",
- "0e8hM3E5tnABRyy29A8yFw==",
- "4iiCq+HhC+hPMldNQMt0NA==",
- "X4o0OkTz0ec70mzgwRfltA==",
- "1E3pMgAHOnHx3ALdNoHr8Q==",
- "xNilc7UOu1kyP0+nK5MrLw==",
- "DQlZWBgdTCoYB1tJrNS5YQ==",
- "iruDC5MeywV4yA8o1tw/KQ==",
- "z+1oDVy8GJ5u/UDF+bIQdA==",
- "uExgqZkkJnZj252l5dKAGg==",
- "ZgdpqFrVGiaHkh9o3rDszg==",
- "5N2oi2pB69NxeNt08yPLhw==",
- "G37U8XTFyshfCs7qzFxATg==",
- "0ZEC3hy411LkOhKblvTcqg==",
- "ITZ3P47ALS0JguFms6/cDA==",
- "WWN44lbUnEdHmxSfMCZc6w==",
- "r2f2MyT+ww1g9uEBzdYI1w==",
- "ZvvxwDd0I6MsYd7aobjLUA==",
- "uQs79rbD/wEakMUxqMI48A==",
- "022B0oiRMx8Xb4Af98mTvQ==",
- "afMd/Hr3rYz/l7a3CfdDjg==",
- "xmsYnsJq78/f9xuKuQ2pBQ==",
- "dFetwmFw+D6bPMAZodUMZQ==",
- "TBQpcKq2huNC5OmI2wzRQw==",
- "skrQRB9xbOsiSA19YgAdIQ==",
- "anyANMnNkUqr3JuPJz5Qzw==",
- "6QUGE2S8oFYx4T4nW56cCw==",
- "rwtF86ZAbWyKI6kLn4+KBw==",
- "6txm8z4/LGCH0cpaet/Hsg==",
- "wdRyYjaM11VmqkkxV/5bsA==",
- "+k5lDb+QdNc9iZ01hL5yBg==",
- "k/pBSWE2BvUsvJhA9Zl5uw==",
- "jQjyjWCEo9nWFjP4O8lehw==",
- "R6Me6sSGP5xpNI8R0xGOWw==",
- "9+hjTVMQUsvVKs7Tmp52tg==",
- "VQIpquUqmeyt/q6OgxzduQ==",
- "KXvdjZ3rRKn60djPTCENGA==",
- "5HovoyHtul8lXh+z8ywq9A==",
- "1+XWdu4qCqLLVjqkKz3nmA==",
- "LCj4hI520tA685Sscq6uLw==",
- "b53qqLnrTBthRXmmnuXWvw==",
- "WTr3q/gDkmB4Zyj7Ly20+w==",
- "FbxScyuRacAQkdQ034ShTA==",
- "qaTdVEeZ6S8NMOxfm+wOMA==",
- "ZNrjP1fLdQpGykFXoLBNPw==",
- "/Bwpt5fllzDHq2Ul6v86fA==",
- "/mFp3GFkGNLhx2CiDvJv4A==",
- "RppDe/WGt1Ed6Vqg1+cCkQ==",
- "6M6QapJ5xtMXfiD3bMaiLA==",
- "Ghuj9hAyfehmYgebBktfgA==",
- "GncGQgmWpI/fZyb/6zaFCg==",
- "R1TCCfgltnXBvt5AiUnCtQ==",
- "5NEP7Xt7ynj6xCzWzt21hQ==",
- "4yEkKp2FYZ09mAhw2IcrrA==",
- "y2Tn2gmhKs5WKc01ce74rg==",
- "wnfYUctNK+UPwefX5y4/Rw==",
- "BV1moliPL15M14xkL+H1zw==",
- "80C9TB9/XT1gGFfQDJxRoA==",
- "yL1DwlIIREPuyuCFULi0uw==",
- "D09afzGpwCEH0EgZUSmIZA==",
- "eCy/T+a8kXggn1L8SQwgvA==",
- "+dIEf5FBrHpkjmwUmGS6eg==",
- "kzXsrxWRnWhkA82LsLRYog==",
- "Nf9fbRHm844KZ2sqUjNgkA==",
- "XAq/C+XyR6m3uzzLlMWO5Q==",
- "jiV+b/1EFMnHG6J0hHpzBg==",
- "HK0yf7F97bkf1VYCrEFoWA==",
- "Cz1G77hsDtAjpe0WzEgQog==",
- "xdCCdP8SNBOK3IsX6PiPQA==",
- "8snljTGo/uICl9q0Hxy7/A==",
- "sLdxIKap0ZfC3GpUk3gjog==",
- "IA1jmtfpYkz/E2wD0+27WA==",
- "PPa7BDMpRdxJdBxkuWCxKA==",
- "CuGIxWhRLN7AalafBZLCKQ==",
- "MWcV03ULc0vSt/pFPYPvFA==",
- "QVwuN66yPajcjiRnVk/V8g==",
- "aLY2pCT0WfFO5EJyinLpPg==",
- "dGrf9SWJ13+eWS6BtmKCNw==",
- "YtZ8CYfnIpMd2FFA5fJ+1Q==",
- "Umd+5fTcxa3mzRFDL9Z8Ww==",
- "Al8+d/dlOA5BXsUc5GL8Tg==",
- "/KYZdUWrkfxSsIrp46xxow==",
- "kr8tw1+3NxoPExnAtTmfxg==",
- "PwvPBc+4L73xK22S9kTrdA==",
- "VWNDBOtjiiI4uVNntOlu/A==",
- "lJFPmPWcDzDp5B2S8Ad8AA==",
- "Mofqu40zMRrlcGRLS42eBw==",
- "BuENxPg7JNrWXcCxBltOPg==",
- "nmD7fEU4u7/4+W/pkC4/0Q==",
- "axEl7xXt/bwlvxKhI7hx4g==",
- "W04GeDh+Tk/I1S85KlozRA==",
- "tVw8U1AsslIFmQs4H1xshg==",
- "TSPFvkgw6uLsJh66Ou0H9w==",
- "IYIbEaErHoFBn8sTT9ICIQ==",
- "WBu0gJmmjVdVbjDmQOkU6w==",
- "ZgjifTVKmxOieco81gnccQ==",
- "ZrCnZB/U/vcqEtI1cSvnww==",
- "2D6yhuABiaFFoXz0Lh0C+w==",
- "SfwnYZCKP1iUJyU1yq4eKg==",
- "tsiqwelcBAMU/HpLGBtMGw==",
- "S9L29U2P5K8wNW+sWbiH7w==",
- "sGLPmr568+SalaQr8SE/PA==",
- "Hm6MG6BXbAGURVJKWRM6ZA==",
- "euxzbIq4vfGYoY3s1QmLcw==",
- "/FchS2nPezycB8Bcqc2dbg==",
- "ZKvox7BaQg4/p5jIX69Umw==",
- "HkbdaMuDTPBDnt3wAn5RpQ==",
- "eddhS+FkXxiUnbPoCd5JJw==",
- "Muf2Eafcf9G3U2ZvQ9OgtQ==",
- "a7Pv1SOWYnkhIUC22dhdDA==",
- "O839JUrR+JS30/nOp428QA==",
- "2qK2ZEY9LgdKSTaLf6VnLA==",
- "BTiGLT6XdZIpFBc91IJY6g==",
- "EqYq2aVOrdX5r7hBqUJP7g==",
- "SIuKH/Qediq0TyvqUF93HQ==",
- "c5ymZKqx/td1MiS2ERiz9A==",
- "rqucO37p86LpzehR/asCSQ==",
- "1tpM0qgdo7JDFwvT0TD78g==",
- "Ar1Eb/f/LtuIjXnnVPYQlA==",
- "V8q+xz4ljszLZMrOMOngug==",
- "P5WPQc5NOaK7WQiRtFabkw==",
- "Xo8ZjXOIoXlBjFCGdlPuZw==",
- "jTmPbq+wh30+yJ/dRXk1cA==",
- "KSumhnbKxMXQDkZIpDSWmQ==",
- "Kh/J1NpDBGoyDU+Mrnnxkg==",
- "3BjLFon1Il0SsjxHE2A1LQ==",
- "dml2gqLPsKpbIZ93zTXwCQ==",
- "ZyoaR1cMiKAsElmYZqKjLA==",
- "vnOJ3e9Zd4wPx8PX7QgZzQ==",
- "2melaInV0wnhBpiI3da6/A==",
- "mUek9NkXm8HiVhQ6YXiyzA==",
- "RZTpYKxOAH9JgF1QFGN+hw==",
- "a/Y6IAVFv0ykRs9WD+ming==",
- "yhRi5M9Etuu9HSu4d24i3w==",
- "+1gcqAqaRZwCj5BGiZp3CA==",
- "o1zeXHJEKevURAAbUE/Vog==",
- "cvOg7N4DmTM+ok1NBLyBiQ==",
- "uPdjKJIGzN7pbGZDZdCGaA==",
- "REnDNe9mGfqVGZt+GdsmjQ==",
- "XqTK/2QuGWj50tGmiDxysA==",
- "bL2FuwsPT7a7oserJQnPcw==",
- "uO+uK1DntCxVRr1KttfUIw==",
- "Xconi1dtldH90Wou9swggw==",
- "HRF3WL/ue3/QlYyu7NUTrA==",
- "5LuFDNKzMd2BzpWEIYO2Ww==",
- "dNTU+/2DdZyGGTdc+3KMhQ==",
- "H+NHjk/GJDh/GaNzMQSzjg==",
- "/Ph/6l/lFNVqxAje1+PgFA==",
- "4WRdAjiUmOQg2MahsunjAg==",
- "j+lDhAnWAyso+1N8cm85hQ==",
- "nFBXCPeiwxK9mLXPScXzTA==",
- "vGKknndb4j6VTV8DxeT4fQ==",
- "fdqt93OrpG13KAJ5cASvkg==",
- "1MIn73MLroxXirrb+vyg2Q==",
- "Q7teXmTHAC5qBy+t7ugf0w==",
- "bWwtTFlhO3xEh/pdw0uWaQ==",
- "Omi2ZB9kdR1HrVP2nueQkA==",
- "+ZozWaPWw8ws1cE5DJACeg==",
- "3FH4D31nKV13sC9RpRZFIg==",
- "4kXlJNuT79XXf1HuuFOlHw==",
- "36XDmX6j542q+Oei1/x0gw==",
- "MqqDg9Iyt4k3vYVW5F+LDw==",
- "cvrGmub2LoJ+FaM5HTPt9A==",
- "uC2lzm7HaMAoczJO6Z/IhQ==",
- "MnStiFQAr3QlaRZ02SYGaQ==",
- "ZuayB6IpbeITokKGVi9R5w==",
- "FtxpWdhEmC6MT61qQv4DGA==",
- "KujFdhhgB9q4oJfjYMSsLg==",
- "ZV8mEgJweIYk0/l0BFKetA==",
- "gDLjxT7vm07arF4SRX5/Vg==",
- "/MEOgAhwb7F0nBnV4tIRZA==",
- "k2KP9oPMnHmFlZO6u6tgyw==",
- "fbTm027Ms0/tEzbGnKZMDA==",
- "HOi+vsGAae4vhr+lJ5ATnQ==",
- "9Bet5waJF5/ZvsYaHUVEjQ==",
- "Wd0dOs7eIMqW5wnILTQBtg==",
- "z/e5M2lE9qh3bzB97jZCKA==",
- "b16O4LF7sVqB7aLU2f3F1A==",
- "lsBTMnse2BgPS6wvPbe7JA==",
- "0nOg18ZJ/NicqVUz5Jr0Hg==",
- "MFeXfNZy6Q9wBfZmPQy3xg==",
- "ksOFI9C7IrDNk4OP6SpPgw==",
- "NquRbPn8fFQhBrUCQeRRoQ==",
- "ccmy4GVuX967KaQyycmO0w==",
- "DY0IolKTYlW+jbKLPAlYjQ==",
- "aJFbBhYtMbTyMFBFIz/dTA==",
- "9pdeedz1UZUlv8jPfPeZ1g==",
- "qZ2q5j2gH3O56xqxkNhlIA==",
- "N7fHwb397tuQHtBz1P80ZQ==",
- "uOkMpYy/7DYYoethJdixfQ==",
- "E9ajQQMe02gyUiW3YLjO/A==",
- "dFSavcNwGd8OaLUdWq3sng==",
- "TAD0Lk95CD86vbwrcRogaQ==",
- "jLI3XpVfjJ6IzrwOc4g9Pw==",
- "CzP13PM/mNpJcJg8JD3s6w==",
- "GSWncBq4nwomZCBoxCULww==",
- "9k17UqdR1HzlF7OBAjpREA==",
- "TrWS+reCJ0vbrDNT5HDR9w==",
- "CXMKIdGvm60bgfsNc+Imvg==",
- "6NP81geiL14BeQW6TpLnUA==",
- "hW9DJA1YCxHmVUAF7rhSmQ==",
- "8M0kSvjn5KN8bjsMdUqKZQ==",
- "eS/vTdSlMUnpmnl1PbHjyw==",
- "h2B0ty0GobQhDnFqmKOpKQ==",
- "n7KL1Kv027TSxBVwzt9qeA==",
- "yYmnM/WOgi+48Rw7foGyXA==",
- "FhthAO5IkMyW4dFwpFS7RA==",
- "81ZH3SO0NrOO+xoR/Ngw1g==",
- "t7HaNlXL16fVwjgSXmeOAQ==",
- "N+K1ibXAOyMWdfYctNDSZQ==",
- "yQCLV9IoPyXEOaj3IdFMWw==",
- "3+zsjCi7TnJhti//YXK35w==",
- "600mjiWke4u0CDaSQKLOOg==",
- "K4VS+DDkTdBblG93l2eNkA==",
- "5KOgetfZR+O2wHQSKt41BQ==",
- "kj5WqpRCjWAfjM7ULMcuPQ==",
- "AxEjImKz4tMFieSo7m60Sg==",
- "jp5Em/0Ml4Txr1ptTUQjpg==",
- "jQVlDU+HjZ2OHSDBidxX5A==",
- "4NHQwbb3zWq2klqbT/pG6g==",
- "PeJS+mXnAA6jQ0WxybRQ8w==",
- "l6Ssc04/CnsqUua9ELu2iQ==",
- "nFPDZGZowr3XXLmDVpo7hg==",
- "yYBIS9PZbKo7Gram7IXWPA==",
- "/HU2+fBqfWTEuqINc0UZSA==",
- "adT+OjEB2kqpeYi4kQ6FPg==",
- "GW1Uaq622QamiiF24QUA0g==",
- "rTwJggSxTbwIYdp07ly0LA==",
- "4yrFNgqWq17zVCyffULocA==",
- "vvh9vAIrXjIwLVkuJb5oDQ==",
- "C7UaoIEXsVRxjeA0u99Qmw==",
- "x1A74vg/hwwjAx6GrkU8zw==",
- "7XRiYvytcwscemlxd9iXIQ==",
- "64AA4jLHXc1Dp15aMaGVcA==",
- "u/QxrP1NOM/bOJlJlsi/jQ==",
- "5M3dFrAOemzQ0MAbA8bI5w==",
- "wyqmQGB6vgRVrYtmB2vB7w==",
- "8vLA9MOdmLTo3Qg+/2GzLA==",
- "/u5W2Gab4GgCMIc4KTp2mg==",
- "lhAOM81Ej6YZYBu45pQYgg==",
- "MArbGuIAGnw4+fw6mZIxaw==",
- "ZZImGypBWwYOAW43xDRWCQ==",
- "L2IeUnATZHqOPcrnW2APbA==",
- "bQKkL+/KUCsAXlwwIH0N3w==",
- "f09F7+1LRolRL5nZTcfKGA==",
- "hPnPQOhz4QKhZi02KD6C+A==",
- "78b8sDBp28zUlYPV5UTnYw==",
- "iVDd2Zk7vwmEh97LkOONpQ==",
- "LHQETSI5zsejvDaPpsO29g==",
- "Yjm5tSq1ejZn3aWqqysNvA==",
- "gkrg0NR0iCaL7edq0vtewA==",
- "Lo1xTCEWSxVuIGEbBEkVxA==",
- "8GyPup4QAiolFJ9v80/Nkw==",
- "3L3KEBHhgDwH615w4OvgZA==",
- "hJSP7CostefBkJrwVEjKHA==",
- "9oQ/SVNJ4Ye9lq8AaguGAQ==",
- "n7Bns42aTungqxKkRfQ5OQ==",
- "K5lhaAIZkGeP5rH2ebSJFw==",
- "ZaPsR9X77SNt7dLjMJUh8A==",
- "18ndtDM9UaNfBR1cr3SHdA==",
- "0QbH4oI8IjZ9BRcqRyvvDQ==",
- "J/eAtAPswMELIj8K2ai+Xg==",
- "qenHZKKlTUiEFv6goKM/Mw==",
- "vjrSYGUpeKOtJ2cNgLFg2g==",
- "DA+3fjr7mgpwf6BZcExj0w==",
- "rh7bzsTQ1UZjG7amysr0Gg==",
- "tFMJRXfWE9g78O1uBUxeqQ==",
- "e/nWuo5YalCAFKsoJmFyFA==",
- "gqehq46BhFX2YLknuMv02w==",
- "Uudn69Kcv2CGz2FbfJSSEA==",
- "Otz/PgYOEZ1CQDW54FWJIQ==",
- "IwfeA6d0cT4nDTCCRhK+pA==",
- "jgNijyoj2JrQNSlUv4gk4A==",
- "KzWdWPP2gH0DoMYV4ndJRg==",
- "pv/m2mA/RJiEQu2Qyfv9RA==",
- "ATmMzriwGLl+M3ppkfcZNA==",
- "tVvWdA+JqH0HR2OlNVRoag==",
- "n6QVaozMGniCO0PCwGQZ6w==",
- "gU3gu8Y5CYVPqHrZmLYHbQ==",
- "cBBOQn7ZjxDku0CUrxq2ng==",
- "w+jzM0I5DRzoUiLS/9QIMQ==",
- "MLlVniZ08FHAS5xe+ZKRaA==",
- "wMyJLQJdmrC2TSeFkIuSvQ==",
- "dG98w8MynOoX7aWmkvt+jg==",
- "zm+z+OOyHhljV2TjA3U9zw==",
- "Tk5MAqd1gyHpkYi8ErlbWg==",
- "g6zSo8BvLuKqdmBFM1ejLA==",
- "d0VAZLbLcDUgLgIfT1GmVQ==",
- "SNPYH4r/J9vpciGN2ybP5Q==",
- "XA2hUgq3GVPpxtRYiqnclg==",
- "fVCRaPsTCKEVLkoF4y3zEw==",
- "FpgdsQ2OG+bVEy3AeuLXFQ==",
- "JquDByOmaQEpFb47ZJ4+JA==",
- "e369ZIQjxMZJtopA//G55Q==",
- "Nsd+DfRX6L54xs+iWeMjCQ==",
- "+/UCpAhZhz368iGioEO8aQ==",
- "e5l9ZiNWXglpw6nVCtO8JQ==",
- "Cl1u5nGyXaoGyDmNdt38Bw==",
- "6sNP0rzCCm3w976I2q2s/w==",
- "qcpeZWUlPllQYZU6mHVwUw==",
- "kzYddqiMsY3EYrpxve2/CQ==",
- "3iC21ByW/YVL+pSyppanWw==",
- "3HPOzIZxoaQAmWRy9OkoSg==",
- "xsCZVhCk2qJmOqvUjK3Y8Q==",
- "i2sSvrTh/RdLJX0uKhbrew==",
- "7Y87wVJok20UfuwkGbXxLg==",
- "ibsb1ncaLZXAYgGkMO7tjQ==",
- "+VfRcTBQ80KSeJRdg0cDfw==",
- "kgKWQJJQKLUuD2VYKIKvxA==",
- "ARKIvf4+zRF8eCvUITWPng==",
- "1fztTtQWNMIMSAc5Hr6jMQ==",
- "md6zNd7ZBn3qArYqQz7/fw==",
- "kvAaIJb+aRAfKK104dxFAA==",
- "UIXytIHyVODxlrg+eQoARA==",
- "Dk0L/lQizPEb3Qud6VHb1Q==",
- "64YsV2qeDxk2Q6WK/h7OqA==",
- "90dtIMq0ozJXezT2r79vMQ==",
- "wy/Z8505o4sVovk4UuBp1A==",
- "ytDXLDBqWiU1w3sTurYmaw==",
- "9pk75mBzhmcdT+koHvgDlw==",
- "DQeib845UqBMEl96sqsaSg==",
- "UPYR575ASaBSZIR3aX1IgQ==",
- "swsVVsPi/5aPFBGP+jmPIw==",
- "1cj1Fpd3+UiBAOahEhsluA==",
- "ifuJCv9ZA84Vz1FYAPsyEA==",
- "uu+ncs63SdQIvG6z4r7Q3Q==",
- "UvC1WADanMrhT+gPp/yVqA==",
- "llOvGOUDVfX68jKnAlvVRA==",
- "SusSOsWNoAerAIMBVWHtfA==",
- "VznvTPAAwAev+yhl9oZT0w==",
- "luR/kvHLwA6tSdLeTM4TzA==",
- "PcdBtV8pfKU0YbDpsjPgwg==",
- "5l6kDfjtZjkTZPJvNNOVFw==",
- "4FBBtWPvqJ3dv4w25tRHiQ==",
- "JJbzQ/trOeqQomsKXKwUpQ==",
- "0bj069wXgEJbw7dpiPr8Tg==",
- "tejpAZp7y32SO2+o4OGvwQ==",
- "kq26VyDyJTH/eM6QvS2cMw==",
- "+zBkeHF4P8vLzk1iO1Zn3Q==",
- "BzkNYH03gF/mQY71RwO3VA==",
- "RnxOYPSQdHS6fw4KkDJtrA==",
- "65KhGKUBFQubRRIEdh9SwQ==",
- "k1DPiH6NkOFXP/r3N12GyA==",
- "DqzWt1gfyu/e7RQl5zWnuQ==",
- "gnez1VrH+UHT8C/SB9qGdA==",
- "vZtL0yWpSIA+9v8i23bZSg==",
- "FNvQqYoe0s/SogpAB7Hr1Q==",
- "6nwR+e9Qw0qp8qIwH9S/Mg==",
- "BPT4PQxeQcsZsUQl33VGmg==",
- "rOYeIcB+Rg5V6JG2k4zS2w==",
- "Je1UESovkBa9T6wS0hevLw==",
- "HFHMGgfOeO0UPrray1G+Zw==",
- "NBmB/cQfS+ipERd7j9+oVg==",
- "iIm8c9uDotr87Aij+4vnMw==",
- "S3VQa6DH+BdlSrxT/g6B5g==",
- "BwRA+tMtwEvth28IwpZx+w==",
- "vg3jozLXEmAnmJwdfcEN0g==",
- "gW0oKhtQQ7BxozxUWw5XvQ==",
- "Q6vGRQiNwoyz7bDETGvi5g==",
- "Ak3rlzEOds6ykivfg39xmw==",
- "G4qzBI1sFP2faN+tlRL/Bw==",
- "ND9l4JWcncRaSLATsq0LVw==",
- "yQmNZnp/JZywbBiZs3gecA==",
- "ZoNSxARrRiKZF5Wvpg7bew==",
- "GhpJfRSWZigLg/azTssyVA==",
- "QyyiJ5I/OZC50o89fa5EmQ==",
- "4kj0S8XlmhHXoUP7dQItUw==",
- "Dt8Q5ORzTmpPR2Wdk0k+Aw==",
- "/hFhjFGJx2wRfz6hyrIpvA==",
- "eFimq+LuHi42byKnBeqnZQ==",
- "JrKGKAKdjfAaYeQH8Y2ZRQ==",
- "JFFeXsFsMA59iNtZey7LAA==",
- "91SdBFJEZ65M+ixGaprY/A==",
- "+S+WXgVDSU1oGmCzGwuT3g==",
- "1X14kHeKwGmLeYqpe60XEA==",
- "4xojeUxTFmMLGm6jiMYh/Q==",
- "+1e7jvUo8f2/2l0TFrQqfA==",
- "8WU1vLKV1GhrL7oS9PpABg==",
- "DYWCPUq/hpjr6puBE7KBHg==",
- "birqO8GOwGEI97zYaHyAuw==",
- "6e8boFcyc8iF0/tHVje4eQ==",
- "FLvED9nB9FEl9LqPn7OOrA==",
- "ji306HRiq965zb8EZD2uig==",
- "AklOdt9/2//3ylUhWebHRw==",
- "VGRCSrgGTkBNb8sve0fYnQ==",
- "oqlkgrYe9aCOwHXddxuyag==",
- "KXuFON8tMBizNkCC48ICLA==",
- "9aKH1u5+4lgYhhLztQ4KWA==",
- "3hVslsq98QCDIiO40JNOuA==",
- "OOS6wQCJsXH8CsWEidB35A==",
- "YXHQ3JI9+oca8pc/jMH6mA==",
- "V9vkAanK+Pkc4FGAokJsTA==",
- "OFLn4wun6lq484I7f6yEwg==",
- "3WVBP9fyAiBPZAq3DpMwOQ==",
- "5gGoDPTc/sOIDLngmlEq4A==",
- "E2lvMXqHdTw0x+KCKVnblg==",
- "f1Gs++Iilgq9GHukcnBG3w==",
- "uIkVijg7RPi/1j7c18G1qA==",
- "9T7gB0ZkdWB0VpbKIXiujQ==",
- "KCJJfgLe00+tjSfP6EBcUg==",
- "WbAdlac/PhYUq7J2+n5f+w==",
- "GLnS9wDCje7TOMvBX9jJVA==",
- "VAg/aU5nl72O+cdNuPRO4g==",
- "kzTl7WH/JXsX1fqgnuTOgw==",
- "1HDgfU7xU7LWO/BXsODZAQ==",
- "D0W5F7gKMljoG5rlue1jrg==",
- "9reBKZ1Rp6xcdH1pFQacjw==",
- "SSKhl2L3Mvy93DcZulADtA==",
- "hlu7os0KtAkpBTBV6D2jyQ==",
- "sfte/o9vVNyida/yLvqADA==",
- "gYGQBLo5TdMyXks0LsZhsQ==",
- "dNq2InSVDGnYXjkxPNPRxA==",
- "fiv0DJivQeqUkrzDNlluRw==",
- "msstzxq++XO0AqNTmA7Bmg==",
- "DCjgaGV5hgSVtFY5tcwkuA==",
- "aMmrAzoRWLOMPHhBuxczKg==",
- "qNOSm15bdkIDSc/iUr+UTQ==",
- "2nSTEYzLK77h5Rgyti+ULQ==",
- "BhKO1s1O693Fjy1LItR/Jw==",
- "kRnBEH6ILR5GNSmjHYOclw==",
- "R97chlspND/sE9/HMScXjQ==",
- "1Oykse0jQVbuR3MvW5ot4A==",
- "Dmyb+a7/QFsU4d2cVQsxDw==",
- "W5now3RWSzzMDAxsHSl++Q==",
- "IrDuBrVu1HWm0BthAHyOLQ==",
- "V6zyoX6MERIybGhhULnZiw==",
- "ZQSDYgpsimK+lYGdXBWE/w==",
- "lV70RNlE++04G1KFB3BMXA==",
- "QmSBVvdk0tqH9RAicXq2zA==",
- "qNyy6Fc0b8oOMWqqaliZ/w==",
- "xvipmmwKdYt4eoKvvRnjEg==",
- "Q7Df6zGwvb4rC+EtIKfaSw==",
- "n1M2dgFPpmaICP+JwxHUug==",
- "1k8tL2xmGFVYMgKUcmDcEw==",
- "fFvXa1dbMoOOoWZdHxPGjw==",
- "UP9mmAKzeQqGhod7NCqzhg==",
- "PMCWKgog/G+GFZcIruSONw==",
- "dnvatwSEcl73ROwcZ4bbIQ==",
- "hY82j+sUQQRpCi6CCGea5A==",
- "QoUC9nyK1BAzoUVnBLV2zw==",
- "+aF4ilbjQbLpAuFXQEYMWQ==",
- "XTCcsVfEvqxnjc0K5PLcyw==",
- "ML7ipnY/g8mA1PUIju1j8Q==",
- "tOkYq1BZY152/7IJ6ZYKUg==",
- "2bsIpvnGcFhTCSrK9EW1FQ==",
- "Af9j1naGtnZf0u1LyYmK1w==",
- "ZmblZauRqO5tGysY3/0kDw==",
- "PF0lpolQQXlpc3qTLMBk8w==",
- "emVLJVzha7ui5OFHPJzeRQ==",
- "gR0sgItXIH8hE4FVs9Q07w==",
- "PTW+fhZq/ErxHqpM0DZwHQ==",
- "g0kHTNRI7x/lAsr92EEppw==",
- "24H9q+E8pgCEdFS7JO5kzQ==",
- "HtDXgMuF8PJ1haWk88S0Ew==",
- "pulldyBt2sw6QDvTrCh6zw==",
- "ehwc2vvwNUAI7MxU4MWQZw==",
- "enj9VEzLbmeOyYugTmdGfQ==",
- "auvG6kWMnhCMi7c7e9eHrw==",
- "R36O31Pj8jn0AWSuqI7X2Q==",
- "3AVYtcIv7A5mVbVnQMaCeA==",
- "T9WoUJNwp8h4Yydixbx6nA==",
- "t0WN8TwMLgi8UVEImoFXKg==",
- "mS99D+CXhwyfVt8xJ+dJZA==",
- "AFdelaqvxRj6T3YdLgCFyg==",
- "Lu02ic/E94s42A14m7NGCA==",
- "7w3b73nN/fIBvuLuGZDCYQ==",
- "O209ftgvu0vSr0UZywRFXA==",
- "MQvAr+OOfnYnr/Il/2Ubkg==",
- "e5txnNRcGs2a9+mBFcF1Qg==",
- "YA0kMTJ82PYuLA4pkn4rfw==",
- "QIKjir/ppRyS63BwUcHWmw==",
- "P3y5MoXrkRTSLhCdLlnc4A==",
- "WY7mCUGvpXrC8gkBB46euw==",
- "g0GbRp2hFVIdc7ct7Ky7ag==",
- "Cv079ZF55RnbsDT27MOQIA==",
- "cvMJ714elj/HUh89a9lzOQ==",
- "9inw7xzbqAnZDKOl/MfCqA==",
- "F58ktE4O0f7C9HdsXYm+lw==",
- "CsPkyTZADMnKcgSuNu1qxg==",
- "mAzsVkijuqihhmhNTTz65g==",
- "FxnbKnuDct4OWcnFMT/a5w==",
- "P5wS+xB8srW4a5KDp/JVkA==",
- "ctJYJegZhG42i+vnPFWAWw==",
- "OrqJKjRndcZ8OjE3cSQv7g==",
- "aXqiibI6BpW3qilV6izHaQ==",
- "BA18GEAOOyVXO2yZt2U35w==",
- "saEpnDGBSZWqeXSJm34eOA==",
- "CUEueo8QXRxkfVdfNIk/gg==",
- "H0UMAUfHFQH92A2AXRCBKA==",
- "CT9g8mKsIN/VeHLSTFJcNQ==",
- "E4NtzxQruLcetC23zKVIng==",
- "203EqmJI9Q4tWxTJaBdSzA==",
- "Do3aqbRKtmlQI2fXtSZfxQ==",
- "JaYQXntiyznQzrTlEeZMIw==",
- "VK95g27ws2C6J2h/7rC2qA==",
- "CQ0PPwgdG3N6Ohfwx1C8xA==",
- "/MeHciFhvFzQsCIw39xIZA==",
- "u5cUPxM6/spLIV8VidPrAA==",
- "OwArFF1hpdBupCkanpwT+Q==",
- "PdBgXFq5mBqNxgCiqaRnkw==",
- "lC5EumoIcctvxYqwELqIqw==",
- "xoPSM86Se+1hHX0y3hhdkw==",
- "F5bs0GGWBx9eBwcJJpXbqg==",
- "1mw6LfTiirFyfjejf8QNGA==",
- "daBhAvmE9shDgmciDAC5eg==",
- "AvdeYb9XNOUFWiiz+XGfng==",
- "JJJkp1TpuDx5wrua2Wml7g==",
- "3y5Xk65ShGvWFbQxcZaQAQ==",
- "l6QHU5JsJExNoOnqxBPVbw==",
- "X2YfnPXgF2VHVX95ZcBaxQ==",
- "g6udffWh7qUnSIo1Ldn3eA==",
- "V2P75JFB4Se9h7TCUMfeNA==",
- "IUZ5aGpkJ9rLgSg6oAmMlw==",
- "pyrUqiZ98gVXxlXQNXv5fA==",
- "83ERX2XJV3ST4XwvN7YWCg==",
- "eJDUejE/Ez/7kV+S74PDYg==",
- "M9oqlPb63e0kZE0zWOm+JQ==",
- "0rTYcuVYdilO7zEfKrxY3A==",
- "rfPTskbnoh3hRJH6ZAzQRg==",
- "QtD35QhE8sAccPrDnhtQmQ==",
- "jpNUgFnanr9Sxvj2xbBXZw==",
- "nykEOLL/o7h0cs0yvdeT2g==",
- "wX2URK6eDDHeEOF3cgPgHA==",
- "jqPQ0aOuvOJte/ghI1RVng==",
- "nHTsDl0xeQPC5zNRnoa0Rw==",
- "mNv2Q67zePjk/jbQuvkAFA==",
- "HjlPM2FQWdILUXHalIhQ5w==",
- "cHkOsVd80Rgwepeweq4S1g==",
- "kTCHqcb3Cos51o8cL+MXcg==",
- "nvmBgp0YlUrdZ05INsEE8Q==",
- "kFrRjz7Cf2KvLtz9X6oD+w==",
- "Tmx0suRHzlUK4FdBivwOwA==",
- "bG+P+p34t/IJ1ubRiWg6IA==",
- "uESeJe/nYrHCq4RQbrNpGA==",
- "ehfPlu6YctzzpQmFiQDxGA==",
- "ZH5Es/4lJ+D5KEkF1BVSGg==",
- "HHxn4iIQ7m0tF1rSd+BZBg==",
- "DQJRsUwO1fOuGlkgJavcwQ==",
- "HITIVoFoWNg04NExe13dNA==",
- "MeKXnEfxeuQu9t3r/qWvcw==",
- "Y7OofF9eUvp7qlpgdrzvkg==",
- "XSb71ae0v+yDxNF5HJXGbQ==",
- "p8W1LgFuW6JSOKjHkx3+aA==",
- "y2JOIoIiT9cV1VxplZPraQ==",
- "MN94B0r5CNAF9sl3Kccdbw==",
- "Q1pdQadt12anX1QRmU2Y/A==",
- "JIC8R48jGVqro6wmG2KXIw==",
- "eWgLAqJOU+fdn8raHb9HCw==",
- "5CMadLqS2KWwwMCpzlDmLw==",
- "H1y2iXVaQYwP0SakN6sa+Q==",
- "CUCjG2UaEBmiYWQc6+AS1Q==",
- "yV3IbbTWAbHMhMGVvgb/ZQ==",
- "80PCwYh4llIKAplcDvMj4g==",
- "fgdUFvQPb5h+Rqz8pzLsmw==",
- "2SI4F7Vvde2yjzMLAwxOog==",
- "kJdY3XEdJS/hyHdR+IN0GA==",
- "IKgNa2oPaFVGYnOsL+GC5Q==",
- "eXFOya6x5inTdGwJx/xtUQ==",
- "uTA0XbiH3fTeVV7u5z0b3w==",
- "onFcHOO1c3pDdfCb5N4WkQ==",
- "Slu3z535ijcs5kzDnR7kfA==",
- "SElc2+YVi3afE1eG1MI7dQ==",
- "ND2hYtAIQGMxBF7o7+u7nQ==",
- "Pv9FWQEDLKnG/9K9EIz4Gw==",
- "6CjtF1S2Y6RCbhl7hMsD+g==",
- "rs2QrN4qzAHCHhkcrAvIfA==",
- "eTMPXa60OTGjSPmvR4IgGw==",
- "pvXHwJ3dwf9GDzfDD9JI3g==",
- "CRmAj3JcasAb4iZ9ZbNIbw==",
- "rcY4Ot40678ByCfqvGOGdg==",
- "l4ddTxbTCW5UmZW+KRmx6A==",
- "NKRzJndo2uXNiNppVnqy1g==",
- "0NrvBuyjcJ2q6yaHpz/FOA==",
- "3YXp1PmMldUjBz3hC6ItbA==",
- "CmVD6nh8b/04/6JV9SovlA==",
- "HjyxyL0db2hGDq2ZjwOOhg==",
- "4PBaoeEwUj79njftnYYqLg==",
- "vFFzkWgGyw6OPADONtEojQ==",
- "czBWiYsQtNFrksWwoQxlOw==",
- "9iB7+VwXRbi6HLkWyh9/kg==",
- "zwY6tCjjya/bgrYaCncaag==",
- "mW6TCje9Zg2Ep7nzmDjSYQ==",
- "5LJqHFRyIwQKA4HbtqAYQQ==",
- "INNBBin5ePwTyhPIyndHHg==",
- "dChBe9QR29ObPFu/9PusLg==",
- "1dhq3ozNCx0o4dV1syLVDA==",
- "nyaekSYTKzfSeSfPrB114Q==",
- "TfNHjSTV8w6Pg6+FaGlxvA==",
- "m/Lp4U75AQyk9c8cX14HJg==",
- "uU1TX5DoDg6EcFKgFcn0GA==",
- "B+TsxQZf0IiQrU8X9S4dsQ==",
- "6b7ue29cBDsvmj1VSa5njw==",
- "RvXWAFwM+mUAPW1MjPBaHA==",
- "pdaY6kZ8+QqkMOInvvACNA==",
- "7nr3zyWL+HHtJhRrCPhYZA==",
- "BXGlq54wIH6R3OdYfSSDRw==",
- "b06KGv5zDYsTxyTbQ9/eyA==",
- "8ylI1AS3QJpAi3I/NLMYdg==",
- "0fpe9E6m3eLp/5j5rLrz2Q==",
- "Qrh7OEHjp80IW+YzQwzlJg==",
- "lqhgbgEqROAdfzEnJ17eXA==",
- "Dulw855DfgIwiK7hr3X8vg==",
- "wsp+vmW8sEqXYVURd/gjHA==",
- "VoPth5hDHhkQcrQTxHXbuw==",
- "TgWe70YalDPyyUz6n88ujg==",
- "9lLhHcrPWI4EsA4fHIIXuw==",
- "UymZUnEEQWVnLDdRemv+Tw==",
- "qnkFUlJ8QT322JuCI3LQgg==",
- "/p/aCTIhi1bU0/liuO/a2Q==",
- "hWoxz5HhE50oYBNRoPp1JQ==",
- "88tB/HgUIUnqWXEX++b5Aw==",
- "Z8T1b9RsUWf59D06MUrXCQ==",
- "BZTzHJGhzhs3mCXHDqMjnQ==",
- "XfY+QUriCAA1+3QAsswdgg==",
- "TZ3ATPOFjNqFGSKY3vP2Hw==",
- "cl4t9FXabQg7tbh1g7a0OA==",
- "9SgfpAY0UhNC6sYGus9GgQ==",
- "d/Wd3Ma1xYyoMByPQnA9Cw==",
- "DDitrRSvovaiXe2nfAtp4g==",
- "s+eHg5K9zZ2Jozu5Oya9ZQ==",
- "z3L2BNjQOMOfTVBUxcpnRA==",
- "v4xIYrfPGILEbD/LwVDDzA==",
- "HoaBBw2aPCyhh0f5GxF+/Q==",
- "i9IRqAqKjBTppsxtPB7rdw==",
- "cWUg7AfqhiiEmBIu+ryImA==",
- "E+02smwQGBIxv42LIF2Y4Q==",
- "W4CfeVp9mXgk04flryL7iA==",
- "9SUOfKtfKmkGICJnvbIDMg==",
- "xweGAZf+Yb3TtwR/sGmGIA==",
- "EJgedRYsZPc4cT9rlwaZhg==",
- "wv4NC9CIpwuGf/nOQYe/oA==",
- "ZXeMG5eqQpZO/SGKC4WQkA==",
- "bzXXzQGZs8ustv0K4leklA==",
- "RkQK9S1ezo+dFYHQP57qrw==",
- "mrinv7KooPQPrLCNTRWCFg==",
- "qIUJPanWmGzTD1XxvHp+6w==",
- "Js7g8Dr6XsnGURA4UNF0Ug==",
- "dpSTNOCPFHN5yGoMpl1EUA==",
- "ugY8rTtJkN4CXWMVcRZiZw==",
- "rqHKB91H3qVuQAm+Ym5cUA==",
- "UjmDFO7uzjl4RZDPeMeNyg==",
- "cu4ZluwohhfIYLkWp72pqA==",
- "ZydKlOpn2ySBW0G3uAqwuw==",
- "LWd0+N3M94n81qd346LfJQ==",
- "VbHoWmtiiPdABvkbt+3XKQ==",
- "J4MC9He6oqjOWsYQh9nl3Q==",
- "ahAbmGJZvUOXrcK6OydNGQ==",
- "Byhi4ymFqqH8uIeoMRvPug==",
- "LSN9GmT6LUHlCAMFqpuPIA==",
- "IAMInfSYb76GxDlAr1dsTg==",
- "qYHdgFAXhF/XcW4lxqfvWQ==",
- "26+yXbqI+fmIZsYl4UhUzw==",
- "AwPTZpC28NJQhf5fNiJuLA==",
- "SESKbGF35rjO64gktmLTWA==",
- "YVlRQHQglkbj3J2nHiP/Hw==",
- "DdaT4JLC7U0EkF50LzIj9w==",
- "G0LChrb0OE5YFqsfTpIL1Q==",
- "5Yrj6uevT8wHRyqqgnSfeg==",
- "NmWmDxwK5FpKlZbo0Rt8RA==",
- "iUsUCB0mfRsE9KPEQctIzw==",
- "Tm4zk2Lmg8w4ITMI31NfTA==",
- "Vu0E+IJXBnc25x4n41kQig==",
- "6wkfN8hyKmKU6tG3YetCmw==",
- "trjM81KANPZrg9iSThWx6Q==",
- "iGuY4VxcotHvMFXuXum7KA==",
- "ICPdBCdONUqPwD5BXU5lrw==",
- "alqHQBz8V446EdzuVfeY5Q==",
- "74FW/QYTzr/P1k6QwVHMcw==",
- "avZp5K7zJvRvJvpLSldNAw==",
- "TIKadc6FAaRWSQUg5OATgg==",
- "PfkWkSbAxIt1Iso0znW0+Q==",
- "Z+bsbVP91KrJvxrujBLrrQ==",
- "mrxlFD3FBqpSZr1kuuwxGg==",
- "nUgYO7/oVNSX8fJqP2dbdg==",
- "tVhXk9Ff3wAg56FbdNtcFg==",
- "DdiNGiOSoIZxrMrGNvqkXw==",
- "CDsanJz7e3r/eQe+ZYFeVQ==",
- "wVfSZYjMjbTsD2gaSbwuqQ==",
- "6c0iuya20Ys8BsvoI4iQaQ==",
- "qCPfJTR8ecTw6u6b1yHibA==",
- "fZrj3wGQSt8RXv0ykJROcQ==",
- "gR3B8usSEb0NLos51BmJQg==",
- "vTAmgfq3GxL4+ubXpzwk5w==",
- "jLkmUZ6fV56GfhC0nkh4GA==",
- "3v09RHCPTLUztqapThYaHg==",
- "nULSbtw2dXbfVjZh33pDiA==",
- "IHhyR6+5sZXTH+/NrghIPg==",
- "tnUtJ/DQX9WaVJyTgemsUA==",
- "7xTKFcog69nTmMfr5qFUTA==",
- "IshzWega6zr3979khNVFQQ==",
- "Ng5v/B9Z10TTfsDFQ/XrXQ==",
- "hnCUnoxofUiqQvrxl73M8w==",
- "VPa7DG6v7KnzMvtJPb88LQ==",
- "4LtQrahKXVtsbXrEzYU1zQ==",
- "Ev/xjTi7akYBI7IeZJ4Igw==",
- "41WEjhYUlG6jp2UPGj11eQ==",
- "JvXTdChcE3AqMbFYTT3/wg==",
- "2rOkEVl90EPqfHOF5q2FYw==",
- "mjFBVRJ7TgnJx+Q74xllPg==",
- "Uy4QI8D2y1bq/HDNItCtAw==",
- "wMOE/pEKVIklE75xjt6b6w==",
- "ZcuIvc8fDI+2uF0I0uLiVA==",
- "CX/N/lHckmAtHKysYtGdZA==",
- "j8to4gtSIRYpCogv2TESuQ==",
- "iS9wumBV5ktCTefFzKYfkA==",
- "ewPT4dM12nDWEDoRfiZZnA==",
- "vWn9OPnrJgfPavg4D6T/HQ==",
- "J/PNYu4y6ZMWFFXsAhaoow==",
- "catI+QUNk3uJ+mUBY3bY8Q==",
- "F8tEIT5EhcvLNRU5f0zlXQ==",
- "zyA9f5J7mw5InjhcfeumAQ==",
- "MlOOZOwcRGIkifaktEq0aQ==",
- "Pt3i49uweYVgWze3OjkjJA==",
- "sfIClgTMtZo9CM9MHaoqhQ==",
- "HeQbUuBM9sqfXFXRBDISSw==",
- "SFn78uklZfMtKoz2N0xDaQ==",
- "H6j2nPbBaxHecXruxiWYkA==",
- "fU32wmMeD44UsFSqFY0wBA==",
- "hDILjSpTLqJpiSSSGu445A==",
- "ieEAgvK9LsWh2t6DsQOpWA==",
- "xfjBQk3CrNjhufdPIhr91A==",
- "j+8/VARfbQSYhHzj0KPurQ==",
- "/zFLRvi75UL8qvg+a6zqGg==",
- "U0KmEI6e5zJkaI4YJyA5Ew==",
- "uXvr6vi5kazZ9BCg2PWPJA==",
- "jEqP0dyHKHiUjZ9dNNGTlQ==",
- "1xWx5V3G9murZP7srljFmA==",
- "OIwtfdq37eQ0qoXuB2j7Hw==",
- "fUAy3f9bAglLvZWvkO2Lug==",
- "duRFqmvqF93uf/vWn8aOmg==",
- "ysRQ+7Aq7eVLOp88KnFVMA==",
- "CkZUmKBAGu0FLpgPDrybpw==",
- "TrLmfgwaNATh24eSrOT+pw==",
- "83wtvSoSP9FVBsdWaiWfpA==",
- "pUfWmRXo70yGkUD/x5oIvA==",
- "PybPZhJErbRTuAafrrkb3g==",
- "8hsfXqi4uiuL+bV1VrHqCw==",
- "TVlHoi8J7sOZ2Ti7Dm92cQ==",
- "za4rzveYVMFe3Gw531DQJQ==",
- "JKphO0UYjFqcbPr6EeBuqg==",
- "hqeSvwu8eqA072iidlJBAw==",
- "bUF0JIfS4uKd3JZj2xotLQ==",
- "hKOsXOBoFTl/K4xE+RNHDA==",
- "JHBjKpCgSgrNNACZW1W+1w==",
- "Rrq0ak9YexLqqbSD4SSXlw==",
- "+NmjwjsPhGJh9bM10SFkLw==",
- "xMIHeno2qj3V8q9H1xezeg==",
- "TcFinyBrUoAEcLzWdFymow==",
- "Rvchz/xjcY9uKiDAkRBMmA==",
- "TYlnrwgyeZoRgOpBYneRAg==",
- "PbnxuVerGwHyshkumqAARg==",
- "iFtadcw8v6betKka9yaJfg==",
- "7wgT9WIiMVcrj48PVAMIgw==",
- "2HHqeGRMfzf3RXwVybx+ZQ==",
- "tdgI9v7cqJsgCAeW1Fii1A==",
- "4ZFYKa7ZgvHyZLS6WpM8gA==",
- "gB8wkuIzvuDAIhDtNT1gyA==",
- "g1ELwsk6hQ+RAY1BH640Pg==",
- "UZoibx+y1YJy/uRSa9Oa2w==",
- "yS/yMnJDHW0iaOsbj4oPTg==",
- "JzW+yhrjXW1ivKu3mUXPXg==",
- "/wIZAye9h1TUiZmDW0ZmYA==",
- "YK+q7uJObkQZvOwQ9hplMg==",
- "Rs8deApkoosIJSfX7NXtAA==",
- "MsCloSmTFoBpm7XWYb+ueQ==",
- "3ltw31yJuAl4VT6MieEXXw==",
- "1+qmrbC8c7MJ6pxmDMcKuA==",
- "AYxGETZs477n2sa1Ulu/RQ==",
- "Q0TJZxpn3jk67L7N+YDaNA==",
- "OGpsXRHlaN8BvZftxh1e7A==",
- "UbABE6ECnjB+9YvblE9CYw==",
- "kZ0D191c/uv4YMG15yVLDw==",
- "QWURrsEgxbJ8MWcaRmOWqw==",
- "xiFlcSfa/gnPiO+LwbixcQ==",
- "Szko0IPE7RX2+mfsWczrMg==",
- "Ugt8HVC/aUzyWpiHd0gCOQ==",
- "8j9GVPiFdfIRm/+ho7hpoA==",
- "KR401XBdgCrtVDSaXqPEiA==",
- "d0NBFiwGlQNclKObRtGVMQ==",
- "XEwOJG24eaEtAuBWtMxhwg==",
- "0Y6iiZjCwPDwD/CwJzfioQ==",
- "MvMbvZNKbXFe2XdN+HtnpQ==",
- "fsoXIbq0T0nmSpW8b+bj+g==",
- "Uje3Ild84sN41JEg3PEHDg==",
- "i6ZYpFwsyWyMJNgqUMSV1A==",
- "+P5q4YD1Rr5SX26Xr+tzlw==",
- "z4oKy2wKH+sbNSgGjbdHGw==",
- "XwKWd03sAz8MmvJEuN08xA==",
- "Xv0mNYedaBc57RrcbHr9OA==",
- "9oUawSwUGOmb0sDn3XS6og==",
- "9RGIQ2qyevNbSSEF36xk/A==",
- "q8YF9G2jqydAxSqwyyys5Q==",
- "m5JIUETVXcRza4VL4xlJbg==",
- "aRpdnrOyu5mWB1P5YMbvOA==",
- "rM/BOovNgnvebKMxZQdk7g==",
- "fQS0jnQMnHBn7+JZWkiE/g==",
- "gAoV4BZYdW1Wm712YXOhWQ==",
- "hCzsi1yDv9ja5/o7t94j9Q==",
- "CoLvjQDQGldGDqRxfQo+WQ==",
- "pfGcaa49SM3S6yJIPk/EJQ==",
- "yYp4iuI5f/y/l1AEJxYolQ==",
- "Jj4IrSVpqQnhFrzNvylSzA==",
- "4jeOFKuKpCmMXUVJSh9y0g==",
- "+NMUaQ7XPsAi0rk7tTT9wQ==",
- "Jt4Eg6MJn8O4Ph/K2LeSUA==",
- "CiiUeJ0LeWfm7+gmEmYXtg==",
- "c5Tc7rTFXNJqYyc0ppW+Iw==",
- "4KJZPCE9NKTfzFxl76GWjg==",
- "aXs9qTEXLTkN956ch3pnOA==",
- "f5Xo7F1uaiM760Qbt978iw==",
- "wpZqFkKafFpLcykN2IISqg==",
- "vIORTYSHFIXk5E2NyIvWcQ==",
- "prOsOG0adI4o+oz50moipw==",
- "blygTgAHZJ3NzyAT33Bfww==",
- "rBt6L/KLT7eybxKt5wtFdg==",
- "vMuaLvAntJB5o7lmt/kVXA==",
- "iujlt9fXcUXEYc+T2s5UjA==",
- "LyYPOZKm8bBegMr5NTSBfg==",
- "ZtWvgitOSRDWq7LAKYYd4Q==",
- "kh51WUI5TRnKhur6ZEpRTQ==",
- "VzQ1NwNv9btxUzxwVqvHQg==",
- "8fJLQeIHaTnJ8wGqUiKU6g==",
- "vvEH5A39TTe1AOC11rRCLA==",
- "dihDsG7+6aocG6M9BWrCzQ==",
- "3jqsY8/xTWELmu/az3Daug==",
- "mpOtwBvle+nyY6lUBwTemw==",
- "E1CvxFbuu9AYW604mnpGTw==",
- "1LPC0BzhJbepHTSAiZ3QTw==",
- "XpGXh76RDgXC4qnTCsnNHA==",
- "3Gg9N7vjAfQEYOtQKuF/Eg==",
- "+WpF8+poKmHPUBB4UYh/ig==",
- "UNt7CNMtltJWq8giDciGyA==",
- "RIZYDgXqsIdTf9o2Tp/S7g==",
- "0QCQORCYfLuSbq94Sbt0bQ==",
- "hvsZ5JmVevK1zclFYmxHaw==",
- "3+9nURtBK3FKn0J9DQDa3g==",
- "jdVMQqApseHH3fd91NFhxg==",
- "VX+cVXV8p9i5EBTMoiQOQQ==",
- "I5qDndyelK4Njv4YrX7S6w==",
- "rWliqgfZ3/uCRBOZ9sMmdA==",
- "vwno3vugCvt6ooT3CD4qIQ==",
- "cffrYrBX3UQhfX1TbAF+GQ==",
- "nOiwBFnXxCBfPCHYITgqNg==",
- "LQttmX92SI94+hDNVd8Gtw==",
- "iCF+GWw9/YGQXsOOPAnPHQ==",
- "nwtCsN1xEYaHvEOPzBv+qQ==",
- "CQpJFrpOvcQhsTXIlJli+Q==",
- "tYeIZjIm0tVEsYxH1iIiUQ==",
- "iCnm5fPmSmxsIzuRK6osrA==",
- "tX8X8KoxUQ8atFSCxgwE1Q==",
- "hZlX6qOfwxW5SPfqtRqaMw==",
- "2aIx9UdMxxZWvrfeJ+DcTw==",
- "TlJizlASbPtShZhkPww4UA==",
- "p+bx+/WQWALXEBCTnIMr4w==",
- "4VR5LiXLew6Nyn91zH9L4w==",
- "bfUD03N2PRDT+MZ+WFVtow==",
- "cTvDd8okNUx0RCMer6O8sw==",
- "49jZr/mEW6fvnyzskyN40w==",
- "vHmQUl4WHXs1E/Shh+TeyA==",
- "fgXfRuqFfAu8qxbTi4bmhA==",
- "Wn+Vj4eiWx0WPUHr3nFbyA==",
- "2SwIiUwT4vRZPrg7+vZqDA==",
- "nkedTagkmf6YE4tEY+0fKw==",
- "8nOTDhFyZ8YUA4b6M5p84w==",
- "qnzWszsyJhYtx8wkMN6b1g==",
- "ka7pMp8eSiv92WgAsz2vdA==",
- "pGQEWJ38hb/ZYy2P1+FIuw==",
- "cVhdRFuZaW/09CYPmtNv5g==",
- "prCOYlboBnzmLEBG/OeVrQ==",
- "oIWwTbkVS5DDL47mY9/1KQ==",
- "PKtXc4x4DEjM45dnmPWzyg==",
- "f9ywiGXsz+PuEsLTV3zIbQ==",
- "6G2bD3Y7qbGmfPqH9TqLFA==",
- "DMHmyn2U2n+UXxkqdvKpnA==",
- "XOG1PYgqoG8gVLIbVLTQgg==",
- "1FSrgkUXgZot2CsmbAtkPw==",
- "BxFP+4o6PSlGN78eSVT1pA==",
- "EZVQGsXTZvht1qedRLF8bQ==",
- "eYAQWuWZX2346VMCD6s7/A==",
- "jkUpkLoIXuu7aSH8ZghIAQ==",
- "mXPtbPaoNAAlGmUMmJEWBQ==",
- "HLesnV3DL+FhWF3h6RXe8g==",
- "nDAsSla+9XfAlQSPsXtzPA==",
- "RAECgYZmcF4WxcFcZ4A0Ww==",
- "W+M4BcYNmjj7xAximDGWsA==",
- "ueODvMv/f9ZD8O0aIHn4sg==",
- "cszpMdGbsbe6BygqMlnC9Q==",
- "siHwJx6EgeB1gBT9z/vTyw==",
- "FN7oLGBQGHXXn5dLnr/ElA==",
- "Tud+AMyuFkWYYZ73yoJGpQ==",
- "TuaG3wRdM9BWKAxh2UmAsg==",
- "8CjmgWQSAAGcXX9kz3kssw==",
- "ays5/F7JANIgPHN0vp2dqQ==",
- "PCOGl7GIqbizAKj/sZmlwQ==",
- "rZKD8oJnIj5fSNGiccfcvA==",
- "gFEnTI8os2BfRGqx9p5x8w==",
- "5r1ZsGkrzNQEpgt/gENibw==",
- "1YO9G8qAhLIu2rShvekedw==",
- "6ZKmm7IW7IdWuVytLr68CQ==",
- "mMfn8OaKBxtetweulho+xQ==",
- "GQJxu1SoMBH14KPV/G/KrQ==",
- "IYIP2UBRyWetVfYLRsi1SQ==",
- "Jit0X0srSNFnn8Ymi1EY+g==",
- "ARCWkHAnVgBOIkCDQ19ZuA==",
- "qA0sTaeNPNIiQbjIe1bOgQ==",
- "iGI9uqMoBBAjPszpxjZBWQ==",
- "+L1FDsr5VQtuYc2Is5QGjw==",
- "4XNUmgwxsqDYsNmPkgNQYQ==",
- "Yig+Wh18VIqdsmwtwfoUQw==",
- "uqp92lAqjec8UQYfyjaEZw==",
- "QiozlNcQCbqXtwItWExqJQ==",
- "JFHutgSe1/SlcYKIbNNYwQ==",
- "Y26jxXvl79RcffH8O8b9Ew==",
- "bQ7J5mebp38rfP/fuqQOsg==",
- "HI4ZIE5s8ez8Rb+Mv39FxA==",
- "OzH7jTcyeM7RPVFtBdakpQ==",
- "HLxROy6fx/mLXFTDSX4eLA==",
- "s5RUHVRNAoKMuPR/Jkfc2Q==",
- "X9QAaNjgiOeAWSphrGtyVw==",
- "ALJWKUImVE40MbEooqsrng==",
- "9MDG0WeBPpjGJLEmUJgBWg==",
- "9RXymE9kCkDvBzWGyMgIWA==",
- "vFox1d3llOeBeCUZGvTy0A==",
- "r3lQAYOYhwlLnDWQIunKqg==",
- "2os5s7j7Tl46ZmoZJH8FjA==",
- "O5N2yd+QQggPBinQ+zIhtQ==",
- "ZygAjaN62XhW5smlLkks+Q==",
- "AgDJsaW0LkpGE65Kxk5+IA==",
- "omAjyj1l6gyQAlBGfdxJTw==",
- "fY9VATklOvceDfHZDDk57A==",
- "StpQm/cQF8cT0LFzKUhC5w==",
- "CYJB3qy5GalPLAv1KGFEZA==",
- "coGEgMVs2b314qrXMjNumQ==",
- "DQQB/l55iPN9XcySieNX3A==",
- "6dshA8knH5qqD+KmR/kdSQ==",
- "qyRmvxh8p4j4f+61c10ZFQ==",
- "apWEPWUvMC24Y+2vTSLXoA==",
- "RzX2OfSFEd//LhZwRwzBVw==",
- "NdULoUDGhIolzw1PyYKV0A==",
- "5w/c9WkI/FA+4lOtdPxoww==",
- "bV9r7j2kNJpDCEM5E2339Q==",
- "vbyiKeDCQ4q9dDRI1Q0Ong==",
- "9xIgKpZGqq0/OU6wM5ZSHw==",
- "RYkDwwng6eeffPHxt8iD9A==",
- "w5N/aHbtOIKzcvG3GlMjGA==",
- "3P2aJxV8Trll2GH9ptElYA==",
- "yteeQr3ub2lDXgLziZV+DQ==",
- "yqtj8GfLaUHYv/BsdjxIVw==",
- "NyF+4VRog7etp90B9FuEjA==",
- "uwA6N5LptSXqIBkTO0Jd7Q==",
- "6lVSzYUQ/r0ep4W2eCzFpg==",
- "1d7RPHdZ9qzAbG3Vi9BdFA==",
- "7br49X11xc2GxQLSpZWjKQ==",
- "peMW+rpwmXrSwplVuB/gTA==",
- "RqYpA5AY7mKPaSxoQfI1CA==",
- "dqVw2q2nhCvTcW82MT7z0g==",
- "5S5/asYfWjOwnzYpbK6JDw==",
- "NvkR0inSzAdetpI4SOXGhw==",
- "tIqwBotg052wGBL65DZ+yA==",
- "S4RvORcJ3m6WhnAgV4YfYA==",
- "UAqf4owQ+EmrE45hBcUMEw==",
- "4aPU6053cfMLHgLwAZJRNg==",
- "3Y6/HqS1trYc9Dh778sefg==",
- "ck86G8HsbXflyrK7MBntLg==",
- "GLmWLXURlUOJ+PMjpWEXVA==",
- "jNJQ6otieHBYIXA9LjXprg==",
- "AsAHrIkMgc3RRWnklY9lJw==",
- "FCLQocqxxhJeleARZ6kSPg==",
- "3Leu2Sc+YOntJFlrvhaXeg==",
- "hSkY45CeB6Ilvh0Io4W6cg==",
- "DwrNdmU5VFFf3TwCCcptPA==",
- "u2WQlcMxOACy6VbJXK4FwA==",
- "E9IlDyULLdeaVUzN6eky8g==",
- "EXveRXjzsjh8zbbQY2pM9g==",
- "5VO1inwXMvLDBQSOahT6rg==",
- "HaHTsLzx7V3G1SFknXpGxA==",
- "MMaegl2Md9s/wOx5o9564w==",
- "mpWNaUH9kn4WY26DWNAh3Q==",
- "w3G+qXXqqKi8F5s+qvkBUg==",
- "wM8tnXO4PDlLVHspZFcjYw==",
- "LFcpCtnSnsCPD2gT/RA+Zg==",
- "bhVbgJ4Do4v56D9mBuR/EA==",
- "yU3N0HMSP5etuHPNrVkZtg==",
- "FzqIpOcTsckSNHExrl+9jg==",
- "BYz52gYI/Z6AbYbjWefcEA==",
- "h3vYYI9yhpSZV2MQMJtwFQ==",
- "adJAjAFyR2ne1puEgRiH+g==",
- "eDcyiPaB954q5cPXcuxAQw==",
- "40gCrW4YWi+2lkqMSPKBPg==",
- "ulLuTZqhEDkX0EJ3xwRP9A==",
- "y4iBxAMn/KzMmaWShdYiIw==",
- "ilBBNK/IV69xKTShvI94fQ==",
- "0HN6MIGtkdzNPsrGs611xA==",
- "twPn6wTGqI0aR//0wP3xtA==",
- "3UNJ37f+gnNyYk9yLFeoYA==",
- "4SdHWowXgCpCDL28jEFpAw==",
- "Mr5mCtC53+wwmwujOU/fWw==",
- "81pAhreEPxcKse+++h1qBg==",
- "KmcGEE0pacQ/HDUgjlt7Pg==",
- "Gt4/MMrLBErhbFjGbiNqQQ==",
- "lf1fwA0YoWUZaEybE+LyMQ==",
- "RIVYGO2smx9rmRoDVYMPXw==",
- "rJ9qVn8/2nOxexWzqIHlcQ==",
- "lfOLLyZNbsWQgHRhicr4ag==",
- "wgH1GlUxWi6/yLLFzE76uQ==",
- "Qg1ubGl+orphvT990e5ZPA==",
- "Z5B+uOmPZbpbFWHpI9WhPw==",
- "snGTzo540cCqgBjxrfNpKw==",
- "ZqkmoGB0p5uT5J6XBGh7Tw==",
- "uPi8TsGY3vQsMVo/nsbgVQ==",
- "Y5XR8Igvau/h+c1pRgKayg==",
- "ZmVpw1TUVuT13Zw/MNI5hQ==",
- "60suecbWRfexSh7C67RENA==",
- "kZ/mZZg9YSDmk2rCGChYAg==",
- "OpL+vHwPasW30s2E1TYgpA==",
- "ZVnErH1Si4u51QoT0OT7pA==",
- "3pi3aNVq1QNJmu1j0iyL0g==",
- "tb5+2dmYALJibez1W4zXgA==",
- "jOPdd330tB6+7C29a9wn0Q==",
- "5oD/aGqoakxaezq43x0Tvw==",
- "HdB7Se47cWjPgpJN0pZuiA==",
- "6WhHPWlqEUqXC52rHGRHjA==",
- "WLwpjgr9KzevuogoHZaVUw==",
- "E8yMPK7W0SIGTK6gIqhxiQ==",
- "1/Hxu8M9N/oNwk8bCj4FNQ==",
- "Uo1ebgsOxc3eDRds1ah3ag==",
- "5pqqzC/YmRIMA9tMFPi7rg==",
- "ri4AOITPdB1YHyXV+5S51g==",
- "HfvsiCQN/3mT0FabCU5ygQ==",
- "UQTQk5rrs6lEb1a+nkLwfg==",
- "VH70dN82yPCRctmAHMfCig==",
- "yD3Dd4ToRrl53k/2NSCJiw==",
- "fO0+6TsjL+45p9mSsMRiIg==",
- "fM5uYpkvJFArnYiQ3MrQnA==",
- "V+QzdKh5gxTPp2yPC9ZNEg==",
- "XHHEg/8KZioW/4/wgSEkbQ==",
- "2abfl3N46tznOpr+94VONQ==",
- "gxwbqZDHLbQVqXjaq42BCg==",
- "WnHK5ZQDR6Da5cGODXeo0A==",
- "SChDh/Np1HyTPWfICfE1uA==",
- "yhexr/OFKfZl0o3lS70e4w==",
- "N65PqIWiQeS082D6qpfrAg==",
- "RM5CpIiB94Sqxi462G7caA==",
- "CBAGa5l95f3hVzNi6MPWeQ==",
- "OHJBT2SEv5b5NxBpiAf7oQ==",
- "p48i7AfSSAyTdJSyHvOONw==",
- "/SP6pOdYFzcAl2OL05z4uQ==",
- "N8dXCawxSBX40fgRRSDqlQ==",
- "bMWFvjM8eVezU1ZXKmdgqw==",
- "Um1ftRBycvb+363a90Osog==",
- "QAz7FA+jpz9GgLvwdoNTEQ==",
- "qO4HlyHMK5ygX+6HbwQe8w==",
- "UgvtdE2eBZBUCAJG/6c0og==",
- "q5g3c8tnQTW2EjNfb2sukw==",
- "gsC/mWD8KFblxB0JxNuqJw==",
- "SVFbcjXbV7HRg+7jUrzpwg==",
- "bz294kSG4egZnH2dJ8HwEg==",
- "ybpTgPr3SjJ12Rj5lC/IMA==",
- "yDrAd1ot38soBk7zKdnT8A==",
- "BB/R8oQOcoE4j63Hrh8ifg==",
- "GNrMvNXQkW7PydlyJa+f1w==",
- "w0PKdssv+Zc5J/BbphoxpA==",
- "D5ibbo8UJMfFZ48RffuhgQ==",
- "MdvhC1cuXqni/0mtQlSOCw==",
- "wQKL8Ga6JQkpZ7yymDkC3w==",
- "o1uhaQg5/zfne84BFAINUQ==",
- "Ft2wXUokFdUf6d2Y/lwriw==",
- "sLJrshdEANp0qk2xOUtTnQ==",
- "jx7rpxbm1NaUMcE2ktg5sA==",
- "ZQ0ZnTsZKWxbRj7Tilh24Q==",
- "KhrIIHfqXl9zGE9aGrkRVg==",
- "jS0JuioLGAVaHdo/96JFoQ==",
- "tr+U/vt+MIGXPRQYYWJfRg==",
- "TXab/hqNGWaSK+fXAoB2bg==",
- "0K4NBxqEa3RYpnrkrD/XjQ==",
- "3oMTbWf7Bv83KRlfjNWQZA==",
- "yLAhLNezvqVHmN1SfMRrPw==",
- "ZYW30FfgwHmW6nAbUGmwzA==",
- "CZNoTy26VUQirvYxSPc/5A==",
- "CF1sAlhjDQY/KWOBnSSveA==",
- "+CLf5witKkuOvPCulTlkqw==",
- "1m1yD4L9A7Q1Ot+wCsrxJQ==",
- "2E41e0MgM3WhFx2oasIQeA==",
- "mDXHuOmI4ayjy2kLSHku1Q==",
- "sCLMrLjEUQ6P1L8tz90Kxg==",
- "zDUZCzQesFjO1JI3PwDjfg==",
- "x/BIDm6TKMhqu/gtb3kGyw==",
- "DEaZD/8aWV6+zkiLSVN/gA==",
- "7dz+W494zwU5sg63v5flCg==",
- "Y5iDQySR2c3MK7RPMCgSrw==",
- "GglPoW5fvr4JSM3Zv99oiA==",
- "myzvc+2MfxGD9uuvZYdnqQ==",
- "V9G1we3DOIQGKXjjPqIppQ==",
- "gYvdNJCDDQmNhtJ6NKSuTA==",
- "rXtGpN17Onx8LnccJnXwJQ==",
- "/a+bLXOq02sa/s8h7PhUTg==",
- "htNVAogFakQkTX6GHoCVXg==",
- "eshD40tvOA6bXb0Fs/cH3A==",
- "K1CGbMfhlhIuS0YHLG30PQ==",
- "aOeJZUIZM9YWjIEokFPnzQ==",
- "r0hAwlS0mPZVfCSB+2G6uQ==",
- "0q+erphtrB+6HBnnYg7O6w==",
- "bkRdUHAksJZGzE1gugizYQ==",
- "J8v2f6hWFu8oLuwhOeoQjA==",
- "qkvEep4vvXhc2ZJ6R449Mg==",
- "6HGeEPyTAu9oiKhNVLjQnA==",
- "JoATsk/aJH0UcDchFMksWA==",
- "QozQL0DTtr+PXNKifv6l6g==",
- "HiAgt86AyznvbI2pnLalVQ==",
- "lY+tivtsfvU0LJzBQ6itYQ==",
- "EfXDc6h69aBPE6qsB+6+Ig==",
- "gnAIpoCyl3mQytLFgBEgGA==",
- "p2JPOX8yDQ0agG+tUyyT/g==",
- "zeELfk015D5krExLKRUYtg==",
- "wDiGoFEfIVEDyyc4VpwhWQ==",
- "7Ephy+mklG2Y3MFdqmXqlA==",
- "8ZFPMJJYVJHsfRpU4DigSg==",
- "ocRh5LR1ZIN9Johnht8fhQ==",
- "l5f3I6osM9oxLRAwnUnc5A==",
- "yxCyBXqGWA735JEyljDP7Q==",
- "qE/h/Z+6buZWf+cmPdhxog==",
- "HCu4ZMrcLMZbPXbTlWuvvQ==",
- "TDrq23VUdzEU/8L5i8jRJQ==",
- "L+N/6geuokiLPPSDXM9Qkg==",
- "v6jZicMNM3ysm3U5xu0HoQ==",
- "b85nxzs8xiHxaqezuDVWvg==",
- "ca+kx+kf7JuZ3pfYKDwFlg==",
- "KlY5TGg0pR/57TVX+ik1KQ==",
- "3jmCreW5ytSuGfmeLv7NfQ==",
- "ucLMWnNDSqE4NOCGWvcGWw==",
- "NSrzwNlB0bde3ph8k6ZQcQ==",
- "nL4iEd3b5v4Y9fHWDs+Lrw==",
- "W2x0SBzSIsTRgyWUCOZ/lg==",
- "ifZM0gBm9g9L09YlL+vXBg==",
- "4WcFEswYU/HHQPw77DYnyA==",
- "TLJbasOoVO435E5NE5JDcA==",
- "WyCFB4+6lVtlzu3ExHAGbQ==",
- "BW0A06zoQw7S+YMGaegT7g==",
- "qP1cCE4zsKGTPhjbcpczMw==",
- "UVEZPoH9cysC+17MKHFraw==",
- "eQ45Mvf5in9xKrP6/qjYbg==",
- "fOARCnIg/foF/6tm7m9+3w==",
- "lK2xe+OuPutp4os0ZAZx5w==",
- "Tug3eh+28ttyf+U7jfpg5w==",
- "ENFfP93LA257G6pXQkmIdg==",
- "FuWspiqu5g8Eeli5Az+BkA==",
- "kIGxCUxSlNgsKZ45Al1lWw==",
- "RzeH+G3gvuK1z+nJGYqARQ==",
- "0ofMbUCA3/v5L8lHnX4S5w==",
- "VI8pgqBZeGWNaxkuqQVe7g==",
- "x6lNRGgJcRxgKTlzhc1WPg==",
- "La0gzdbDyXUq6YAXeKPuJA==",
- "dAq8/1JSQf1f4QPLUitp0g==",
- "WN7lFJfw4lSnTCcbmt5nsg==",
- "2aDK0tGNgMLyxT+BQPDE8Q==",
- "9W57pTzc572EvSURqwrRhw==",
- "37Nkh06O979nt7xzspOFyQ==",
- "4TQkMnRsXBobbtnBmfPKnA==",
- "f/BjtP5fmFw2dRHgocbFlg==",
- "9vEgJVJLEfed6wJ7hBUGgQ==",
- "HRWYX2XOdsOqYzCcqkwIyw==",
- "StDtLMlCI75g4XC59mESEQ==",
- "99+SBN45LwKCPfrjUKRPmw==",
- "HbT6W1Ssd3W7ApKzrmsbcg==",
- "l8/KMItWaW3n4g1Yot/rcQ==",
- "s7iW1M6gkAMp+D/3jHY58w==",
- "GWwJ32SZqD5wldrXUdNTLA==",
- "YhLEPsi/TNyeUJw69SPYzQ==",
- "g0aTR8aJ0uVy3YvGYu5xrw==",
- "m6get5wjq5j1i5abnpXuZQ==",
- "ymtA8EMPMgmMcimWZZ0A1Q==",
- "HEcOaEd9zCoOVbEmroSvJg==",
- "F8l+Qd9TZgzV+r8G584lKA==",
- "3yDD+xT8iRfUVdxcc7RxKw==",
- "1eRUCdIJe3YGD5jOMbkkOg==",
- "DO1/jfP/xBI9N0RJNqB2Rw==",
- "SiSlasZ+6U2IZYogqr2UPg==",
- "tBQDfy48FnIOZI04rxfdcA==",
- "HEghmKg3GN60K7otpeNhaA==",
- "mTLBkP+yGHsdk5g7zLjVUw==",
- "RgtwfY5pTolKrUGT+6Pp6g==",
- "EyIsYQxgFa4huyo/Lomv7g==",
- "HwLSUie8bzH+pOJT3XQFyg==",
- "7Tauesu7bgs5lJmQROVFiQ==",
- "ojugpLIfzflgU2lonfdGxA==",
- "ZqjnqxZE/BjOUY0CMdVl0g==",
- "oQjugfjraFziga1BcwRLRA==",
- "JXCYeWjFqcdSf6QwB54G+A==",
- "TeBGJCqSqbzvljIh9viAqA==",
- "1Gpj4TPXhdPEI4zfQFsOCg==",
- "asouSfUjJa8yfMG7BBe+fA==",
- "ccy3Ke2k4+evIw0agHlh3w==",
- "CzSumIcYrZlxOUwUnLR2Zw==",
- "9QFYrCXsGsInUb4SClS3cQ==",
- "3RTtSaMp1TZegJo5gFtwwA==",
- "aTWiWjyeSDVY/q8y9xc2zg==",
- "UK+R+hAoVeZ4xvsoZjdWpw==",
- "rHagXw+CkF3uEWPWDKXvog==",
- "MfkyURTBfkNZwB+wZKjP4g==",
- "Qf7JFJJuuacSzl6djUT2EQ==",
- "K1RL+tLjICBvMupe7QppIQ==",
- "R2OOV18CV/YpWL1xzr/VQg==",
- "o+areESiXgSO0Lby56cBeg==",
- "VPqyIomYm7HbK5biVDvlpw==",
- "pw1jplCdTC+b0ThX0FXOjw==",
- "gTnsH3IzALFscTZ1JkA9pw==",
- "JYJvOZ4CHktLrYJyAbdOnA==",
- "P8lUiLFoL100c9YSQWYqDA==",
- "LATQEY7f47i77M6p11wjWA==",
- "U9kE50Wq5/EHO03c5hE4Ug==",
- "pFKzcRHSUBqSMtkEJvrR1Q==",
- "vHVXsAMQqc0qp7HA5Q+YkA==",
- "3XyoREdvhmSbyvAbgw2y/A==",
- "qOEIUWtGm5vx/+fg4tuazg==",
- "a6IszND1m+6w+W+CvseC7g==",
- "KuNY8qAJBce+yUIluW8AYw==",
- "5Wcq+6hgnWsQZ/bojERpUw==",
- "l2ZB9TvT68rn8AAN4MdxWw==",
- "h5HsEsObPuPFqREfynVblw==",
- "fvm0IQfnbfZFETg9v3z/Fg==",
- "QV0OG5bpjrjku4AzDvp9yw==",
- "nMuMtK/Zkb3Xr34oFuX/Lg==",
- "jMZKSMP2THqwpWqJNJRWdw==",
- "fX4G68hFL7DmEmjbWlCBJQ==",
- "ZlBNHAiYsfaEEiPQ1z+rCA==",
- "ckugAisBNX18eQz+EnEjjw==",
- "Dt6hvhPJu94CJpiyJ5uUkg==",
- "eYE9No9sN5kUZ5ePEyS3+Q==",
- "Tp52d1NndiC9w3crFqFm9g==",
- "MBjMU/17AXBK0tqyARZP5w==",
- "1EI9aa955ejNo1dJepcZJw==",
- "FqWLkhWl0iiD/u2cp+XK9A==",
- "j8nMH8mK/0Aae7ZkqyPgdg==",
- "ZtmnX24AwYAXHb2ZDC6MeQ==",
- "who8uUamlHWHXnBf7dwy4A==",
- "CmkmWcMK4eqPBcRbdnQvhw==",
- "61V74uIjaSfZM8au1dxr1A==",
- "778O1hdVKHLG2q9dycUS0Q==",
- "IdadoCPmSgHDHzn1zyf8Jw==",
- "Z2rwGmVEMCY6nCfHO3qOzw==",
- "Q3TpCE+wnmH/1h/EPWsBtQ==",
- "HnVfyqgJ+1xSsN4deTXcIA==",
- "XgPHx2+ULpm14IOZU2lrDg==",
- "IbN736G1Px5bsYqE5gW1JQ==",
- "nY/H7vThZ+dDxoPRyql+Cg==",
- "wlWxtQDJ+siGhN2fJn3qtw==",
- "MrbEUlTagbesBNg0OemHpw==",
- "LJtRcR70ug6UHiuqbT6NGw==",
- "hSNZWNKUtDtMo6otkXA/DA==",
- "LawT9ZygiVtBk0XJ+KkQgQ==",
- "DLzHkTjjuH6LpWHo2ITD0Q==",
- "i8XXN7jcrmhnrOVDV8a2Hw==",
- "ogcuGHUZJkmv+vCz567a2g==",
- "rUp5Mfc57+A8Q29SPcvH/Q==",
- "6706ncrH1OANFnaK6DUMqQ==",
- "gK7dhke5ChQzlYc/bcIkcg==",
- "t3Txxjq43e/CtQmfQTKwWg==",
- "6ZMs9vCzK9lsbS6eyzZlIA==",
- "uTHBqApdKOAgdwX3cjrCYQ==",
- "zirOtGUXeRL22ezfotZfQg==",
- "iK0dWKHjVVexuXvMWJV9pg==",
- "uzEgwx1iAXAvWPKSVwYSeQ==",
- "FHvI0IVNvih8tC7JgzvCOw==",
- "jjNMPXbmpFNsCpWY0cv3eg==",
- "/cJ0Nn5YbXeUpOHMfWXNHQ==",
- "WkSJpxBa45XJRWWZFee7hw==",
- "edlXkskLx287vOBZ9+gVYg==",
- "+Pl0bSMBAdXpRIA+zE02JA==",
- "3xw8+0/WU51Yz4TWIMK8mw==",
- "GdTanUprpE3X/YjJDPpkhQ==",
- "qnsBdl050y9cUaWxbCczRw==",
- "pnJnBzAJlO4j3IRqcfmhkQ==",
- "USq1iF90eUv41QBebs3bhw==",
- "QH3lAwOYBAJ0Fd5pULAZqw==",
- "gvvyX5ATi4q9NhnwxRxC8w==",
- "7xDIG/80SnhgxAYPL9YJtg==",
- "WVhfn2yJZ43qCTu0TVWJwA==",
- "twjiDKJM7528oIu/el4Zbg==",
- "6sBemZt4qY/TBwqk3YcLOQ==",
- "m3XYojKO+I6PXlVRUQBC3w==",
- "gUNP5w7ANJm257qjFxSJrA==",
- "mMLhjdWNnZ8zts9q+a2v3g==",
- "kjWYVC7Eok2w2YT4rrI+IA==",
- "ZzT5b0dYQXkQHTXySpWEaA==",
- "YzTV0esAxBFVls3e0qRsnA==",
- "9xmtuClkFlpz/X5E9JBWBA==",
- "nhAnHuCGXcYlqzOxrrEe1g==",
- "cbBXgB1WQ/i8Xul0bYY2fg==",
- "AkAes5oErTaJiGD2I4A1Pw==",
- "Wx9jh/teM0LJHrvTScssyQ==",
- "fU5ZZ1bIVsV+eXxOpGWo/Q==",
- "k8eZxqwxiN/ievXdLSEL/w==",
- "E2LR1aZ3DcdCBuVT7BhReA==",
- "1eCHcz4swFH+uRhiilOinQ==",
- "JipruVZx4ban3Zo5nNM37g==",
- "IPLD9nT5EEYG9ioaSIYuuA==",
- "pHozgRyMiEmyzThtJnY4MQ==",
- "p0eNK7zJd7D/HEGaVOrtrQ==",
- "dGjcKAOGBd4gIjJq7fL+qQ==",
- "uMq8cDVWFD+tpn8aeP8Pqg==",
- "gC7gUwGumN7GNlWwfIOjJQ==",
- "It+K/RCYMOfNrDZxo7lbcA==",
- "4CfEP8TeMKX33ktwgifGgA==",
- "nxDGRpePV3H4NChn4eLwag==",
- "300hoYyMR/mk1mfWJxS8/w==",
- "DmxgZsQg+Qy1GP0fPkW3VA==",
- "1vqRt79ukuvdJNyIlIag8Q==",
- "RWI0HfpP7643OSEZR8kxzw==",
- "zZtYkKU50PPEj6qSbO5/Sw==",
- "UNRlg6+CYVOt68NwgufGNA==",
- "kkbX+a00dfiTgbMI+aJpMg==",
- "VIC7inSiqzM6v9VqtXDyCw==",
- "l+x2QhxG8wb5AQbcRxXlmA==",
- "GUiinC3vgBjbQC2ybMrMNQ==",
- "6uMF5i0b/xsk55DlPumT7A==",
- "aK9nybtiIBUvxgs1iQFgsw==",
- "BLbTFLSb4mkxMaq4/B2khg==",
- "mTAqtg6oi0iytHQCaSVUsA==",
- "eBapvE+hdyFTsZ0y5yrahg==",
- "lHN2dn2cUKJ8ocVL3vEhUQ==",
- "Mj87ajJ/yR41XwAbFzJbcA==",
- "FA+nK6mpFWdD0kLFcEdhxA==",
- "FrTgaF5YZCNkyfR1kVzTLQ==",
- "5eHStFN7wEmIE+uuRwIlPQ==",
- "AyWlT+EGzIXc395zTlEU5Q==",
- "I+wVQA+jpPTJ6xEsAlYucg==",
- "Y1flEyZZAYxauMo4cmtJ1w==",
- "1AeReq55UQotRQVKJ66pmg==",
- "xzGzN5Hhbh0m/KezjNvXbQ==",
- "meHzY9dIF7llDpFQo1gyMg==",
- "RnOXOygwJFqrD+DlM3R5Ew==",
- "JKg64m6mU7C/CkTwVn4ASg==",
- "gGLz3Ss+amU7y6JF09jq7A==",
- "Pu9pEf+Tek3J+3jmQNqrKw==",
- "EATnlYm0p3h04cLAL95JgA==",
- "o64LDtKq/Fulf1PkVfFcyg==",
- "hUWqqG1QwYgGC5uXJpCvJw==",
- "RfSwpO/ywQx4lfgeYlBr2w==",
- "VaJc9vtYlqJbRPGb5Tf0ow==",
- "9JKIJrlQjhNSC46H3Cstcw==",
- "6Z9myGCF5ylWljgIYAmhqw==",
- "9bAWYElyRN1oJ6eJwPtCtQ==",
- "ohK6EftXOqBzIMI+5XnESw==",
- "AVjwqrTBQH1VREuBlOyUOg==",
- "G2UponGde3/Z+9b2m9abpQ==",
- "DoiItHSms0B9gYmunVbRkQ==",
- "vUC0HlTTHj6qNHwfviDtAw==",
- "hq35Fjgvrcx6I9e6egWS4w==",
- "sw+bmpzqsM4gEQtnqocQLQ==",
- "ApiuEPWr8UjuRyJjsYZQBw==",
- "VXu4ARjq7DS2IR/gT24Pfw==",
- "3TbRZtFtsh9ez8hqZuTDeA==",
- "CazLJMJjQMeHhYLwXW7YNg==",
- "ROSt+NlEoiPFtpRqKtDUrQ==",
- "IUwVHH6+8/0c+nOrjclOWA==",
- "lkzFdvtBx5bV6xZO0cxK7g==",
- "4ekt4m38G9m599xJCmhlug==",
- "fzkmVWKhJsxyCwiqB/ULnQ==",
- "LZAKplVoNjeQgfaHqkyEJA==",
- "91vfsZ7Lx9x5gqWTOdM4sg==",
- "MVoxyIA+emaulH8Oks8Weg==",
- "oGH7SMLI2/qjd9Vnhi3s0A==",
- "vmqfGJE6r4yDahtU/HLrxw==",
- "Y5KKN7t/v9JSxG/m1GMPSA==",
- "gXlb7bbRqHXusTE5deolGA==",
- "/2c4oNniwhL3z5IOngfggg==",
- "HgIFX42oUdRPu7sKAXhNWg==",
- "A3dX2ShyL9+WOi6MNJBoYQ==",
- "hN9bmMHfmnVBVr+7Ibd2Ng==",
- "DB706G73NpBSRS8TKQOVZw==",
- "JSyq2MIuObPnEgEUDyALjQ==",
- "kSUectNPXpXNg+tIveTFRw==",
- "XVVy3e6dTnO3HpgD6BtwQw==",
- "td7nDgTDmKPSODRusMcupw==",
- "Lt/pVD4TFRoiikmgAxEWEw==",
- "mmRob7iyTkTLDu8ObmTPow==",
- "Fd0c8f2eykUp9GYhqOcKoA==",
- "18RKixTv12q3xoBLz6eKiA==",
- "RClzwwKh51rbB4ekl99EZA==",
- "oONlXCW4aAqGczQ/bUllBw==",
- "foPAmiABJ3IXBoed2EgQXA==",
- "wEJDulZafLuXCvcqBYioFQ==",
- "K1RgR6HR5uDEQgZ32TAFgA==",
- "SEIZhyguLoyH7So0p1KY0A==",
- "ggIfX1J4dX3xQoHnHUI7VA==",
- "HBRzLacCVYfwUVGzrefZYg==",
- "aWZRql2IUPVe9hS3dxgVfQ==",
- "Err1mbWJud80JNsDEmXcYg==",
- "Z2MkqmpQXdlctCTCUDPyzw==",
- "JnE6BK0vpWIhNkaeaYNUzw==",
- "5dUry23poD+0wxZ3hH6WmA==",
- "DwP0MQf71VsqvAbAMtC3QQ==",
- "kHcBZXoxnFJ+GMwBZ/xhfQ==",
- "SUAwMWLMml8uGqagz5oqhQ==",
- "79uTykH43voFC3XhHHUzKg==",
- "P5fucOJhtcRIoElFJS4ffg==",
- "s8NpalwgPdHPla7Zi9FJ3w==",
- "8cXqZub6rjgJXmh1CYJBOg==",
- "tY916jrSySzrL+YTcVmYKQ==",
- "DRiFNojs7wM8sfkWcmLnhQ==",
- "wqUJ1Gq1Yz2cXFkbcCmzHQ==",
- "0u+0WHr7WI6IlVBBgiRi6w==",
- "GCYI9Dn1h3gOuueKc7pdKA==",
- "nVDxVhaa2o38gd1XJgE3aw==",
- "5I/heFSQG/UpWGx0uhAqGQ==",
- "1PvTn90xwZJPoVfyT5/uIQ==",
- "jHOoSl3ldFYr9YErEBnD3w==",
- "swJhrPwllq5JORWiP5EkDA==",
- "tj2rWvF2Fl+XIccctj8Mhw==",
- "QvYZxsLdu+3nV/WhY1DsYg==",
- "fKalNdhsyxTt1w08bv9fJA==",
- "CHLHizLruvCrVi9chj9sXA==",
- "sa2DECaqYH1z1/AFhpHi+g==",
- "LbPp1oL0t3K2BAlIN+l8DA==",
- "5SbwLDNT6sBOy6nONtUcTg==",
- "AfVPdxD3FyfwwNrQnVNQ7A==",
- "jt9Ocr9D8EwGRgrXVz//aQ==",
- "KkwQL0DeUM3nPFfHb2ej+A==",
- "WwraoO97OTalvavjUsqhxQ==",
- "fAKFfwlCOyhtdBK6yNnsNg==",
- "EqMlrz1to7HG4GIFTPaehQ==",
- "YmjZJyNfHN5FaTL/HAm8ww==",
- "L2D7G0btrwxl9V4dP3XM5Q==",
- "oUqO4HrBvkpSL781qAC9+w==",
- "c6Yhwy/q3j7skXq52l36Ww==",
- "FWphIPZMumqnXr1glnbK4w==",
- "AcKwfS8FRVqb72uSkDNY/Q==",
- "uSIiF1r9F18avZczmlEuMQ==",
- "XrFDomoH2qFjQ2jJ2yp9lA==",
- "N2X7KWekNN+fMmwyXgKD5w==",
- "IdmcpJXyVDajzeiGZixhSA==",
- "Wf2olJCYZRGTTZxZoBePuQ==",
- "oVlG+0rjrg2tdFImxIeVBA==",
- "7w4PDRJxptG8HMe/ijL6cQ==",
- "rueNryrchijjmWaA3kljYg==",
- "ZybIEGf1Rn/26vlHmuMxhw==",
- "yYVW07lOZHdgtX42xJONIA==",
- "4ifNsmjYf1iOn2YpMfzihg==",
- "KTjwL+qswa+Bid8xLdjMTg==",
- "THfzE2G2NVKKfO+A2TjeFw==",
- "QoqHzpHDHTwQD5UF30NruQ==",
- "dTMoNd6DDr1Tu8tuZWLudw==",
- "wOc4TbwQGUwOC1B3BEZ4OQ==",
- "gfhkPuMvjoC3CGcnOvki3Q==",
- "vljJciS+uuIvL7XXm5688g==",
- "EGLOaMe6Nvzs/cmb7pNpbg==",
- "oLWWIn/2AbKRHnddr2og9g==",
- "7l0RMKbONGS/goW/M+gnMQ==",
- "eFkXKRd2dwu/KWI5ZFpEzw==",
- "jWsC7kdp2YmIZpfXGUimiA==",
- "Jcxjli2tcIAjCe+5LyvqdQ==",
- "MUkRa/PjeWMhbCTq43g6Aw==",
- "g2nh2xENCFOpHZfdEXnoQA==",
- "x6M66krXSi0EhppwmDmsxA==",
- "26Wmdp6SkKN74W0/XPcnmA==",
- "ycjv4XkS5O7zcF3sqq9MwQ==",
- "gfnbviaVhKvv1UvlRGznww==",
- "aIPde9CtyZrhbHLK740bfw==",
- "0p8YbEMxeb73HbAfvPLQRw==",
- "Is3uxoSNqoIo5I15z6Z2UQ==",
- "NZtcY8fIpSKPso/KA6ZfzA==",
- "iQ304I1hmLZktA1d1cuOJA==",
- "0QB0OUW5x2JLHfrtmpZQ+w==",
- "kgyUtd8MFe0tuuxDEUZA9w==",
- "AcbG0e6xN8pZfYAv7QJe1Q==",
- "bb/U8UynPHwczew/hxLQxw==",
- "NuBYjwlxadAH+vLWYRZ3bg==",
- "Ao1Zc0h5AdSHtYt1caWZnQ==",
- "FL/j3GJBuXdAo54JYiWklQ==",
- "E2v8Kk60qVpQ232YzjS2ow==",
- "zVupSPz7cD0v/mD/eUIIjg==",
- "sEeblUmISi1HK4omrWuPTA==",
- "xQpYjaAmrQudWgsdu24J0A==",
- "vCekQ2nOQKiN/q8Be/qwZg==",
- "8g08gjG/QtvAYer32xgNAg==",
- "miiOqnhtef1ODjFzMHnxjA==",
- "sXlFMSTBFnq0STHj6cS/8w==",
- "+SclwwY8R2RPrnX54Z+A6w==",
- "g8TcogVxHpw7uhgNFt5VCQ==",
- "9viAzLFGYYudBYFu7kFamg==",
- "BAJ+/jbk2HyobezZyB9LiQ==",
- "/DJgKE9ouibewuZ2QEnk6w==",
- "fxg/vQq9WPpmQsqQ4RFYaA==",
- "lM/EhwTsbivA7MDecaVTPw==",
- "pVgjGg4TeTNhKimyOu3AAw==",
- "gYnznEt9r97haD/j2Cko7g==",
- "/ngbFuKIAVpdSwsA3VxvNw==",
- "VCL3xfPVCL5RjihQM59fgg==",
- "eDWsx4isnr2xPveBOGc7Hw==",
- "FIOCTEbzb2+KMCnEdJ7jZw==",
- "40HzgVKYnqIb6NJhpSIF0A==",
- "ccK42Lm8Tsv73YMVZRwL6A==",
- "MpAwWMt7bcs4eL7hCSLudQ==",
- "zxsSqovedB3HT99jVblCnQ==",
- "4erEA42TqGA9K4iFKkxMMA==",
- "BaRwTrc5ulyKbW4+QqD0dw==",
- "CT3ldhWpS1SEEmPtjejR/Q==",
- "lkl6XkrTMUpXi46dPxTPxg==",
- "3EhLkC9NqD3A6ApV6idmgg==",
- "fsW2DaKYTCC7gswCT+ByQQ==",
- "pW4gDKtVLj48gNz6V17QdA==",
- "KjfL7YyVqmCJGBGDFdJ0gw==",
- "bGGUhiG9SqJMHQWitXTcYQ==",
- "8RtLlzkGEiisy1v9Xo0sbw==",
- "R81DX/5a7DYKkS4CU+TL+w==",
- "Tu6w6DtX2RJJ3Ym3o3QAWw==",
- "nx/U4Tode5ILux4DSR+QMg==",
- "mjQS8CpyGnsZIDOIEdYUxg==",
- "wJpepvmtQQ3sz3tVFDnFqw==",
- "a4rPqbDWiMivVzaRxvAj7g==",
- "6o5g9JfKLKQ2vBPqKs6kjg==",
- "UzPPFSXgeV7KW4CN5GIQXA==",
- "NdVyHoTbBhX6Umz/9vbi0g==",
- "Fzuq+Wg7clo6DTujNrxsSA==",
- "XXFr0WUuGsH5nXPas7hR3Q==",
- "JVSLiwurnCelNBiG2nflpQ==",
- "NiawWuMBDo0Q3P2xK/vnLQ==",
- "nNaGqigseHw30DaAhjBU3g==",
- "+edqJYGvcy1AH2mEjJtSIg==",
- "1WIi4I62GqkjDXOYqHWJfQ==",
- "rwplpbNJz0ADUHTmzAj15Q==",
- "iWNlSnwrtCmVF89B+DZqOQ==",
- "tHDbi43e6k6uBgO0hA+Uiw==",
- "fHNpW230mNib08aB7IM3XQ==",
- "OChiB4BzcRE8Qxilu6TgJg==",
- "d+ctfXU0j07rpRRzb5/HDA==",
- "GDMqfhPQN0PxfJPnK1Bb9A==",
- "bLd38ZNkVeuhf0joEAxnBQ==",
- "nvUKoKfC6j8fz3gEDQrc/w==",
- "fhcbn9xE/6zobqQ2niSBgA==",
- "HGxe+5/kkh6R9GXzEOOFHA==",
- "mPwCyD0yrIDonVi+fhXyEQ==",
- "5PfGtbH9fmVuNnq83xIIgQ==",
- "XePy/hhnQwHXFeXUQQ55Vg==",
- "yfAaL0MMtSXPQ37pBdmHxQ==",
- "NiQ/m4DZXUbpca9aZdzWAw==",
- "uT6WRh5UpVdeABssoP2VTg==",
- "oxoZP897lgMg/KLcZAtkAg==",
- "oKt57TPe4PogmsGssc3Cbg==",
- "RxmdoO8ak8y/HzMSIm+yBQ==",
- "6leyDVmC5jglAa98NQ3+Hg==",
- "+QosBAnSM2h4lsKuBlqEZw==",
- "hy303iin+Wm7JA6MeelwiQ==",
- "m9iuy4UtsjmyPzy6FTTZvw==",
- "f6Ye5F0Lkn34uLVDCzogFQ==",
- "iGykaF+h4p46HhrWqL8Ffg==",
- "LPYFDbTEp5nGtG6uO8epSw==",
- "t2vWMIh2BvfDSQaz5T1TZw==",
- "OONAvFS/kmH7+vPhAGTNSg==",
- "g/z9yk94XaeBRFj4hqPzdw==",
- "2wesXiib76wM9sqRZ7JYwQ==",
- "n7h9v2N1gOcvMuBEf8uThw==",
- "ITYL3tDwddEdWSD6J6ULaA==",
- "inrUwXyKikpOW0y2Kl1wGw==",
- "iwKBOGDTFzV4aXgDGfyUkw==",
- "+fcjH2kZKNj8quOytUk4nQ==",
- "Srl4HivgHMxMOUHyM3jvNw==",
- "qngzBJbiTB4fivrdnE5gOg==",
- "G0MlFNCbRjXk4ekcPO/chQ==",
- "t+bYn9UqrzKiuxAYGF7RLA==",
- "RVD3Ij6sRwwxTUDAxwELtA==",
- "RNdyt6ZRGvwYG5Ws3QTuEA==",
- "9DRHdyX8ECKHUoEsGuqR4Q==",
- "oMJLQTH1wW7LvOV0KRx/dw==",
- "bjLZ7ot/X/vWSVx4EYwMCg==",
- "+p8pofUlwn8vV6Rp6+sz9g==",
- "cchuqe+CWCJpoakjHLvUfA==",
- "NvurnIHin4O+wNP7MnrZ1w==",
- "RBMv0IxXEO3o7MnV47Bzow==",
- "xTizUioizbMQxD0T6fy/EQ==",
- "ZCdad3AwhVArttapWFwT/Q==",
- "Hy1nqC40l5ItxumkIC2LAA==",
- "W/5ThNLu43uT1O+fg0Fzwg==",
- "b3BQG9/9qDNC/bNSTBY/sQ==",
- "neQoa8pvETr07blVMN3pgA==",
- "oR8rvIZoeoaZ/ufpo0htfQ==",
- "zEzWZ6l7EKoVUxvk/l78Mw==",
- "IHyIeMad23fSDisblwyfpA==",
- "m6srF+pMehggHB1tdoxlPg==",
- "kggaIvN2tlbZdZRI8S5Apw==",
- "2RFaMPlSbVuoEqKXgkIa5A==",
- "//eHwmDOQRSrv+k9C/k3ZQ==",
- "X/Gha4Ajjm/GStp/tv+Jvw==",
- "+H0Rglt/HnhZwdty2hsDHg==",
- "a1aL8zQ+ie3YPogE3hyFFg==",
- "HxEU37uBMeiR5y8q/pM42g==",
- "68nqDtXOuxF7DSw6muEZvg==",
- "s5+78jS4hQYrFtxqTW3g1Q==",
- "drfODfDI6GyMW7hzkmzQvA==",
- "pT1raq2fChffFSIBX3fRiA==",
- "sfowXUMdN2mCoBVrUzulZg==",
- "AV/YJfdoDUdRcrXVwinhQg==",
- "3AKEYQqpkfW7CZMFQZoxOw==",
- "PHwJ5ZAqqftZ4ypr8H1qiQ==",
- "AoN/pnK4KEUaGw4V9SFjpg==",
- "soBA65OmZdfBGJkBmY/4Iw==",
- "mSstwJq7IkJ0JBJ5T8xDKg==",
- "h13Xuonj+0dD1xH86IhSyQ==",
- "HK9xG03FjgCy8vSR+hx8+Q==",
- "oFanDWdePmmZN0xqwpUukA==",
- "zCRZgVsHbQZcVMHd9pGD3A==",
- "EvSB+rCggob2RBeXyDQRvQ==",
- "tXuu7YpZOuMLTv87NjKerA==",
- "DJ+a37tCaGF5OgUhG+T0NA==",
- "KkXlgPJPen6HLxbNn5llBw==",
- "2W6lz1Z7PhkvObEAg2XKJw==",
- "n+xYzfKmMoB3lWkdZ+D3rg==",
- "CPDs+We/1wvsGdaiqxzeCQ==",
- "2Wvk/kouEEOY0evUkQLhOQ==",
- "ezsm4aFd6+DO9FUxz0A8Pg==",
- "9sYLg75/hudZaBA3FrzKHw==",
- "Pp1ZMxJ8yajdbfKM4HAQxA==",
- "xiyRfVG0EfBA+rCk+tgWRQ==",
- "/IarsLzJB8bf0AupJJ+/Eg==",
- "LJeLdqmriyAQp+QjZGFkdQ==",
- "IhHyHbHGyQS+VawxteLP0w==",
- "nGzPc0kI/EduVjiK7bzM6Q==",
- "m06wctjNc3o7iyBHDMZs2w==",
- "mSJF9dJnxZ15lTC6ilbJ2A==",
- "xdmY+qyoxxuRZa9kuNpDEg==",
- "oNOI17POQCAkDwj6lJsYOA==",
- "p73gSu4d+4T/ZNNkIv9Nlw==",
- "vOJ55zFdgPPauPyFYBf01w==",
- "4A+RHIw+aDzw0rSRYfbc7g==",
- "/gi3UZmunVOIXhZSktZ8zQ==",
- "a6vem8n6WmRZAalDrHNP0g==",
- "kGeXrHEN6o7h5qJYcThCPw==",
- "wrewZ0hoHODf7qmoGcOd7g==",
- "Z0sjccxzKylgEiPCFBqPSA==",
- "LKyOFgUKKGUU/PxpFYMILw==",
- "L2RofFWDO0fVgSz4D2mtdw==",
- "KI7tQFYW38zYHOzkKp9/lQ==",
- "ewe/P3pJLYu/kMb5tpvVog==",
- "IADk81pIu8NIL/+9Fi94pA==",
- "0L0FVcH5Dlj3oL8+e9Na7g==",
- "tdiTXKrkqxstDasT0D5BPA==",
- "R906Kxp2VFVR3VD+o6Vxcw==",
- "wc+8ohFWgOF4VlSYiZIGwQ==",
- "wJKFMqh6MGctWfasjHrPEg==",
- "UHpge5Bldt9oPGo2oxnYvQ==",
- "vX7RIhatQeXAMr1+OjzhZw==",
- "s2AKVTwrY65/SWqQxDGJQg==",
- "Q4bfQslDSqU64MOQbBQEUw==",
- "mVT74Eht+gAowINoMKV7IQ==",
- "EuGWtIbyKToOe6DN3NkVpQ==",
- "ALlGgVDO8So71ccX0D6u2g==",
- "Rww3qkF3kWSd+AaMT0kfdw==",
- "hlvtFGW8r0PkbUAYXEM+Hw==",
- "Oc3BqTF3ZBW3xE0QsnFn/A==",
- "3j0kFUZ6g+yeeEljx+WXGg==",
- "8BLkvEkfnOizJq0OTCYGzw==",
- "Lqel4GdU0ZkfoJVXI5WC/Q==",
- "rvE64KQGkVkbl07y7JwBqw==",
- "HbXv8InyZqFT7i3VrllBgg==",
- "zwQ/3MzTJ9rfBmrANIh14w==",
- "gglLMohmJDPRGMY1XKndjQ==",
- "lyfqic/AbEJbCiw+wA01FA==",
- "XqUO7ULEYhDOuT/I2J8BOA==",
- "wPhJcp7U7IVX83szbIOOxQ==",
- "1gA65t5FiBTEgMELTQFUPQ==",
- "ll2M0QQzBsj5OFi02fv3Yg==",
- "wt+qDLU38kzNU75ZYi3Hbw==",
- "a4EYNljinYTx9vb1VvUA6A==",
- "T6LA+daQqRI38iDKZTdg1A==",
- "gwyVIrTk5o0YMKQq4lpJ+Q==",
- "bPRX2zl+K1S0iWAWUn1DZw==",
- "KQw25X4LnQ9is+qdqfxo0w==",
- "6tfM6dx3R5TiVKaqYQjnCg==",
- "OlwHO6Sg2zIwsCOCRu0HiQ==",
- "mr1qjhliRfl87wPOrJbFQg==",
- "8c+lvG5sZNimvx9NKNH3ug==",
- "5Nk2Z94DhlIdfG5HNgvBbQ==",
- "F50iXjRo1aSTr37GQQXuJA==",
- "tfgO55QqUyayjDfQh+Zo1Q==",
- "h7Fc+eT/GuC8iWI+YTD0UQ==",
- "3TjntNWtpG7VqBt3729L6Q==",
- "+DWs0vvFGt6d3mzdcsdsyA==",
- "VJt2kPVBLEBpGpgvuv1oUw==",
- "XLq/nWX8lQqjxsK9jlCqUg==",
- "9s3ar9q32Y5A3tla5GW/2Q==",
- "51yLpfEdvqXmtB6+q27/AQ==",
- "AiMtfedwGcddA+XYNc+21g==",
- "p/48hurJ1kh2FFPpyChzJg==",
- "CRiL6zpjfznhGXhCIbz8pQ==",
- "/jDVt9dRIn+o4IQ1DPwbsg==",
- "UNdKik7Vy23LjjPzEdzNsg==",
- "Koiog/hpN7ew5kgJbty34A==",
- "4itEKfbRCJvqlgKnyEdIOQ==",
- "zi04Yc01ZheuFAQc59E45A==",
- "etRjRvfL/IwceY/IJ1tgzQ==",
- "3sNJJIx1NnjYcgJhjOLJOg==",
- "4yVqq66iHYQjiTSxGgX2oA==",
- "Q8RVI/kRbKuXa8HAQD7zUA==",
- "OERGn45uzfDfglzFFn6JAg==",
- "JGEy6VP3sz3LHiyT2UwNHQ==",
- "1zDfWw5LdG20ClNP1HYxgw==",
- "TGB+FIzzKnouLh5bAiVOQg==",
- "n5GA+pA9mO/f4RN9NL9lNg==",
- "bUxQBaqKyvlSHcuRL9whjg==",
- "tOdlnsE3L3XCBDJRmb/OqA==",
- "XdkxmYYooeDKzy7PXVigBQ==",
- "PMvG4NqJP76kMRAup6TSZA==",
- "qpFJZqzkklby+u1UT3c1iA==",
- "fW3QZyq5UixIA1mP6eWgqQ==",
- "9nMltdrrBmM5ESBY2FRjGA==",
- "1Vtrv6QUAfiYQjlLTpNovg==",
- "ur9JDCVNwzSH4q4ngDlHNQ==",
- "4u3eyKc+y3uRnkASrgBVUw==",
- "XddlSluOH6VkR7spFIFmdQ==",
- "NOmu8oZc6CcKLu+Wfz2YOQ==",
- "3Ejtsqw3Iep/UQd0tXnSlg==",
- "y/e3HSdg7T19FanRpJ7+7Q==",
- "YodhkayN5wsgPZEYN7/KNA==",
- "pZfn6IiG+V28fN8E2hawDQ==",
- "jGHMJqbj6X1NdTDyWmXYAQ==",
- "olTSlmirL9MFhKORiOKYkQ==",
- "CrJDgdfzOea2M2hVedTrIg==",
- "fpXijBOM3Ai1RkmHven5Ww==",
- "eLYKLr4labZeLiRrDJ9mnA==",
- "9vmJUS7WIVOlhMqwipAknQ==",
- "G7J/za99BFbAZH+Q+/B8WA==",
- "Hb+pdSavvJ9lUXkSVZW8Og==",
- "gTB2zM3RPm27mUQRXc/YRg==",
- "e5KCqQ/1GAyVMRNgQpYf6g==",
- "1ApqwW7pE+XUB2Cs2M6y7g==",
- "/wiA2ltAuWyBhIvQAYBTQw==",
- "HFCQEiZf7/SNc+oNSkkwlA==",
- "JFi6N1PlrpKaYECOnI7GFg==",
- "E4ojRDwGsIiyuxBuXHsKBA==",
- "+25t/2lo0FUEtWYK8LdQZQ==",
- "up2MVDi9ve+s83/nwNtZ7Q==",
- "cXpfd6Io6Glj2/QzrDMCvA==",
- "DCvI9byhw0wOFwF1uP6xIQ==",
- "PibGJQNw7VHPTgqeCzGUGA==",
- "0ZRGz+oj2infCAkuKKuHiQ==",
- "2QS/6OBA1T01NlIbfkTYJg==",
- "P14k+fyz0TG9yIPdojp52w==",
- "g5EzTJ0KA4sO3+Opss3LMg==",
- "R5oOM58zdbVxFSDQnNWqeA==",
- "Vg2E5qEDfC+QxZTZDCu9yQ==",
- "YPgMthbpcBN2CMkugV60hQ==",
- "gZWTFt5CuLqMz6OhWL+hqQ==",
- "YrEP9z2WPQ8l7TY1qWncDA==",
- "7p4NpnoNSQR7ISg+w+4yFg==",
- "9L6yLO93sRN70+3qq3ObfA==",
- "QH36wzyIhh6I56Vnx79hRA==",
- "9DtM1vls4rFTdrSnQ7uWXw==",
- "ZlOAnCLV1PkR0kb3E+Nfuw==",
- "9UhKmKtr4vMzXTEn74BEhg==",
- "Ndx5LDiVyyTz/Fh3oBTgvA==",
- "mXZ4JeBwT2WJQL4a/Tm4jQ==",
- "N9nD7BGEM7LDwWIMDB+rEQ==",
- "dmAfbd9F0OJHRAhNMEkRsA==",
- "jV/D2B11NLXZRH77sG9lBw==",
- "1C50kisi9nvyVJNfq2hOEQ==",
- "NMbAjbnuK7EkVeY3CQI5VA==",
- "J1nYqJ7tIQK1+a/3sMXI/Q==",
- "m416yrrAlv+YPClGvGh+qQ==",
- "rLZII1R6EGus+tYCiUtm6g==",
- "xktOghh1S9nIX6fXWnT+Ug==",
- "FcFcn4qmPse5mJCX5yNlsA==",
- "xAAipGfHTGTjp9Qk1MR8RQ==",
- "RQOlmzHwQKFpafKPJj0D8w==",
- "WRjYdKdtnd1G9e/vFXCt0g==",
- "z0BU//aSjYHAkGGk3ZSGNg==",
- "M55eersiJuN9v61r8DoAjQ==",
- "l2mAbuFF3QBIUILDODiUHQ==",
- "IhpXs1TK7itQ3uTzZPRP5Q==",
- "t2EkpUsLOEOsrnep0nZSmA==",
- "lMaO8Yf+6YNowGyhDkPhQA==",
- "UbSFw5jtyLk5MealqJw++A==",
- "5u2PdDcIY3RQgtchSGDCGg==",
- "MQYM3BT77i35LG9HcqxY2Q==",
- "8AfCSZC0uasVON9Y/0P2Pw==",
- "evaWFoxZNQcRszIRnxqB+A==",
- "+8PiQt6O7pJI/nIvQpDaAg==",
- "eRwaYiog2DdlGQyaltCMJg==",
- "JyUJEnU6hJu8x2NCnGrYFw==",
- "l0E0U/CJsyCVSTsXW4Fp+w==",
- "XV13yK0QypJXmgI+dj4KYw==",
- "jrRH0aTUYCOpPLZwzwPRfQ==",
- "N3YDSkBUqSmrmNvZZx4a1Q==",
- "0yJ7TQYzcp3DXVSvwavr+w==",
- "rhgtLQh0F9bRA6IllM7AGw==",
- "IWZnTJ3Hb9qw9HAK/M9gTw==",
- "izeyFvXOumNgVyLrbKW45g==",
- "xYD8jrCDmuQna+p1ebnKDQ==",
- "SOdpdrk2ayeyv0xWdNuy9g==",
- "HYylUirJRqLm+dkp39fSOQ==",
- "q4z6A4l3nhX3smTmXr+Sig==",
- "Zyo0fzewcqXiKe2mAwKx5g==",
- "LMEtzh0+J27+4zORfcjITw==",
- "LoUv/f2lcWpjftzpdivMww==",
- "mXBfDUt/sBW5OUZs2sihvw==",
- "PggVPQL5YKqSU/1asihcrg==",
- "mI0eT4Rlr7QerMIngcu/ng==",
- "NmQrsmb8PVP05qnSulPe5Q==",
- "TcyyXrSsQsnz0gJ36w4Dxw==",
- "y4mfEDerrhaqApDdhP5vjA==",
- "ynaj4XjU27b7XbqPyxI8Ig==",
- "Ua6aO6HwM+rY4sPR19CNFA==",
- "3go7bJ9WqH/PPUTjNP3q/Q==",
- "n1ixvP7SfwYT3L2iWpJg6A==",
- "W8y32OLHihfeV0XFw7LmOg==",
- "uzkNhmo2d08tv5AmnyqkoQ==",
- "hJ8leLNuJ6DK5V8scnDaZQ==",
- "KodYHHN62zESrXUye7M01g==",
- "H+yPRiooEh5J7lAJB4RZ7Q==",
- "dZg5w8rFETMp9SgW7m0gfg==",
- "LsmsPokAwWNCuC74MaqFCQ==",
- "1QGhj9NONF2rC44UdO+Izw==",
- "uwGivY3/C9WK+dirRPJZ4A==",
- "rXGWY/Gq+ZEsmvBHUfFMmQ==",
- "j4FBMnNfdBwx0VsDeTvhFg==",
- "81nkjWtpBhqhvOp6K8dcWg==",
- "dCDaYYrgASXPMGFRV0RCGg==",
- "Kj1QI+s9261S3lTtPKd9eg==",
- "LblwOqNiciHmt2NXjd89tg==",
- "46piyANQVvvLqcoMq5G8tQ==",
- "XJihma9zSRrXLC+T+VcFDA==",
- "K3NBEG8jJTJbSrYSOC3FKw==",
- "cT3PwwS6ALZA/na9NjtdzA==",
- "wJ4uCrl4DPg70ltw1dZO3w==",
- "JATLdpQm//SQnkyCfI5x7Q==",
- "X1PaCfEDScclLtOTiF5JUw==",
- "444F9T6Y7J67Y9sULG81qg==",
- "8JVHFRwAd/SCLU0CRJYofg==",
- "aLh1XEUrfR9W82gzusKcOg==",
- "U+bB5NjFIuQr/Y5UpXHwxA==",
- "Egs14xVbRWjfBBX7X5Z60g==",
- "KSorNz/PLR/YYkxaj1fuqw==",
- "RDgGGxTtcPvRg/5KRRlz4w==",
- "5T39s5CtSrK5awMPUcEWJg==",
- "+PUVXkoTqHxJHO18z4KMfw==",
- "Bvk8NX4l6WktLcRDRKsK/A==",
- "kNGIV3+jQmJlZDTXy1pnyA==",
- "E3jMjAgXwvwR8PA53g4+PQ==",
- "MbI04HlTGCoc/6WDejwtaQ==",
- "aEnHUfn7UE/Euh6jsMuZ7g==",
- "z4Bft++f72QeDh4PWGr/sw==",
- "1lCcQWGDePPYco4vYrA5vw==",
- "iu5csar0IQQBOTgw5OvJwQ==",
- "raKMXnnX6PFFsbloDqyVzQ==",
- "uPnL9tboMZo0Kl2fe24CmA==",
- "8OFxXwnPmrogpNoueZlC4Q==",
- "V6CRKrKezPwsRdbm0DJ2Yg==",
- "xmGgK3W5y+oCd0K2u8XjZQ==",
- "Ry3zgZ6KHrpNyb7+Tt2Pkw==",
- "IwLbkL33z+LdTjaFYh93kg==",
- "caepyBOAFu0MxbcXrGf6TA==",
- "iIWxFdolLcnXqIjPMg+5kQ==",
- "P430CeF2MDkuq11YdjvV8A==",
- "yCu+DVU/ceMTOZ5h/7wQTg==",
- "4mQVNv7FHj+/O6XFqWFt/Q==",
- "OEJ40VmMDYzc2ESEMontRA==",
- "D66Suu3tWBD+eurBpPXfjA==",
- "RNK9G1hfuz3ETY/RmA9+aA==",
- "BYpHADmEnzBsegdYTv8B5Q==",
- "DBKrdpCE0awppxST4o/zzg==",
- "KOmdvm+wJuZ/nT/o1+xOuw==",
- "gDxqUdxxeXDYhJk9zcrNyA==",
- "UPzS4LR3p/h0u69+7YemrQ==",
- "hf9HFxWRNX2ucH8FLS7ytA==",
- "ozVqYsmUueKifb4lDyVyrg==",
- "TfHvdbl2M4deg65QKBTPng==",
- "SzCGM8ypE58FLaR1+1ccxQ==",
- "3nthUmLZ30HxQrzr2d7xFA==",
- "1jBaRO8Bg5l6TH7qJ8EPiw==",
- "eJlcN+gJnqAnctbWSIO9uA==",
- "G8LFBop8u6IIng+gQuVg3w==",
- "3JhnM6G4L06NHt31lR0zXA==",
- "342VOUOxoLHUqtHANt83Hw==",
- "hRxbdeniAVFgKUgB9Q3Y+g==",
- "cFFE2R4GztNoftYkqalqUQ==",
- "YmaksRzoU+OwlpiEaBDYaQ==",
- "jon1y9yMEGfiIBjsDeeJdA==",
- "oSnrpW4UmmVXtUGWqLq+tQ==",
- "zaqyy3GaJ7cp8qDoLJWcTw==",
- "luO1R8dUM9gy1E2lojRQoA==",
- "YHM6NNHjmodv+G0mRLK7kw==",
- "ZSmN8mmI9lDEHkJqBBg0Nw==",
- "520wTzrysiRi2Td92Zq0HQ==",
- "RAAw14BA1ws5Wu/rU7oegw==",
- "vb6Agwzk4JG0Nn7qRPPFMQ==",
- "joDXdLpXvRjOqkRiYaD/Sw==",
- "dK2DU3t1ns+DWDwfBvH3SQ==",
- "gZNJ1Qq6OcnwXqc+jXzMLQ==",
- "R8ULpSNu9FcCwXZM0QedSg==",
- "mc45FSMtzdw2PTcEBwHWPw==",
- "d0qvm3bl38rRCpYdWqolCQ==",
- "o9tdzmIu+3J/EYU4YWyTkA==",
- "5eXpiczlRdmqMYSaodOUiQ==",
- "KYuUNrkTvjUWQovw9dNakA==",
- "02im2RooJQ/9UfUrh5LO+A==",
- "kWPUUi7x9kKKa6nJ+FDR5Q==",
- "6z8CRivao3IMyV4p4gMh7g==",
- "SmRWEzqddY9ucGAP5jXjAg==",
- "DJscTYNFPyPmTb57g/1w+Q==",
- "uOHrw37yF9oLLVd16nUpeg==",
- "HaIRV9SNPRTPDOSX9sK/bg==",
- "K4yZNVoqHjXNhrZzz2gTew==",
- "bTNRjJm+FfSQVfd56nNNqQ==",
- "x5lyMArsv1MuJmEFlWCnNw==",
- "cxpZ4bloGv734LBf4NpVhA==",
- "kUudvRfA33uJDzHIShQd3Q==",
- "3Wfj05vCLFAB9vII5AU9tw==",
- "FUQySDFodnRhr+NUsWt0KA==",
- "eC/RcoCVQBlXdE9WtcgXIw==",
- "NoX8lkY+kd2GPuGjp+s0tQ==",
- "EzjbinBHx3Wr08eXpH3HXA==",
- "0VsaJHR0Ms8zegsCpAKoyg==",
- "e2xLFVavnZIUUtxJx+qa1g==",
- "Kt6BTG1zdeBZ3nlVk+BZKQ==",
- "EUXQZwLgnDG+C8qxVoBNdw==",
- "0SkC/4PtnX1bMYgD6r6CLA==",
- "rzj6mjHCcMEouL66083BAg==",
- "V5HEaY3v9agOhsbYOAZgJA==",
- "tJt6VDdAPEemBUvnoc4viA==",
- "g0lWrzEYMntVIahC7i0O2g==",
- "zCpibjrZOA3FQ4lYt0WoVA==",
- "4Xh/B3C16rrjbES+FM1W8g==",
- "GHEdXgGWOeOa6RuPMF0xXg==",
- "3kREs/qaMX0AwFXN0LO5ow==",
- "GLDNTSwygNBmuFwCIm7HtA==",
- "JBkbaBiorCtFq9M9lSUdMg==",
- "rJCuanCy51ydVD4nInf9IQ==",
- "OzFRv+PzPqTNmOnvZGoo5g==",
- "7mxU5fJl/c6dXss9H3vGcQ==",
- "9J53kk+InE3CKa7cPyCXMw==",
- "x9TIZ9Ua++3BX+MpjgTuWA==",
- "h0MH5NGFfChgmRJ3E/R3HQ==",
- "25w3ZRUzCvJwAVHYCIO5uw==",
- "1Wc8jQlDSB4Dp32wkL2odw==",
- "ipPPjxpXHS1tcykXmrHPMQ==",
- "r95wJtP5rsTExKMS7QhHcw==",
- "TZT86wXfzFffjt0f95UF5w==",
- "VpmBstwR7qPVqPgKYQTA3g==",
- "3++dZXzZ6AFEz7hK+i5hww==",
- "mAiD16zf+rCc7Qzxjd5buA==",
- "1JI9bT92UzxI8txjhst9LQ==",
- "TNyvLixb03aP2f8cDozzfA==",
- "spHVvA/pc7nF9Q4ON020+w==",
- "GA8k6GQ20DGduVoC+gieRA==",
- "T7waQc3PvTFr0yWGKmFQdQ==",
- "P0Pc8owrqt6spdf7FgBFSw==",
- "DKApp/alXiaPSRNm3MfSuA==",
- "UreSZCIdDgloih8KLeX7gg==",
- "xJi0T+psHOXMivSOVpMWeQ==",
- "cNsC9bH30eM1EZS6IdEdtQ==",
- "XjjrIpsmATV/lyln4tPb+g==",
- "qt5CsMts2aD4lw/4Q6bHYQ==",
- "h+KRDKIvyVUBmRjv1LcCyg==",
- "2j83jrPwPfYlpJJ2clEBYQ==",
- "ZrCezGLz38xKmzAom6yCTQ==",
- "SEGu+cSbeeeZg4xWwsSErQ==",
- "Duz/8Ebbd0w6oHwOs0Wnwg==",
- "Ci7sS7Yi1+IwAM3VMAB4ew==",
- "DG2Qe2DqPs5MkZPOqX363Q==",
- "v0Bvws1WYVoEgDt8xmVKew==",
- "CtDj/h2Q/lRey20G8dzSgA==",
- "WRoJMO0BCJyn5V6qnpUi4Q==",
- "RQywrOLZEKw9+kG6qTzr3g==",
- "mU4CqbAwpwqegxJaOz9ofQ==",
- "aN5x46Gw1VihRalwCt1CGg==",
- "U6VQghxOXsydh3Naa5Nz4A==",
- "YA+zdEC+yEgFWRIgS1Eiqw==",
- "oPcxgoismve6+jXyIKK6AQ==",
- "PqLCd/pwc+q5GkL6MB0jTg==",
- "fHL+fHtDxhALZFb9W/uHuw==",
- "dhTevyxTYAuKbdLWhG47Kw==",
- "VllbOAjeW3Dpbj5lp2OSmA==",
- "3itfXtlLPRmPCSYaSvc39Q==",
- "GNak/LFeoHWlTdLW1iU4eg==",
- "HuDuxs2KiGqmeyY1s1PjpQ==",
- "xs8J3cesq7lDhP/dNltqOw==",
- "foXSDEUwMhfHWJSmSejsQg==",
- "6fWom3YoKvW6NIg6y9o9CQ==",
- "NhZbSq0CjDNOAIvBHBM9zA==",
- "5w4FbRhWACP7k2WnNitiHg==",
- "0UeRwDID2RBIikInqFI7uw==",
- "/y/jHHEpUu5TR+R2o96kXA==",
- "voO3krg4sdy4Iu+MZEr8+g==",
- "hdzol5dk//Q6tCm4+OndIA==",
- "Nc5kiwXCAyjpzt43G5RF1A==",
- "3UBYBMejKInSbCHRoJJ7dg==",
- "dRFCIbVu0Y8XbjG5i+UFCQ==",
- "t8pjhdyNJirkvYgWIO/eKg==",
- "FAXzjjIr8l1nsQFPpgxM/g==",
- "SPGpjEJrpflv1hF0qsFlPw==",
- "9Y1ZmfiHJd9vCiZ6KfO1xQ==",
- "7Eqzyb+Kep+dIahYJWNNxQ==",
- "9rL8nC/VbSqrvnUtH9WsxQ==",
- "H4FZ5Wcnb40hQM1DMGGe8A==",
- "AjoXWGb/l9xH/hscgEc6kQ==",
- "6nzFl41uutgDdC30oOeCqg==",
- "3jo1jRy3MybXtoLR+JIbJw==",
- "mXdE08dv+OlIhlcqMBH2Gg==",
- "Ifd7DI6o8N5gnyAKqZTlRw==",
- "JNUvg/kxL3rdcZnD4IqUxw==",
- "ry8B+sAHNeFIZHCCDynFyw==",
- "TXaEd5lIKhzjcncfNcBgSg==",
- "Mr3ehuDMUimOSn+FlkchdA==",
- "cwiGhjmX9v8I7E/ekQ0h+g==",
- "I/r5+1jnqumCPprKC/2BqA==",
- "S4V3MfGYk8I4fd3WH09yYw==",
- "A+crVyUeynAkEMYKbnFjZw==",
- "vtyHcNQPcUTRuZcQvRUX4Q==",
- "UNKx1ZVv3HNp21zrUSm6ew==",
- "rsAlvGLv2D0swd6ol3WlvA==",
- "2qwqb8ENAR2fpQnw55sPDw==",
- "xBJJuYYnsTJOeFggZSKC4Q==",
- "omvtZZKruPiEt6fV0YXTdg==",
- "JZEgKUhUN+USJsvtF4HZOg==",
- "euG/kpJ5elSDOGNbWWDfNQ==",
- "DiiVmM6/WNcp0MUjSaFq6w==",
- "QCNS8gAml1M2pJ+MxZsueg==",
- "M6+pggFsHfM3alFxcMOFNQ==",
- "YLoWpDTwXnszEQm8FA164Q==",
- "N08oUZtlXbQvO9t3vXnGog==",
- "jkjuJowWuOa4CLY+RZiErQ==",
- "mPf+S+6oAoVIYEVveaiNFA==",
- "R0iVyo5qreP/68uZlZphDA==",
- "GYlqhQgp03B0mXpUhQ+ZCA==",
- "lQNbmWD7PhwNGye+zbc3GQ==",
- "cNeaOJEOzUSDdRmenPQyuw==",
- "Gp66/Txv6ebv5bn85TuQtA==",
- "xAda6DVkcvvqhI8vWZeGyA==",
- "Ggk1Qa0lEdAgCXG6SmCkBA==",
- "MYuO7ZURXtyaf56q7hH4Zw==",
- "RUIdZRTgJBudWUZQFgiFaQ==",
- "bgFJxLirUom2zT0h7LdOpw==",
- "A2gaOpIlrS7TKVQgy9XMSw==",
- "zevXp0lqqnXv9X6Bgmjtqg==",
- "a5iuFqWAdFFsRgp7SFYwNg==",
- "TxTy0TaDsWTcRH3wdBEQLQ==",
- "jephVdKDeJIhXPrdMOJ4qA==",
- "C4KdamfqUPuJ3RGFdpIEdw==",
- "zl6l2Ioz1qovRUIWrSyxVA==",
- "+gGaDxUe0UnNrf3PPg1qQQ==",
- "1HgbrlaLMHS6Qj/0kkaJxg==",
- "eGxTly6Pnu7eV/MKYMmuYw==",
- "RAMKfnlrzNjpyh2BWt6JHg==",
- "4pZQm9ogCZ/EAR9pjJm1eA==",
- "l1zv3erwXIegQFd02NlCag==",
- "uHGyRZchuA4ulmuD5LqquQ==",
- "/vFu89tsV+lbcoiqM/XWog==",
- "63SUgqfQimrmjvy/bEDQ0w==",
- "JLHuf+FlChFDa9LYfTQ4Eg==",
- "I+ZnPePTFX8ZODe14bxgyA==",
- "CtoK1k3U82BkvzuPfQ4pjQ==",
- "6nqQm4C7y+wZ+qX0kVjwmA==",
- "+C3kBxRXIjqBk0EJxe3Xfg==",
- "qVu748pIxEZtiywg4/4qhw==",
- "07o+sKjjRCYkwy/ACyoYhg==",
- "CiLF4dkbLURekBcQbwPUVA==",
- "W/N5/nkp4iQIPYfAagVV7A==",
- "3PJOphhEjw0E4arTfVVwdg==",
- "YdMbARHwB+bSOd0PlTlXiA==",
- "41hbx5Yr7UWxsV6+bWUYUA==",
- "SqJHXD0MorNwHtHL9TbWLg==",
- "pWKGUzm/muwOiBtzkRMnRg==",
- "az9zZ7HTa4FJGRQMcamvEw==",
- "zavAAN8C9Wo8oBLyztp63Q==",
- "yBAnPmwrMJ8kpPP292S/Lw==",
- "E6szQhjuUAz2e0h9ffQfEQ==",
- "Fs3cQxQyS9kM4T8j5R7rWw==",
- "GB5fRLZxnjRUfEe0SwcePQ==",
- "+9OY8xkT9dM/rb2T6ACtOQ==",
- "If2xFBD1p91iDD7ZrsfgjA==",
- "QCFfoMhy8EleZAOpfRY88w==",
- "NobWPk1Z6bHt5s9NHXt/pg==",
- "nK6T4vV4384OIcqO5tQMhA==",
- "Zov1EzK+VomiuwT1+ulQ8g==",
- "pF98OKDvLUlnTzo7wmlpOw==",
- "Wrq9YDsieAMC3Y2DSY5Rcg=="
- ]
-}
diff --git a/application/basilisk/base/content/newtab/newTab.js b/application/basilisk/base/content/newtab/newTab.js
index bbd2ef39d..1731edadc 100644
--- a/application/basilisk/base/content/newtab/newTab.js
+++ b/application/basilisk/base/content/newtab/newTab.js
@@ -11,7 +11,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/PageThumbs.jsm");
Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm");
-Cu.import("resource:///modules/DirectoryLinksProvider.jsm");
Cu.import("resource://gre/modules/NewTabUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Rect",
diff --git a/application/basilisk/base/content/newtab/newTab.xhtml b/application/basilisk/base/content/newtab/newTab.xhtml
index eef51b4b2..7de1ff3d4 100644
--- a/application/basilisk/base/content/newtab/newTab.xhtml
+++ b/application/basilisk/base/content/newtab/newTab.xhtml
@@ -73,7 +73,6 @@
<div id="newtab-horizontal-margin">
<div class="newtab-side-margin"/>
<div id="newtab-grid">
- <h1 id="topsites-heading"/>
</div>
<div class="newtab-side-margin"/>
</div>
diff --git a/application/basilisk/base/content/newtab/page.js b/application/basilisk/base/content/newtab/page.js
index f7626ced2..7c19a9827 100644
--- a/application/basilisk/base/content/newtab/page.js
+++ b/application/basilisk/base/content/newtab/page.js
@@ -48,11 +48,6 @@ var gPage = {
let enabled = gAllPages.enabled;
this._updateAttributes(enabled);
- // Update thumbnails to the new enhanced setting
- if (aData == "browser.newtabpage.enhanced") {
- this.update();
- }
-
// Initialize the whole page if we haven't done that, yet.
if (enabled) {
this._init();
@@ -79,10 +74,7 @@ var gPage = {
update(reason = "") {
// Update immediately if we're visible.
if (!document.hidden) {
- // Ignore updates where reason=links-changed as those signal that the
- // provider's set of links changed. We don't want to update visible pages
- // in that case, it is ok to wait until the user opens the next tab.
- if (reason != "links-changed" && gGrid.ready) {
+ if (gGrid.ready) {
gGrid.refresh();
}
@@ -119,10 +111,6 @@ var gPage = {
document.getElementById("newtab-search-submit").value =
document.body.getAttribute("dir") == "ltr" ? "\u25B6" : "\u25C0";
- if (Services.prefs.getBoolPref("browser.newtabpage.compact")) {
- document.body.classList.add("compact");
- }
-
// Initialize search.
gSearch.init();
@@ -174,16 +162,6 @@ var gPage = {
*/
_handleUnloadEvent: function Page_handleUnloadEvent() {
gAllPages.unregister(this);
- // compute page life-span and send telemetry probe: using milli-seconds will leave
- // many low buckets empty. Instead we use half-second precision to make low end
- // of histogram linear and not lose the change in user attention
- let delta = Math.round((Date.now() - this._firstVisibleTime) / 500);
- if (this._suggestedTilePresent) {
- Services.telemetry.getHistogramById("NEWTAB_PAGE_LIFE_SPAN_SUGGESTED").add(delta);
- }
- else {
- Services.telemetry.getHistogramById("NEWTAB_PAGE_LIFE_SPAN").add(delta);
- }
},
/**
@@ -258,40 +236,5 @@ var gPage = {
},
onPageVisibleAndLoaded() {
- // Send the index of the last visible tile.
- this.reportLastVisibleTileIndex();
- // Maybe tell the user they can undo an initial automigration
- this.maybeShowAutoMigrationUndoNotification();
- },
-
- reportLastVisibleTileIndex() {
- let cwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
-
- let rect = cwu.getBoundsWithoutFlushing(gGrid.node);
- let nodes = cwu.nodesFromRect(rect.left, rect.top, 0, rect.width,
- rect.height, 0, true, false);
-
- let i = -1;
- let lastIndex = -1;
- let sites = gGrid.sites;
-
- for (let node of nodes) {
- if (node.classList && node.classList.contains("newtab-cell")) {
- if (sites[++i]) {
- lastIndex = i;
- if (sites[i].link.targetedSite) {
- // record that suggested tile is shown to use suggested-tiles-histogram
- this._suggestedTilePresent = true;
- }
- }
- }
- }
-
- DirectoryLinksProvider.reportSitesAction(sites, "view", lastIndex);
- },
-
- maybeShowAutoMigrationUndoNotification() {
- sendAsyncMessage("NewTab:MaybeShowAutoMigrationUndoNotification");
- },
+ }
};
diff --git a/application/basilisk/base/content/newtab/sites.js b/application/basilisk/base/content/newtab/sites.js
index 9d103ce9b..00f81869a 100644
--- a/application/basilisk/base/content/newtab/sites.js
+++ b/application/basilisk/base/content/newtab/sites.js
@@ -62,7 +62,7 @@ Site.prototype = {
this._updateAttributes(true);
let changed = gPinnedLinks.pin(this._link, aIndex);
if (changed) {
- // render site again to remove suggested/sponsored tags
+ // render site again
this._render();
}
return changed;
@@ -136,15 +136,6 @@ Site.prototype = {
return str;
},
- _getSuggestedTileExplanation: function() {
- let targetedName = `<strong> ${this.link.targetedName} </strong>`;
- let targetedSite = `<strong> ${this.link.targetedSite} </strong>`;
- if (this.link.explanation) {
- return this._newTabString(this.link.explanation, [targetedName, targetedSite]);
- }
- return newTabString("suggested.button", [targetedName]);
- },
-
/**
* Checks for and modifies link at campaign end time
*/
@@ -155,11 +146,8 @@ Site.prototype = {
this.link.url = Services.io.newURI(this.url, null, null).resolve("/");
// clear supplied images - this triggers thumbnail download for new url
delete this.link.imageURI;
- delete this.link.enhancedImageURI;
// remove endTime to avoid further time checks
delete this.link.endTime;
- // clear enhanced-content image that may still exist in preloaded page
- this._querySelector(".enhanced-content").style.backgroundImage = "";
gPinnedLinks.replace(oldUrl, this.link);
}
},
@@ -171,11 +159,8 @@ Site.prototype = {
// first check for end time, as it may modify the link
this._checkLinkEndTime();
// setup display variables
- let enhanced = gAllPages.enhanced && DirectoryLinksProvider.getEnhancedLink(this.link);
let url = this.url;
- let title = enhanced && enhanced.title ? enhanced.title :
- this.link.type == "history" ? this.link.baseDomain :
- this.title;
+ let title = this.link.type == "history" ? this.link.baseDomain : this.title;
let tooltip = (this.title == url ? this.title : this.title + "\n" + url);
let link = this._querySelector(".newtab-link");
@@ -189,22 +174,6 @@ Site.prototype = {
titleNode.style.backgroundColor = this.link.titleBgColor;
}
- // remove "suggested" attribute to avoid showing "suggested" tag
- // after site was pinned or dropped
- this.node.removeAttribute("suggested");
-
- if (this.link.targetedSite) {
- if (this.node.getAttribute("type") != "sponsored") {
- this._querySelector(".newtab-sponsored").textContent =
- newTabString("suggested.tag");
- }
-
- this.node.setAttribute("suggested", true);
- let explanation = this._getSuggestedTileExplanation();
- this._querySelector(".newtab-suggested").innerHTML =
- `<div class='newtab-suggested-bounds'> ${explanation} </div>`;
- }
-
if (this.isPinned())
this._updateAttributes(true);
// Capture the page if the thumbnail is missing, which will cause page.js
@@ -244,8 +213,7 @@ Site.prototype = {
*/
refreshThumbnail: function Site_refreshThumbnail() {
// Only enhance tiles if that feature is turned on
- let link = gAllPages.enhanced && DirectoryLinksProvider.getEnhancedLink(this.link) ||
- this.link;
+ let link = this.link;
let thumbnail = this._querySelector(".newtab-thumbnail.thumbnail");
if (link.bgColor) {
@@ -267,16 +235,6 @@ Site.prototype = {
placeholder.style.backgroundColor = "hsl(" + hue + ",80%,40%)";
placeholder.textContent = link.baseDomain.substr(0,1).toUpperCase();
}
-
- if (link.enhancedImageURI) {
- let enhanced = this._querySelector(".enhanced-content");
- enhanced.style.backgroundImage = 'url("' + link.enhancedImageURI + '")';
-
- if (this.link.type != link.type) {
- this.node.setAttribute("type", "enhanced");
- this.enhancedId = link.directoryId;
- }
- }
},
_ignoreHoverEvents: function(element) {
@@ -296,13 +254,6 @@ Site.prototype = {
this._node.addEventListener("dragstart", this, false);
this._node.addEventListener("dragend", this, false);
this._node.addEventListener("mouseover", this, false);
-
- // Specially treat the sponsored icon & suggested explanation
- // text to prevent regular hover effects
- let sponsored = this._querySelector(".newtab-sponsored");
- let suggested = this._querySelector(".newtab-suggested");
- this._ignoreHoverEvents(sponsored);
- this._ignoreHoverEvents(suggested);
},
/**
@@ -333,31 +284,6 @@ Site.prototype = {
.add(aIndex);
},
- _toggleLegalText: function(buttonClass, explanationTextClass) {
- let button = this._querySelector(buttonClass);
- if (button.hasAttribute("active")) {
- let explain = this._querySelector(explanationTextClass);
- explain.parentNode.removeChild(explain);
-
- button.removeAttribute("active");
- }
- else {
- let explain = document.createElementNS(HTML_NAMESPACE, "div");
- explain.className = explanationTextClass.slice(1); // Slice off the first character, '.'
- this.node.appendChild(explain);
-
- let link = '<a href="' + TILES_EXPLAIN_LINK + '">' +
- newTabString("learn.link") + "</a>";
- let type = (this.node.getAttribute("suggested") && this.node.getAttribute("type") == "affiliate") ?
- "suggested" : this.node.getAttribute("type");
- let icon = '<input type="button" class="newtab-control newtab-' +
- (type == "enhanced" ? "customize" : "control-block") + '"/>';
- explain.innerHTML = newTabString(type + (type == "sponsored" ? ".explain2" : ".explain"), [icon, link]);
-
- button.setAttribute("active", "true");
- }
- },
-
/**
* Handles site click events.
*/
@@ -376,48 +302,25 @@ Site.prototype = {
action = "click";
}
}
- // Handle sponsored explanation link click
- else if (target.parentElement.classList.contains("sponsored-explain")) {
- action = "sponsored_link";
- }
- else if (target.parentElement.classList.contains("suggested-explain")) {
- action = "suggested_link";
- }
// Only handle primary clicks for the remaining targets
else if (button == 0) {
aEvent.preventDefault();
if (target.classList.contains("newtab-control-block")) {
- // Notify DirectoryLinksProvider of suggested tile block, this may
- // affect if and how suggested tiles are recommended and needs to
- // be reported before pages are updated inside block() call
- if (this.link.targetedSite) {
- DirectoryLinksProvider.handleSuggestedTileBlock();
- }
this.block();
action = "block";
}
- else if (target.classList.contains("sponsored-explain") ||
- target.classList.contains("newtab-sponsored")) {
- this._toggleLegalText(".newtab-sponsored", ".sponsored-explain");
- action = "sponsored";
- }
else if (pinned && target.classList.contains("newtab-control-pin")) {
this.unpin();
action = "unpin";
}
else if (!pinned && target.classList.contains("newtab-control-pin")) {
if (this.pin()) {
- // suggested link has changed - update rest of the pages
+ // link has changed - update rest of the pages
gAllPages.update(gPage);
}
action = "pin";
}
}
-
- // Report all link click actions
- if (action) {
- DirectoryLinksProvider.reportSitesAction(gGrid.sites, action, tileIndex);
- }
},
/**
diff --git a/application/basilisk/base/content/nsContextMenu.js b/application/basilisk/base/content/nsContextMenu.js
index 3f77dcb90..370e5ba60 100644
--- a/application/basilisk/base/content/nsContextMenu.js
+++ b/application/basilisk/base/content/nsContextMenu.js
@@ -4,7 +4,6 @@
# 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/.
-Components.utils.import("resource://gre/modules/ContextualIdentityService.jsm");
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm");
Components.utils.import("resource://gre/modules/LoginManagerContextMenu.jsm");
@@ -113,7 +112,6 @@ nsContextMenu.prototype = {
this.initLeaveDOMFullScreenItems();
this.initClickToPlayItems();
this.initPasswordManagerItems();
- this.initSyncItems();
},
initPageMenuSeparator: function CM_initPageMenuSeparator() {
@@ -142,28 +140,11 @@ nsContextMenu.prototype = {
this.onPlainTextLink = true;
}
- var inContainer = false;
- if (gContextMenuContentData.userContextId) {
- inContainer = true;
- var item = document.getElementById("context-openlinkincontainertab");
-
- item.setAttribute("data-usercontextid", gContextMenuContentData.userContextId);
-
- var label =
- ContextualIdentityService.getUserContextLabel(gContextMenuContentData.userContextId);
- item.setAttribute("label",
- gBrowserBundle.formatStringFromName("userContextOpenLink.label",
- [label], 1));
- }
-
var shouldShow = this.onSaveableLink || isMailtoInternal || this.onPlainTextLink;
var isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
- var showContainers = Services.prefs.getBoolPref("privacy.userContext.enabled");
this.showItem("context-openlink", shouldShow && !isWindowPrivate);
this.showItem("context-openlinkprivate", shouldShow);
- this.showItem("context-openlinkintab", shouldShow && !inContainer);
- this.showItem("context-openlinkincontainertab", shouldShow && inContainer);
- this.showItem("context-openlinkinusercontext-menu", shouldShow && !isWindowPrivate && showContainers);
+ this.showItem("context-openlinkintab", shouldShow);
this.showItem("context-openlinkincurrent", this.onPlainTextLink);
this.showItem("context-sep-open", shouldShow);
},
@@ -540,10 +521,6 @@ nsContextMenu.prototype = {
popup.insertBefore(fragment, insertBeforeElement);
},
- initSyncItems: function() {
- gFxAccounts.initPageContextMenu(this);
- },
-
openPasswordManager: function() {
LoginHelper.openPasswordManager(window, gContextMenuContentData.documentURIObject.host);
},
@@ -958,13 +935,6 @@ nsContextMenu.prototype = {
params[p] = extra[p];
}
- // If we want to change userContextId, we must be sure that we don't
- // propagate the referrer.
- if ("userContextId" in params &&
- params.userContextId != gContextMenuContentData.userContextId) {
- params.noReferrer = true;
- }
-
return params;
},
@@ -982,7 +952,7 @@ nsContextMenu.prototype = {
},
// Open linked-to URL in a new tab.
- openLinkInTab: function(event) {
+ openLinkInTab: function() {
urlSecurityCheck(this.linkURL, this.principal);
let referrerURI = gContextMenuContentData.documentURIObject;
@@ -1003,7 +973,6 @@ nsContextMenu.prototype = {
let params = {
allowMixedContent: persistAllowMixedContentInChildTab,
- userContextId: parseInt(event.target.getAttribute('data-usercontextid')),
};
openLinkIn(this.linkURL, "tab", this._openLinkInParameters(params));
@@ -1779,8 +1748,4 @@ nsContextMenu.prototype = {
menuItem.label = menuLabel;
menuItem.accessKey = gNavigatorBundle.getString("contextMenuSearch.accesskey");
},
- createContainerMenu: function(aEvent) {
- return createUserContextMenu(aEvent, true,
- gContextMenuContentData.userContextId);
- },
};
diff --git a/application/basilisk/base/content/sync/customize.css b/application/basilisk/base/content/sync/customize.css
deleted file mode 100644
index 2bb62595d..000000000
--- a/application/basilisk/base/content/sync/customize.css
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 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/. */
-
-:root {
- font-size: 80%;
-}
-
-#sync-customize-pane {
- padding-inline-start: 74px;
- background: top left url(chrome://browser/skin/sync-128.png) no-repeat;
- background-size: 64px;
-}
-
-#sync-customize-title {
- margin-inline-start: 0;
- padding-bottom: 0.5em;
- font-weight: bold;
-}
-
-#sync-customize-subtitle {
- font-size: 90%;
-}
-
-checkbox {
- margin: 0;
- padding: 0.5em 0 0;
-}
diff --git a/application/basilisk/base/content/sync/customize.js b/application/basilisk/base/content/sync/customize.js
deleted file mode 100644
index f431ac58c..000000000
--- a/application/basilisk/base/content/sync/customize.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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";
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-addEventListener("dialogaccept", function () {
- let pane = document.getElementById("sync-customize-pane");
- // First determine what the preference for the "global" sync enabled pref
- // should be based on the engines selected.
- let prefElts = pane.querySelectorAll("preferences > preference");
- let syncEnabled = false;
- for (let elt of prefElts) {
- if (elt.name.startsWith("services.sync.") && elt.value) {
- syncEnabled = true;
- break;
- }
- }
- Services.prefs.setBoolPref("services.sync.enabled", syncEnabled);
- // and write the individual prefs.
- pane.writePreferences(true);
- window.arguments[0].accepted = true;
-});
diff --git a/application/basilisk/base/content/sync/customize.xul b/application/basilisk/base/content/sync/customize.xul
deleted file mode 100644
index 827edf565..000000000
--- a/application/basilisk/base/content/sync/customize.xul
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- 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/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/sync/customize.css" type="text/css"?>
-
-<!DOCTYPE dialog [
-<!ENTITY % syncCustomizeDTD SYSTEM "chrome://browser/locale/syncCustomize.dtd">
-%syncCustomizeDTD;
-]>
-<dialog id="sync-customize"
- windowtype="Sync:Customize"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="&syncCustomize.dialog.title;"
- buttonlabelaccept="&syncCustomize.acceptButton.label;"
- buttons="accept">
-
- <prefpane id="sync-customize-pane">
- <preferences>
- <preference id="engine.bookmarks" name="services.sync.engine.bookmarks" type="bool"/>
- <preference id="engine.history" name="services.sync.engine.history" type="bool"/>
- <preference id="engine.tabs" name="services.sync.engine.tabs" type="bool"/>
- <preference id="engine.passwords" name="services.sync.engine.passwords" type="bool"/>
- <preference id="engine.addons" name="services.sync.engine.addons" type="bool"/>
- <preference id="engine.prefs" name="services.sync.engine.prefs" type="bool"/>
- </preferences>
-
- <label id="sync-customize-title" value="&syncCustomize.title;"/>
- <description id="sync-customize-subtitle"
- value="&syncCustomize.description;"/>
-
- <vbox align="start">
- <checkbox label="&engine.tabs.label;"
- accesskey="&engine.tabs.accesskey;"
- preference="engine.tabs"/>
- <checkbox label="&engine.bookmarks.label;"
- accesskey="&engine.bookmarks.accesskey;"
- preference="engine.bookmarks"/>
- <checkbox label="&engine.passwords.label;"
- accesskey="&engine.passwords.accesskey;"
- preference="engine.passwords"/>
- <checkbox label="&engine.history.label;"
- accesskey="&engine.history.accesskey;"
- preference="engine.history"/>
- <checkbox label="&engine.addons.label;"
- accesskey="&engine.addons.accesskey;"
- preference="engine.addons"/>
- <checkbox label="&engine.prefs.label;"
- accesskey="&engine.prefs.accesskey;"
- preference="engine.prefs"/>
- </vbox>
-
- </prefpane>
-
- <script type="application/javascript"
- src="chrome://browser/content/sync/customize.js" />
-
-</dialog>
diff --git a/application/basilisk/base/content/tab-content.js b/application/basilisk/base/content/tab-content.js
index 7441b2140..fec13eba7 100644
--- a/application/basilisk/base/content/tab-content.js
+++ b/application/basilisk/base/content/tab-content.js
@@ -20,6 +20,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "AboutReader",
"resource://gre/modules/AboutReader.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode",
"resource://gre/modules/ReaderMode.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Readerable",
+ "resource://gre/modules/Readerable.jsm");
XPCOMUtils.defineLazyGetter(this, "SimpleServiceDiscovery", function() {
let ssdp = Cu.import("resource://gre/modules/SimpleServiceDiscovery.jsm", {}).SimpleServiceDiscovery;
// Register targets
@@ -336,7 +338,7 @@ var AboutReaderListener = {
* painted is not going to work.
*/
updateReaderButton: function(forceNonArticle) {
- if (!ReaderMode.isEnabledForParseOnLoad || this.isAboutReader ||
+ if (!Readerable.isEnabledForParseOnLoad || this.isAboutReader ||
!content || !(content.document instanceof content.HTMLDocument) ||
content.document.mozSyntheticDocument) {
return;
@@ -375,7 +377,7 @@ var AboutReaderListener = {
this.cancelPotentialPendingReadabilityCheck();
// Only send updates when there are articles; there's no point updating with
// |false| all the time.
- if (ReaderMode.isProbablyReaderable(content.document)) {
+ if (Readerable.isProbablyReaderable(content.document)) {
sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: true });
} else if (forceNonArticle) {
sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: false });
@@ -886,33 +888,6 @@ var RefreshBlocker = {
RefreshBlocker.init();
-var UserContextIdNotifier = {
- init() {
- addEventListener("DOMWindowCreated", this);
- },
-
- uninit() {
- removeEventListener("DOMWindowCreated", this);
- },
-
- handleEvent(aEvent) {
- // When the window is created, we want to inform the tabbrowser about
- // the userContextId in use in order to update the UI correctly.
- // Just because we cannot change the userContextId from an active docShell,
- // we don't need to check DOMContentLoaded again.
- this.uninit();
-
- // We use the docShell because content.document can have been loaded before
- // setting the originAttributes.
- let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
- let userContextId = loadContext.originAttributes.userContextId;
-
- sendAsyncMessage("Browser:WindowCreated", { userContextId });
- }
-};
-
-UserContextIdNotifier.init();
-
addMessageListener("AllowScriptsToClose", () => {
content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
diff --git a/application/basilisk/base/content/tabbrowser.xml b/application/basilisk/base/content/tabbrowser.xml
index 52c51db69..0e819a3ed 100644
--- a/application/basilisk/base/content/tabbrowser.xml
+++ b/application/basilisk/base/content/tabbrowser.xml
@@ -814,10 +814,8 @@
}
let unifiedComplete = this.mTabBrowser._unifiedComplete;
- let userContextId = this.mBrowser.getAttribute("usercontextid") || 0;
if (this.mBrowser.registeredOpenURI) {
- unifiedComplete.unregisterOpenPage(this.mBrowser.registeredOpenURI,
- userContextId);
+ unifiedComplete.unregisterOpenPage(this.mBrowser.registeredOpenURI);
delete this.mBrowser.registeredOpenURI;
}
// Tabs in private windows aren't registered as "Open" so
@@ -825,7 +823,7 @@
if (!isBlankPageURL(aLocation.spec) &&
(!PrivateBrowsingUtils.isWindowPrivate(window) ||
PrivateBrowsingUtils.permanentPrivateBrowsing)) {
- unifiedComplete.registerOpenPage(aLocation, userContextId);
+ unifiedComplete.registerOpenPage(aLocation);
this.mBrowser.registeredOpenURI = aLocation;
}
}
@@ -1230,7 +1228,6 @@
this._adjustFocusAfterTabSwitch(this.mCurrentTab);
}
- updateUserContextUIIndicator();
gIdentityHandler.updateSharingIndicator();
this.tabContainer._setPositionalAttributes();
@@ -1486,7 +1483,6 @@
var aSkipAnimation;
var aForceNotRemote;
var aNoReferrer;
- var aUserContextId;
var aRelatedBrowser;
var aOriginPrincipal;
var aOpener;
@@ -1507,7 +1503,6 @@
aSkipAnimation = params.skipAnimation;
aForceNotRemote = params.forceNotRemote;
aNoReferrer = params.noReferrer;
- aUserContextId = params.userContextId;
aRelatedBrowser = params.relatedBrowser;
aOriginPrincipal = params.originPrincipal;
aOpener = params.opener;
@@ -1530,7 +1525,6 @@
allowMixedContent: aAllowMixedContent,
forceNotRemote: aForceNotRemote,
noReferrer: aNoReferrer,
- userContextId: aUserContextId,
originPrincipal: aOriginPrincipal,
relatedBrowser: aRelatedBrowser,
opener: aOpener });
@@ -1551,7 +1545,6 @@
let aTargetTab;
let aNewIndex = -1;
let aPostDatas = [];
- let aUserContextId;
if (arguments.length == 2 &&
typeof arguments[1] == "object") {
let params = arguments[1];
@@ -1562,7 +1555,6 @@
aNewIndex = typeof params.newIndex === "number" ?
params.newIndex : aNewIndex;
aPostDatas = params.postDatas || aPostDatas;
- aUserContextId = params.userContextId;
}
if (!aURIs.length)
@@ -1611,8 +1603,7 @@
ownerTab: owner,
skipAnimation: multiple,
allowThirdPartyFixup: aAllowThirdPartyFixup,
- postData: aPostDatas[0],
- userContextId: aUserContextId
+ postData: aPostDatas[0]
});
if (aNewIndex !== -1) {
this.moveTabTo(firstTabAdded, aNewIndex);
@@ -1625,8 +1616,7 @@
let tab = this.addTab(aURIs[i], {
skipAnimation: true,
allowThirdPartyFixup: aAllowThirdPartyFixup,
- postData: aPostDatas[i],
- userContextId: aUserContextId
+ postData: aPostDatas[i]
});
if (targetTabIndex !== -1)
this.moveTabTo(tab, ++tabNum);
@@ -1899,7 +1889,7 @@
<body>
<![CDATA[
// Supported parameters:
- // userContextId, remote, isPreloadBrowser, uriIsAboutBlank, permanentKey
+ // remote, isPreloadBrowser, uriIsAboutBlank, permanentKey
const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@@ -1911,10 +1901,6 @@
b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
- if (aParams.userContextId) {
- b.setAttribute("usercontextid", aParams.userContextId);
- }
-
if (aParams.remote) {
b.setAttribute("remote", "true");
}
@@ -1993,7 +1979,7 @@
"use strict";
// Supported parameters:
- // forceNotRemote, userContextId
+ // forceNotRemote
let uriIsAboutBlank = !aURI || aURI == "about:blank";
@@ -2011,7 +1997,6 @@
// Private windows are not included because both the label and the
// icon for the tab would be set incorrectly (see bug 1195981).
if (aURI == BROWSER_NEW_TAB_URL &&
- !aParams.userContextId &&
!PrivateBrowsingUtils.isWindowPrivate(window)) {
browser = this._getPreloadedBrowser();
if (browser) {
@@ -2025,7 +2010,6 @@
browser = this._createBrowser({permanentKey: aTab.permanentKey,
remote: remote,
uriIsAboutBlank: uriIsAboutBlank,
- userContextId: aParams.userContextId,
relatedBrowser: aParams.relatedBrowser,
opener: aParams.opener});
}
@@ -2100,7 +2084,6 @@
var aAllowMixedContent;
var aForceNotRemote;
var aNoReferrer;
- var aUserContextId;
var aEventDetail;
var aRelatedBrowser;
var aOriginPrincipal;
@@ -2123,7 +2106,6 @@
aAllowMixedContent = params.allowMixedContent;
aForceNotRemote = params.forceNotRemote;
aNoReferrer = params.noReferrer;
- aUserContextId = params.userContextId;
aEventDetail = params.eventDetail;
aRelatedBrowser = params.relatedBrowser;
aOriginPrincipal = params.originPrincipal;
@@ -2150,11 +2132,6 @@
t.setAttribute("label", aURI);
}
- if (aUserContextId) {
- t.setAttribute("usercontextid", aUserContextId);
- ContextualIdentityService.setTabStyle(t);
- }
-
t.setAttribute("crop", "end");
t.setAttribute("onerror", "this.removeAttribute('image');");
@@ -2204,7 +2181,6 @@
// of tab.linkedBrowser.
let browserParams = {
forceNotRemote: aForceNotRemote,
- userContextId: aUserContextId,
relatedBrowser: aRelatedBrowser,
opener: aOpener,
};
@@ -2583,8 +2559,7 @@
listener.destroy();
if (browser.registeredOpenURI && !aAdoptedByTab) {
- this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI,
- browser.getAttribute("usercontextid") || 0);
+ this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI);
delete browser.registeredOpenURI;
}
@@ -2783,11 +2758,6 @@
if (ourBrowser.isRemoteBrowser != otherBrowser.isRemoteBrowser)
return;
- // Keep the userContextId if set on other browser
- if (otherBrowser.hasAttribute("usercontextid")) {
- ourBrowser.setAttribute("usercontextid", otherBrowser.getAttribute("usercontextid"));
- }
-
// That's gBrowser for the other window, not the tab's browser!
var remoteBrowser = aOtherTab.ownerDocument.defaultView.gBrowser;
var isPending = aOtherTab.hasAttribute("pending");
@@ -2820,10 +2790,6 @@
aOurTab.setAttribute("soundplaying", "true");
modifiedAttrs.push("soundplaying");
}
- if (aOtherTab.hasAttribute("usercontextid")) {
- aOurTab.setUserContextId(aOtherTab.getAttribute("usercontextid"));
- modifiedAttrs.push("usercontextid");
- }
if (aOtherTab.hasAttribute("sharing")) {
aOurTab.setAttribute("sharing", aOtherTab.getAttribute("sharing"));
modifiedAttrs.push("sharing");
@@ -2961,8 +2927,7 @@
<![CDATA[
// If the current URI is registered as open remove it from the list.
if (aOurBrowser.registeredOpenURI) {
- this._unifiedComplete.unregisterOpenPage(aOurBrowser.registeredOpenURI,
- aOurBrowser.getAttribute("usercontextid") || 0);
+ this._unifiedComplete.unregisterOpenPage(aOurBrowser.registeredOpenURI);
delete aOurBrowser.registeredOpenURI;
}
@@ -3302,10 +3267,6 @@
// it in the other window (making it seem to have moved between
// windows).
let params = { eventDetail: { adoptedTab: aTab } };
- if (aTab.hasAttribute("usercontextid")) {
- // new tab must have the same usercontextid as the old one
- params.userContextId = aTab.getAttribute("usercontextid");
- }
let newTab = this.addTab("about:blank", params);
let newBrowser = this.getBrowserForTab(newTab);
let newURL = aTab.linkedBrowser.currentURI.spec;
@@ -4174,11 +4135,7 @@
return true;
if (this._logInit)
return this._shouldLog;
- let result = false;
- try {
- result = Services.prefs.getBoolPref("browser.tabs.remote.logSwitchTiming");
- } catch (ex) {
- }
+ let result = Services.prefs.getBoolPref("browser.tabs.remote.logSwitchTiming", false);
this._shouldLog = result;
this._logInit = true;
return this._shouldLog;
@@ -4625,7 +4582,6 @@
disableSetDesktopBackground: data.disableSetDesktopBg,
loginFillInfo: data.loginFillInfo,
parentAllowsMixedContent: data.parentAllowsMixedContent,
- userContextId: data.userContextId,
};
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
let event = gContextMenuContentData.event;
@@ -4652,17 +4608,6 @@
}
case "Browser:WindowCreated": {
let tab = this.getTabForBrowser(browser);
- if (tab && data.userContextId) {
- ContextualIdentityService.telemetry(data.userContextId);
- tab.setUserContextId(data.userContextId);
- }
-
- // We don't want to update the container icon and identifier if
- // this is not the selected browser.
- if (browser == gBrowser.selectedBrowser) {
- updateUserContextUIIndicator();
- }
-
break;
}
case "Findbar:Keypress": {
@@ -4845,8 +4790,7 @@
for (let tab of this.tabs) {
let browser = tab.linkedBrowser;
if (browser.registeredOpenURI) {
- this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI,
- browser.getAttribute("usercontextid") || 0);
+ this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI);
delete browser.registeredOpenURI;
}
let filter = this._tabFilters.get(tab);
@@ -5247,7 +5191,7 @@
</xul:arrowscrollbox>
</content>
- <implementation implements="nsIDOMEventListener, nsIObserver">
+ <implementation implements="nsIDOMEventListener">
<constructor>
<![CDATA[
this.mTabClipWidth = Services.prefs.getIntPref("browser.tabs.tabClipWidth");
@@ -5260,23 +5204,11 @@
window.addEventListener("resize", this, false);
window.addEventListener("load", this, false);
- try {
- this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled");
- } catch (ex) {
- this._tabAnimationLoggingEnabled = false;
- }
+ this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled", false);
this._browserNewtabpageEnabled = Services.prefs.getBoolPref("browser.newtabpage.enabled");
- this.observe(null, "nsPref:changed", "privacy.userContext.enabled");
- Services.prefs.addObserver("privacy.userContext.enabled", this, false);
]]>
</constructor>
- <destructor>
- <![CDATA[
- Services.prefs.removeObserver("privacy.userContext.enabled", this);
- ]]>
- </destructor>
-
<field name="tabbrowser" readonly="true">
document.getElementById(this.getAttribute("tabbrowser"));
</field>
@@ -5302,55 +5234,6 @@
<field name="_afterHoveredTab">null</field>
<field name="_hoveredTab">null</field>
- <method name="observe">
- <parameter name="aSubject"/>
- <parameter name="aTopic"/>
- <parameter name="aData"/>
- <body><![CDATA[
- switch (aTopic) {
- case "nsPref:changed":
- // This is the only pref observed.
- let containersEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
-
- const newTab = document.getElementById("new-tab-button");
- const newTab2 = document.getAnonymousElementByAttribute(this, "anonid", "tabs-newtab-button")
-
- if (containersEnabled) {
- for (let parent of [newTab, newTab2]) {
- if (!parent)
- continue;
- let popup = document.createElementNS(
- "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
- "menupopup");
- if (parent.id) {
- popup.id = "newtab-popup";
- } else {
- popup.setAttribute("anonid", "newtab-popup");
- }
- popup.className = "new-tab-popup";
- popup.setAttribute("position", "after_end");
- parent.appendChild(popup);
-
- gClickAndHoldListenersOnElement.add(parent);
- parent.setAttribute("type", "menu");
- }
- } else {
- for (let parent of [newTab, newTab2]) {
- if (!parent)
- continue;
- gClickAndHoldListenersOnElement.remove(parent);
- parent.removeAttribute("type");
- if (!parent.firstChild)
- continue;
- parent.firstChild.remove();
- }
- }
-
- break;
- }
- ]]></body>
- </method>
-
<property name="_isCustomizing" readonly="true">
<getter>
let root = document.documentElement;
@@ -6451,7 +6334,6 @@
inBackground = !inBackground;
let targetTab = this._getDragTargetTab(event, true);
- let userContextId = this.selectedItem.getAttribute("usercontextid");
let replace = !!targetTab;
let newIndex = this._getDropIndex(event, true);
let urls = links.map(link => link.url);
@@ -6461,7 +6343,6 @@
allowThirdPartyFixup: true,
targetTab,
newIndex,
- userContextId,
});
}
@@ -6722,14 +6603,6 @@
-->
<field name="muteReason">undefined</field>
- <property name="userContextId" readonly="true">
- <getter>
- return this.hasAttribute("usercontextid")
- ? parseInt(this.getAttribute("usercontextid"))
- : 0;
- </getter>
- </property>
-
<property name="soundPlaying" readonly="true">
<getter>
return this.getAttribute("soundplaying") == "true";
@@ -6857,27 +6730,6 @@
]]>
</body>
</method>
-
- <method name="setUserContextId">
- <parameter name="aUserContextId"/>
- <body>
- <![CDATA[
- if (aUserContextId) {
- if (this.linkedBrowser) {
- this.linkedBrowser.setAttribute("usercontextid", aUserContextId);
- }
- this.setAttribute("usercontextid", aUserContextId);
- } else {
- if (this.linkedBrowser) {
- this.linkedBrowser.removeAttribute("usercontextid");
- }
- this.removeAttribute("usercontextid");
- }
-
- ContextualIdentityService.setTabStyle(this);
- ]]>
- </body>
- </method>
</implementation>
<handlers>
@@ -7054,30 +6906,9 @@
<handlers>
<handler event="popupshowing">
<![CDATA[
- if (event.target.getAttribute("id") == "alltabs_containersMenuTab") {
- createUserContextMenu(event);
- return;
- }
-
- let containersEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
-
- if (event.target.getAttribute("anonid") == "newtab-popup" ||
- event.target.id == "newtab-popup") {
- createUserContextMenu(event);
- } else {
- document.getElementById("alltabs-popup-separator-1").hidden = !containersEnabled;
- let containersTab = document.getElementById("alltabs_containersTab");
-
- containersTab.hidden = !containersEnabled;
- if (PrivateBrowsingUtils.isWindowPrivate(window)) {
- containersTab.setAttribute("disabled", "true");
- }
-
document.getElementById("alltabs_undoCloseTab").disabled =
SessionStore.getClosedTabCount(window) == 0;
- var tabcontainer = gBrowser.tabContainer;
-
// Listen for changes in the tab bar.
tabcontainer.addEventListener("TabAttrModified", this, false);
tabcontainer.addEventListener("TabClose", this, false);
@@ -7094,9 +6925,6 @@
<handler event="popuphidden">
<![CDATA[
- if (event.target.getAttribute("id") == "alltabs_containersMenuTab") {
- return;
- }
// clear out the menu popup and remove the listeners
for (let i = this.childNodes.length - 1; i > 0; i--) {
@@ -7105,9 +6933,6 @@
menuItem.tab.mCorrespondingMenuitem = null;
this.removeChild(menuItem);
}
- if (menuItem.hasAttribute("usercontextid")) {
- this.removeChild(menuItem);
- }
}
var tabcontainer = gBrowser.tabContainer;
tabcontainer.mTabstrip.removeEventListener("scroll", this, false);
diff --git a/application/basilisk/base/content/utilityOverlay.js b/application/basilisk/base/content/utilityOverlay.js
index 38ca82f55..3d27f7d27 100644
--- a/application/basilisk/base/content/utilityOverlay.js
+++ b/application/basilisk/base/content/utilityOverlay.js
@@ -5,7 +5,6 @@
// Services = object with smart getters for common XPCOM services
Components.utils.import("resource://gre/modules/AppConstants.jsm");
-Components.utils.import("resource://gre/modules/ContextualIdentityService.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
@@ -18,6 +17,9 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
+XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
+ "resource://gre/modules/Deprecated.jsm");
+
this.__defineGetter__("BROWSER_NEW_TAB_URL", () => {
if (PrivateBrowsingUtils.isWindowPrivate(window) &&
!PrivateBrowsingUtils.permanentPrivateBrowsing &&
@@ -35,7 +37,7 @@ var gBidiUI = false;
* Determines whether the given url is considered a special URL for new tabs.
*/
function isBlankPageURL(aURL) {
- return aURL == "about:blank" || aURL == "about:newtab" || aURL == "about:logopage";
+ return aURL == "about:blank" || aURL == BROWSER_NEW_TAB_URL || aURL == "about:logopage";
}
function getBrowserURL()
@@ -43,6 +45,13 @@ function getBrowserURL()
return "chrome://browser/content/browser.xul";
}
+function getBoolPref(pref, defaultValue) {
+ Deprecated.warning("getBoolPref is deprecated and will be removed in a future release. " +
+ "You should use Services.pref.getBoolPref (Services.jsm).",
+ "https://github.com/MoonchildProductions/UXP/issues/989");
+ return Services.prefs.getBoolPref(pref, defaultValue);
+}
+
function getTopWin(skipPopups) {
// If this is called in a browser window, use that window regardless of
// whether it's the frontmost window, since commands can be executed in
@@ -61,16 +70,6 @@ function openTopWin(url) {
openUILinkIn(url, "current");
}
-function getBoolPref(prefname, def)
-{
- try {
- return Services.prefs.getBoolPref(prefname);
- }
- catch (er) {
- return def;
- }
-}
-
/* openUILink handles clicks on UI elements that cause URLs to load.
*
* As the third argument, you may pass an object with the same properties as
@@ -137,7 +136,7 @@ function whereToOpenLink( e, ignoreButton, ignoreAlt )
// ignoreButton allows "middle-click paste" to use function without always opening in a new window.
var middle = !ignoreButton && e.button == 1;
- var middleUsesTabs = getBoolPref("browser.tabs.opentabfor.middleclick", true);
+ var middleUsesTabs = Services.prefs.getBoolPref("browser.tabs.opentabfor.middleclick", true);
// Don't do anything special with right-mouse clicks. They're probably clicks on context menu items.
@@ -145,7 +144,7 @@ function whereToOpenLink( e, ignoreButton, ignoreAlt )
if (metaKey || (middle && middleUsesTabs))
return shift ? "tabshifted" : "tab";
- if (alt && getBoolPref("browser.altClickSave", false))
+ if (alt && Services.prefs.getBoolPref("browser.altClickSave", false))
return "save";
if (shift || (middle && !middleUsesTabs))
@@ -176,7 +175,6 @@ function whereToOpenLink( e, ignoreButton, ignoreAlt )
* skipTabAnimation (boolean)
* allowPinnedTabHostChange (boolean)
* allowPopups (boolean)
- * userContextId (unsigned int)
*/
function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) {
var params;
@@ -222,7 +220,6 @@ function openLinkIn(url, where, params) {
var aAllowPinnedTabHostChange = !!params.allowPinnedTabHostChange;
var aNoReferrer = params.noReferrer;
var aAllowPopups = !!params.allowPopups;
- var aUserContextId = params.userContextId;
var aIndicateErrorPageLoad = params.indicateErrorPageLoad;
var aPrincipal = params.originPrincipal;
var aTriggeringPrincipal = params.triggeringPrincipal;
@@ -268,7 +265,6 @@ function openLinkIn(url, where, params) {
function useOAForPrincipal(principal) {
if (principal && principal.isCodebasePrincipal) {
let attrs = {
- userContextId: aUserContextId,
privateBrowsingId: aIsPrivate || (w && PrivateBrowsingUtils.isWindowPrivate(w)),
};
return Services.scriptSecurityManager.createCodebasePrincipal(principal.URI, attrs);
@@ -315,17 +311,12 @@ function openLinkIn(url, where, params) {
createInstance(Ci.nsISupportsPRUint32);
referrerPolicySupports.data = aReferrerPolicy;
- var userContextIdSupports = Cc["@mozilla.org/supports-PRUint32;1"].
- createInstance(Ci.nsISupportsPRUint32);
- userContextIdSupports.data = aUserContextId;
-
sa.appendElement(wuri, /* weak =*/ false);
sa.appendElement(charset, /* weak =*/ false);
sa.appendElement(referrerURISupports, /* weak =*/ false);
sa.appendElement(aPostData, /* weak =*/ false);
sa.appendElement(allowThirdPartyFixupSupports, /* weak =*/ false);
sa.appendElement(referrerPolicySupports, /* weak =*/ false);
- sa.appendElement(userContextIdSupports, /* weak =*/ false);
sa.appendElement(aPrincipal, /* weak =*/ false);
sa.appendElement(aTriggeringPrincipal, /* weak =*/ false);
@@ -342,7 +333,7 @@ function openLinkIn(url, where, params) {
if (loadInBackground == null) {
loadInBackground = aFromChrome ?
false :
- getBoolPref("browser.tabs.loadInBackground");
+ Services.prefs.getBoolPref("browser.tabs.loadInBackground");
}
let uriObj;
@@ -418,8 +409,7 @@ function openLinkIn(url, where, params) {
flags: flags,
referrerURI: aNoReferrer ? null : aReferrerURI,
referrerPolicy: aReferrerPolicy,
- postData: aPostData,
- userContextId: aUserContextId
+ postData: aPostData
});
browserUsedForLoad = aCurrentBrowser;
break;
@@ -438,7 +428,6 @@ function openLinkIn(url, where, params) {
skipAnimation: aSkipTabAnimation,
allowMixedContent: aAllowMixedContent,
noReferrer: aNoReferrer,
- userContextId: aUserContextId,
originPrincipal: aPrincipal,
triggeringPrincipal: aTriggeringPrincipal,
});
@@ -482,74 +471,6 @@ function checkForMiddleClick(node, event) {
}
}
-// Populate a menu with user-context menu items. This method should be called
-// by onpopupshowing passing the event as first argument.
-function createUserContextMenu(event, isContextMenu = false, excludeUserContextId = 0) {
- while (event.target.hasChildNodes()) {
- event.target.removeChild(event.target.firstChild);
- }
-
- let bundle = document.getElementById("bundle_browser");
- let docfrag = document.createDocumentFragment();
-
- // If we are excluding a userContextId, we want to add a 'no-container' item.
- if (excludeUserContextId) {
- let menuitem = document.createElement("menuitem");
- menuitem.setAttribute("data-usercontextid", "0");
- menuitem.setAttribute("label", bundle.getString("userContextNone.label"));
- menuitem.setAttribute("accesskey", bundle.getString("userContextNone.accesskey"));
-
- // We don't set an oncommand/command attribute because if we have
- // to exclude a userContextId we are generating the contextMenu and
- // isContextMenu will be true.
-
- docfrag.appendChild(menuitem);
-
- let menuseparator = document.createElement("menuseparator");
- docfrag.appendChild(menuseparator);
- }
-
- ContextualIdentityService.getIdentities().forEach(identity => {
- if (identity.userContextId == excludeUserContextId) {
- return;
- }
-
- let menuitem = document.createElement("menuitem");
- menuitem.setAttribute("data-usercontextid", identity.userContextId);
- menuitem.setAttribute("label", ContextualIdentityService.getUserContextLabel(identity.userContextId));
-
- if (identity.accessKey) {
- menuitem.setAttribute("accesskey", bundle.getString(identity.accessKey));
- }
-
- menuitem.classList.add("menuitem-iconic");
- menuitem.setAttribute("data-identity-color", identity.color);
-
- if (!isContextMenu) {
- menuitem.setAttribute("command", "Browser:NewUserContextTab");
- }
-
- menuitem.setAttribute("data-identity-icon", identity.icon);
-
- docfrag.appendChild(menuitem);
- });
-
- if (!isContextMenu) {
- docfrag.appendChild(document.createElement("menuseparator"));
-
- let menuitem = document.createElement("menuitem");
- menuitem.setAttribute("label",
- bundle.getString("userContext.aboutPage.label"));
- menuitem.setAttribute("accesskey",
- bundle.getString("userContext.aboutPage.accesskey"));
- menuitem.setAttribute("command", "Browser:OpenAboutContainers");
- docfrag.appendChild(menuitem);
- }
-
- event.target.appendChild(docfrag);
- return true;
-}
-
// Closes all popups that are ancestors of the node.
function closeMenus(node)
{
@@ -652,7 +573,7 @@ function getShellService()
function isBidiEnabled() {
// first check the pref.
- if (getBoolPref("bidi.browser.ui", false))
+ if (Services.prefs.getBoolPref("bidi.browser.ui", false))
return true;
// then check intl.uidirection.<locale>
@@ -914,7 +835,7 @@ function openHelpLink(aHelpTopic, aCalledFromModal, aWhere) {
function openPrefsHelp() {
// non-instant apply prefwindows are usually modal, so we can't open in the topmost window,
// since its probably behind the window.
- var instantApply = getBoolPref("browser.preferences.instantApply");
+ var instantApply = Services.prefs.getBoolPref("browser.preferences.instantApply");
var helpTopic = document.getElementsByTagName("prefwindow")[0].currentPane.helpTopic;
openHelpLink(helpTopic, !instantApply);
diff --git a/application/basilisk/base/content/web-panels.xul b/application/basilisk/base/content/web-panels.xul
index ed868c24a..78f8954c1 100644
--- a/application/basilisk/base/content/web-panels.xul
+++ b/application/basilisk/base/content/web-panels.xul
@@ -23,7 +23,6 @@
<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
<script type="application/javascript" src="chrome://browser/content/browser.js"/>
<script type="application/javascript" src="chrome://browser/content/browser-places.js"/>
- <script type="application/javascript" src="chrome://browser/content/browser-fxaccounts.js"/>
<script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/>
<script type="application/javascript" src="chrome://browser/content/web-panels.js"/>
diff --git a/application/basilisk/base/jar.mn b/application/basilisk/base/jar.mn
index ddfb0ffe8..76727731b 100644
--- a/application/basilisk/base/jar.mn
+++ b/application/basilisk/base/jar.mn
@@ -15,7 +15,6 @@ browser.jar:
* content/browser/aboutDialog.xul (content/aboutDialog.xul)
content/browser/aboutDialog.js (content/aboutDialog.js)
content/browser/aboutDialog.css (content/aboutDialog.css)
- content/browser/aboutRobots.xhtml (content/aboutRobots.xhtml)
* content/browser/abouthome/aboutHome.xhtml (content/abouthome/aboutHome.xhtml)
content/browser/abouthome/aboutHome.js (content/abouthome/aboutHome.js)
* content/browser/abouthome/aboutHome.css (content/abouthome/aboutHome.css)
@@ -25,7 +24,9 @@ browser.jar:
content/browser/abouthome/bookmarks.png (content/abouthome/bookmarks.png)
content/browser/abouthome/history.png (content/abouthome/history.png)
content/browser/abouthome/addons.png (content/abouthome/addons.png)
+#ifdef MOZ_SERVICES_SYNC
content/browser/abouthome/sync.png (content/abouthome/sync.png)
+#endif
content/browser/abouthome/settings.png (content/abouthome/settings.png)
content/browser/abouthome/restore.png (content/abouthome/restore.png)
content/browser/abouthome/restore-large.png (content/abouthome/restore-large.png)
@@ -36,7 +37,9 @@ browser.jar:
content/browser/abouthome/bookmarks@2x.png (content/abouthome/bookmarks@2x.png)
content/browser/abouthome/history@2x.png (content/abouthome/history@2x.png)
content/browser/abouthome/addons@2x.png (content/abouthome/addons@2x.png)
+#ifdef MOZ_SERVICES_SYNC
content/browser/abouthome/sync@2x.png (content/abouthome/sync@2x.png)
+#endif
content/browser/abouthome/settings@2x.png (content/abouthome/settings@2x.png)
content/browser/abouthome/restore@2x.png (content/abouthome/restore@2x.png)
content/browser/abouthome/restore-large@2x.png (content/abouthome/restore-large@2x.png)
@@ -49,18 +52,6 @@ browser.jar:
content/browser/abouthealthreport/abouthealth.js (content/abouthealthreport/abouthealth.js)
content/browser/abouthealthreport/abouthealth.css (content/abouthealthreport/abouthealth.css)
#endif
- content/browser/aboutaccounts/aboutaccounts.xhtml (content/aboutaccounts/aboutaccounts.xhtml)
- content/browser/aboutaccounts/aboutaccounts.js (content/aboutaccounts/aboutaccounts.js)
- content/browser/aboutaccounts/aboutaccounts.css (content/aboutaccounts/aboutaccounts.css)
- content/browser/aboutaccounts/main.css (content/aboutaccounts/main.css)
- content/browser/aboutaccounts/normalize.css (content/aboutaccounts/normalize.css)
- content/browser/aboutaccounts/images/fox.png (content/aboutaccounts/images/fox.png)
- content/browser/aboutaccounts/images/graphic_sync_intro.png (content/aboutaccounts/images/graphic_sync_intro.png)
- content/browser/aboutaccounts/images/graphic_sync_intro@2x.png (content/aboutaccounts/images/graphic_sync_intro@2x.png)
-
-
- content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
- content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
content/browser/aboutTabCrashed.css (content/aboutTabCrashed.css)
content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js)
content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml)
@@ -76,17 +67,15 @@ browser.jar:
content/browser/browser-feeds.js (content/browser-feeds.js)
content/browser/browser-fullScreenAndPointerLock.js (content/browser-fullScreenAndPointerLock.js)
content/browser/browser-fullZoom.js (content/browser-fullZoom.js)
- content/browser/browser-fxaccounts.js (content/browser-fxaccounts.js)
content/browser/browser-gestureSupport.js (content/browser-gestureSupport.js)
* content/browser/browser-media.js (content/browser-media.js)
- content/browser/browser-places.js (content/browser-places.js)
+* content/browser/browser-places.js (content/browser-places.js)
content/browser/browser-plugins.js (content/browser-plugins.js)
content/browser/browser-refreshblocker.js (content/browser-refreshblocker.js)
#ifdef MOZ_SAFE_BROWSING
content/browser/browser-safebrowsing.js (content/browser-safebrowsing.js)
#endif
content/browser/browser-sidebar.js (content/browser-sidebar.js)
-* content/browser/browser-syncui.js (content/browser-syncui.js)
* content/browser/browser-tabPreviews.xml (content/browser-tabPreviews.xml)
#ifdef CAN_DRAW_IN_TITLEBAR
content/browser/browser-tabsintitlebar.js (content/browser-tabsintitlebar.js)
@@ -125,8 +114,6 @@ browser.jar:
content/browser/newtab/newTab.xhtml (content/newtab/newTab.xhtml)
* content/browser/newtab/newTab.js (content/newtab/newTab.js)
content/browser/newtab/newTab.css (content/newtab/newTab.css)
- content/browser/newtab/newTab.inadjacent.json (content/newtab/newTab.inadjacent.json)
- content/browser/newtab/alternativeDefaultSites.json (content/newtab/alternativeDefaultSites.json)
* content/browser/pageinfo/pageInfo.xul (content/pageinfo/pageInfo.xul)
content/browser/pageinfo/pageInfo.js (content/pageinfo/pageInfo.js)
content/browser/pageinfo/pageInfo.css (content/pageinfo/pageInfo.css)
@@ -135,23 +122,6 @@ browser.jar:
content/browser/pageinfo/feeds.xml (content/pageinfo/feeds.xml)
content/browser/pageinfo/permissions.js (content/pageinfo/permissions.js)
content/browser/pageinfo/security.js (content/pageinfo/security.js)
- content/browser/sync/aboutSyncTabs.xul (content/sync/aboutSyncTabs.xul)
-* content/browser/sync/aboutSyncTabs.js (content/sync/aboutSyncTabs.js)
- content/browser/sync/aboutSyncTabs.css (content/sync/aboutSyncTabs.css)
- content/browser/sync/aboutSyncTabs-bindings.xml (content/sync/aboutSyncTabs-bindings.xml)
- content/browser/sync/setup.xul (content/sync/setup.xul)
- content/browser/sync/addDevice.js (content/sync/addDevice.js)
- content/browser/sync/addDevice.xul (content/sync/addDevice.xul)
- content/browser/sync/setup.js (content/sync/setup.js)
- content/browser/sync/genericChange.xul (content/sync/genericChange.xul)
- content/browser/sync/genericChange.js (content/sync/genericChange.js)
- content/browser/sync/key.xhtml (content/sync/key.xhtml)
- content/browser/sync/utils.js (content/sync/utils.js)
- content/browser/sync/customize.xul (content/sync/customize.xul)
- content/browser/sync/customize.js (content/sync/customize.js)
- content/browser/sync/customize.css (content/sync/customize.css)
- content/browser/sync/quota.xul (content/sync/quota.xul)
- content/browser/sync/quota.js (content/sync/quota.js)
content/browser/safeMode.css (content/safeMode.css)
content/browser/safeMode.js (content/safeMode.js)
content/browser/safeMode.xul (content/safeMode.xul)
diff --git a/application/basilisk/components/about/AboutRedirector.cpp b/application/basilisk/components/about/AboutRedirector.cpp
index b77949ea7..d52b063e2 100644
--- a/application/basilisk/components/about/AboutRedirector.cpp
+++ b/application/basilisk/components/about/AboutRedirector.cpp
@@ -80,11 +80,6 @@ static RedirEntry kRedirMap[] = {
nsIAboutModule::ALLOW_SCRIPT
},
{
- "robots", "chrome://browser/content/aboutRobots.xhtml",
- nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
- nsIAboutModule::ALLOW_SCRIPT
- },
- {
"searchreset", "chrome://browser/content/search/searchReset.xhtml",
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT
@@ -97,10 +92,16 @@ static RedirEntry kRedirMap[] = {
"welcomeback", "chrome://browser/content/aboutWelcomeBack.xhtml",
nsIAboutModule::ALLOW_SCRIPT
},
+#ifdef MOZ_SERVICES_SYNC
+ {
+ "sync-progress", "chrome://browser/content/sync/progress.xhtml",
+ nsIAboutModule::ALLOW_SCRIPT
+ },
{
"sync-tabs", "chrome://browser/content/sync/aboutSyncTabs.xul",
nsIAboutModule::ALLOW_SCRIPT
},
+#endif
{ "home", "chrome://browser/content/abouthome/aboutHome.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
@@ -128,10 +129,6 @@ static RedirEntry kRedirMap[] = {
},
#endif
{
- "accounts", "chrome://browser/content/aboutaccounts/aboutaccounts.xhtml",
- nsIAboutModule::ALLOW_SCRIPT
- },
- {
"reader", "chrome://global/content/reader/aboutReader.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT |
diff --git a/application/basilisk/components/build/nsModule.cpp b/application/basilisk/components/build/nsModule.cpp
index 1baccd710..3fdde8823 100644
--- a/application/basilisk/components/build/nsModule.cpp
+++ b/application/basilisk/components/build/nsModule.cpp
@@ -94,16 +94,17 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "feeds", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "privatebrowsing", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "rights", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
- { NS_ABOUT_MODULE_CONTRACTID_PREFIX "robots", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "searchreset", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "sessionrestore", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "welcomeback", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
+#ifdef MOZ_SERVICES_SYNC
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-tabs", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
+ { NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-progress", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
+#endif
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "home", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "preferences", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "downloads", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
- { NS_ABOUT_MODULE_CONTRACTID_PREFIX "accounts", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#ifdef MOZ_SERVICES_HEALTHREPORT
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "healthreport", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#endif
diff --git a/application/basilisk/components/contextualidentity/content/usercontext.css b/application/basilisk/components/contextualidentity/content/usercontext.css
deleted file mode 100644
index 728275d9f..000000000
--- a/application/basilisk/components/contextualidentity/content/usercontext.css
+++ /dev/null
@@ -1,91 +0,0 @@
-[data-identity-color="blue"] {
- --identity-tab-color: #0996f8;
- --identity-icon-color: #00a7e0;
-}
-
-[data-identity-color="turquoise"] {
- --identity-tab-color: #01bdad;
- --identity-icon-color: #01bdad;
-}
-
-[data-identity-color="green"] {
- --identity-tab-color: #57bd35;
- --identity-icon-color: #7dc14c;
-}
-
-[data-identity-color="yellow"] {
- --identity-tab-color: #ffcb00;
- --identity-icon-color: #ffcb00;
-}
-
-[data-identity-color="orange"] {
- --identity-tab-color: #ff9216;
- --identity-icon-color: #ff9216;
-}
-
-[data-identity-color="red"] {
- --identity-tab-color: #d92215;
- --identity-icon-color: #d92215;
-}
-
-[data-identity-color="pink"] {
- --identity-tab-color: #ea385e;
- --identity-icon-color: #ee5195;
-}
-
-[data-identity-color="purple"] {
- --identity-tab-color: #7a2f7a;
- --identity-icon-color: #7a2f7a;
-}
-
-[data-identity-icon="fingerprint"] {
- --identity-icon: url("chrome://browser/content/usercontext.svg#fingerprint");
-}
-
-[data-identity-icon="briefcase"] {
- --identity-icon: url("chrome://browser/content/usercontext.svg#briefcase");
-}
-
-[data-identity-icon="dollar"] {
- --identity-icon: url("chrome://browser/content/usercontext.svg#dollar");
-}
-
-[data-identity-icon="cart"] {
- --identity-icon: url("chrome://browser/content/usercontext.svg#cart");
-}
-
-[data-identity-icon="circle"] {
- --identity-icon: url("chrome://browser/content/usercontext.svg#circle");
-}
-
-#userContext-indicator {
- height: 16px;
- width: 16px;
-}
-
-#userContext-label {
- margin-inline-end: 3px;
- color: var(--identity-tab-color);
-}
-
-#userContext-icons {
- -moz-box-align: center;
-}
-
-.tabbrowser-tab[usercontextid] {
- background-image: linear-gradient(to right, transparent 20%, var(--identity-tab-color) 30%, var(--identity-tab-color) 70%, transparent 80%);
- background-size: auto 2px;
- background-repeat: no-repeat;
-}
-
-.userContext-icon,
-.menuitem-iconic[data-usercontextid] > .menu-iconic-left > .menu-iconic-icon,
-.subviewbutton[usercontextid] > .toolbarbutton-icon,
-#userContext-indicator {
- background-image: var(--identity-icon);
- filter: url(chrome://browser/skin/filters.svg#fill);
- fill: var(--identity-icon-color);
- background-size: contain;
- background-repeat: no-repeat;
- background-position: center center;
-}
diff --git a/application/basilisk/components/contextualidentity/jar.mn b/application/basilisk/components/contextualidentity/jar.mn
deleted file mode 100644
index 848245949..000000000
--- a/application/basilisk/components/contextualidentity/jar.mn
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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/usercontext/usercontext.css (content/usercontext.css)
diff --git a/application/basilisk/components/customizableui/CustomizableUI.jsm b/application/basilisk/components/customizableui/CustomizableUI.jsm
index cb0f519b2..d56d63d99 100644
--- a/application/basilisk/components/customizableui/CustomizableUI.jsm
+++ b/application/basilisk/components/customizableui/CustomizableUI.jsm
@@ -158,10 +158,7 @@ var gUIStateBeforeReset = {
XPCOMUtils.defineLazyGetter(this, "log", () => {
let scope = {};
Cu.import("resource://gre/modules/Console.jsm", scope);
- let debug;
- try {
- debug = Services.prefs.getBoolPref(kPrefCustomizationDebug);
- } catch (ex) {}
+ let debug = Services.prefs.getBoolPref(kPrefCustomizationDebug, false);
let consoleOptions = {
maxLogLevel: debug ? "all" : "log",
prefix: "CustomizableUI",
@@ -200,7 +197,6 @@ var CustomizableUIInternal = {
"find-button",
"preferences-button",
"add-ons-button",
- "sync-button",
];
if (!AppConstants.MOZ_DEV_EDITION) {
@@ -1915,16 +1911,10 @@ var CustomizableUIInternal = {
// state immediately when a browser window opens, which is important for
// other consumers of this API.
loadSavedState: function() {
- let state = null;
- try {
- state = Services.prefs.getCharPref(kPrefCustomizationState);
- } catch (e) {
- log.debug("No saved state found");
- // This will fail if nothing has been customized, so silently fall back to
- // the defaults.
- }
-
+ let state = Services.prefs.getCharPref(kPrefCustomizationState, "");
if (!state) {
+ log.debug("No saved state found");
+ // Nothing has been customized, so silently fall back to the defaults.
return;
}
try {
@@ -2209,10 +2199,7 @@ var CustomizableUIInternal = {
this.notifyListeners("onWidgetAdded", widget.id, widget.currentArea,
widget.currentPosition);
} else if (widgetMightNeedAutoAdding) {
- let autoAdd = true;
- try {
- autoAdd = Services.prefs.getBoolPref(kPrefCustomizationAutoAdd);
- } catch (e) {}
+ let autoAdd = Services.prefs.getBoolPref(kPrefCustomizationAutoAdd, true);
// If the widget doesn't have an existing placement, and it hasn't been
// seen before, then add it to its default area so it can be used.
diff --git a/application/basilisk/components/customizableui/CustomizableWidgets.jsm b/application/basilisk/components/customizableui/CustomizableWidgets.jsm
index 09b3f167e..d4a191a97 100644
--- a/application/basilisk/components/customizableui/CustomizableWidgets.jsm
+++ b/application/basilisk/components/customizableui/CustomizableWidgets.jsm
@@ -23,8 +23,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
"resource://gre/modules/CharsetMenu.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
- "resource://gre/modules/ContextualIdentityService.jsm");
XPCOMUtils.defineLazyGetter(this, "CharsetBundle", function() {
const kCharsetBundle = "chrome://global/locale/charsetMenu.properties";
@@ -42,10 +40,7 @@ const kWidePanelItemClass = "panel-wide-item";
XPCOMUtils.defineLazyGetter(this, "log", () => {
let scope = {};
Cu.import("resource://gre/modules/Console.jsm", scope);
- let debug;
- try {
- debug = Services.prefs.getBoolPref(kPrefCustomizationDebug);
- } catch (ex) {}
+ let debug = Services.prefs.getBoolPref(kPrefCustomizationDebug, false);
let consoleOptions = {
maxLogLevel: debug ? "all" : "log",
prefix: "CustomizableWidgets",
@@ -288,144 +283,6 @@ const CustomizableWidgets = [
log.debug("History view is being hidden!");
}
}, {
- id: "sync-button",
- label: "remotetabs-panelmenu.label",
- tooltiptext: "remotetabs-panelmenu.tooltiptext2",
- type: "view",
- viewId: "PanelUI-remotetabs",
- defaultArea: CustomizableUI.AREA_PANEL,
- deckIndices: {
- DECKINDEX_TABS: 0,
- DECKINDEX_TABSDISABLED: 1,
- DECKINDEX_FETCHING: 2,
- DECKINDEX_NOCLIENTS: 3,
- },
- onCreated(aNode) {
- // Add an observer to the button so we get the animation during sync.
- // (Note the observer sets many attributes, including label and
- // tooltiptext, but we only want the 'syncstatus' attribute for the
- // animation)
- let doc = aNode.ownerDocument;
- let obnode = doc.createElementNS(kNSXUL, "observes");
- obnode.setAttribute("element", "sync-status");
- obnode.setAttribute("attribute", "syncstatus");
- aNode.appendChild(obnode);
- },
- setDeckIndex(index) {
- let deck = this._tabsList.ownerDocument.getElementById("PanelUI-remotetabs-deck");
- // We call setAttribute instead of relying on the XBL property setter due
- // to things going wrong when we try and set the index before the XBL
- // binding has been created - see bug 1241851 for the gory details.
- deck.setAttribute("selectedIndex", index);
- },
-
- _showTabsPromise: Promise.resolve(),
- // Update the tab list after any existing in-flight updates are complete.
- _showTabs() {
- this._showTabsPromise = this._showTabsPromise.then(() => {
- return this.__showTabs();
- });
- },
- // Return a new promise to update the tab list.
- __showTabs() {
- let doc = this._tabsList.ownerDocument;
- return SyncedTabs.getTabClients().then(clients => {
- // The view may have been hidden while the promise was resolving.
- if (!this._tabsList) {
- return;
- }
- if (clients.length === 0 && !SyncedTabs.hasSyncedThisSession) {
- // the "fetching tabs" deck is being shown - let's leave it there.
- // When that first sync completes we'll be notified and update.
- return;
- }
-
- if (clients.length === 0) {
- this.setDeckIndex(this.deckIndices.DECKINDEX_NOCLIENTS);
- return;
- }
-
- this.setDeckIndex(this.deckIndices.DECKINDEX_TABS);
- this._clearTabList();
- SyncedTabs.sortTabClientsByLastUsed(clients, 50 /* maxTabs */);
- let fragment = doc.createDocumentFragment();
-
- for (let client of clients) {
- // add a menu separator for all clients other than the first.
- if (fragment.lastChild) {
- let separator = doc.createElementNS(kNSXUL, "menuseparator");
- fragment.appendChild(separator);
- }
- this._appendClient(client, fragment);
- }
- this._tabsList.appendChild(fragment);
- }).catch(err => {
- Cu.reportError(err);
- }).then(() => {
- // an observer for tests.
- Services.obs.notifyObservers(null, "synced-tabs-menu:test:tabs-updated", null);
- });
- },
- _clearTabList () {
- let list = this._tabsList;
- while (list.lastChild) {
- list.lastChild.remove();
- }
- },
- _showNoClientMessage() {
- this._appendMessageLabel("notabslabel");
- },
- _appendMessageLabel(messageAttr, appendTo = null) {
- if (!appendTo) {
- appendTo = this._tabsList;
- }
- let message = this._tabsList.getAttribute(messageAttr);
- let doc = this._tabsList.ownerDocument;
- let messageLabel = doc.createElementNS(kNSXUL, "label");
- messageLabel.textContent = message;
- appendTo.appendChild(messageLabel);
- return messageLabel;
- },
- _appendClient: function (client, attachFragment) {
- let doc = attachFragment.ownerDocument;
- // Create the element for the remote client.
- let clientItem = doc.createElementNS(kNSXUL, "label");
- clientItem.setAttribute("itemtype", "client");
- let window = doc.defaultView;
- clientItem.setAttribute("tooltiptext",
- window.gSyncUI.formatLastSyncDate(new Date(client.lastModified)));
- clientItem.textContent = client.name;
-
- attachFragment.appendChild(clientItem);
-
- if (client.tabs.length == 0) {
- let label = this._appendMessageLabel("notabsforclientlabel", attachFragment);
- label.setAttribute("class", "PanelUI-remotetabs-notabsforclient-label");
- } else {
- for (let tab of client.tabs) {
- let tabEnt = this._createTabElement(doc, tab);
- attachFragment.appendChild(tabEnt);
- }
- }
- },
- _createTabElement(doc, tabInfo) {
- let item = doc.createElementNS(kNSXUL, "toolbarbutton");
- let tooltipText = (tabInfo.title ? tabInfo.title + "\n" : "") + tabInfo.url;
- item.setAttribute("itemtype", "tab");
- item.setAttribute("class", "subviewbutton");
- item.setAttribute("targetURI", tabInfo.url);
- item.setAttribute("label", tabInfo.title != "" ? tabInfo.title : tabInfo.url);
- item.setAttribute("image", tabInfo.icon);
- item.setAttribute("tooltiptext", tooltipText);
- // We need to use "click" instead of "command" here so openUILink
- // respects different buttons (eg, to open in a new tab).
- item.addEventListener("click", e => {
- doc.defaultView.openUILink(tabInfo.url, e);
- CustomizableUI.hidePanelForNode(item);
- });
- return item;
- },
- }, {
id: "privatebrowsing-button",
shortcutId: "key_privatebrowsing",
defaultArea: CustomizableUI.AREA_PANEL,
@@ -977,89 +834,6 @@ const CustomizableWidgets = [
let win = aEvent.view;
win.MailIntegration.sendLinkForBrowser(win.gBrowser.selectedBrowser)
}
- }, {
- id: "containers-panelmenu",
- type: "view",
- viewId: "PanelUI-containers",
- hasObserver: false,
- onCreated: function(aNode) {
- let doc = aNode.ownerDocument;
- let win = doc.defaultView;
- let items = doc.getElementById("PanelUI-containersItems");
-
- let onItemCommand = function (aEvent) {
- let item = aEvent.target;
- if (item.hasAttribute("usercontextid")) {
- let userContextId = parseInt(item.getAttribute("usercontextid"));
- win.openUILinkIn(win.BROWSER_NEW_TAB_URL, "tab", {userContextId});
- }
- };
- items.addEventListener("command", onItemCommand);
-
- if (PrivateBrowsingUtils.isWindowPrivate(win)) {
- aNode.setAttribute("disabled", "true");
- }
-
- this.updateVisibility(aNode);
-
- if (!this.hasObserver) {
- Services.prefs.addObserver("privacy.userContext.enabled", this, true);
- this.hasObserver = true;
- }
- },
- onViewShowing: function(aEvent) {
- let doc = aEvent.target.ownerDocument;
-
- let items = doc.getElementById("PanelUI-containersItems");
-
- while (items.firstChild) {
- items.firstChild.remove();
- }
-
- let fragment = doc.createDocumentFragment();
- let bundle = doc.getElementById("bundle_browser");
-
- ContextualIdentityService.getIdentities().forEach(identity => {
- let label = ContextualIdentityService.getUserContextLabel(identity.userContextId);
-
- let item = doc.createElementNS(kNSXUL, "toolbarbutton");
- item.setAttribute("label", label);
- item.setAttribute("usercontextid", identity.userContextId);
- item.setAttribute("class", "subviewbutton");
- item.setAttribute("data-identity-color", identity.color);
- item.setAttribute("data-identity-icon", identity.icon);
-
- fragment.appendChild(item);
- });
-
- fragment.appendChild(doc.createElementNS(kNSXUL, "menuseparator"));
-
- let item = doc.createElementNS(kNSXUL, "toolbarbutton");
- item.setAttribute("label", bundle.getString("userContext.aboutPage.label"));
- item.setAttribute("command", "Browser:OpenAboutContainers");
- item.setAttribute("class", "subviewbutton");
- fragment.appendChild(item);
-
- items.appendChild(fragment);
- },
-
- updateVisibility(aNode) {
- aNode.hidden = !Services.prefs.getBoolPref("privacy.userContext.enabled");
- },
-
- observe(aSubject, aTopic, aData) {
- let {instances} = CustomizableUI.getWidget("containers-panelmenu");
- for (let {node} of instances) {
- if (node) {
- this.updateVisibility(node);
- }
- }
- },
-
- QueryInterface: XPCOMUtils.generateQI([
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver
- ]),
}];
let preferencesButton = {
diff --git a/application/basilisk/components/customizableui/CustomizeMode.jsm b/application/basilisk/components/customizableui/CustomizeMode.jsm
index 4365ddfbc..2958655d2 100644
--- a/application/basilisk/components/customizableui/CustomizeMode.jsm
+++ b/application/basilisk/components/customizableui/CustomizeMode.jsm
@@ -40,9 +40,7 @@ let gDebug;
XPCOMUtils.defineLazyGetter(this, "log", () => {
let scope = {};
Cu.import("resource://gre/modules/Console.jsm", scope);
- try {
- gDebug = Services.prefs.getBoolPref(kPrefCustomizationDebug);
- } catch (ex) {}
+ gDebug = Services.prefs.getBoolPref(kPrefCustomizationDebug, false);
let consoleOptions = {
maxLogLevel: gDebug ? "all" : "log",
prefix: "CustomizeMode",
@@ -1503,10 +1501,7 @@ CustomizeMode.prototype = {
if (!AppConstants.CAN_DRAW_IN_TITLEBAR) {
return;
}
- let drawInTitlebar = true;
- try {
- drawInTitlebar = Services.prefs.getBoolPref(kDrawInTitlebarPref);
- } catch (ex) { }
+ let drawInTitlebar = Services.prefs.getBoolPref(kDrawInTitlebarPref, true);
let button = this.document.getElementById("customization-titlebar-visibility-button");
// Drawing in the titlebar means 'hiding' the titlebar:
if (drawInTitlebar) {
diff --git a/application/basilisk/components/customizableui/content/panelUI.inc.xul b/application/basilisk/components/customizableui/content/panelUI.inc.xul
index 8ebd93327..da8077554 100644
--- a/application/basilisk/components/customizableui/content/panelUI.inc.xul
+++ b/application/basilisk/components/customizableui/content/panelUI.inc.xul
@@ -20,27 +20,6 @@
oncommand="gMenuButtonUpdateBadge.onMenuPanelCommand(event);"
wrap="true"
hidden="true"/>
- <hbox id="PanelUI-footer-fxa">
- <hbox id="PanelUI-fxa-status"
- defaultlabel="&fxaSignIn.label;"
- signedinTooltiptext="&syncSettings.label;"
- tooltiptext="&syncSettings.label;"
- errorlabel="&fxaSignInError.label;"
- unverifiedlabel="&fxaUnverified.label;"
- settingslabel="&syncSettings.label;"
- onclick="if (event.which == 1) gFxAccounts.onMenuPanelCommand();">
- <image id="PanelUI-fxa-avatar"/>
- <toolbarbutton id="PanelUI-fxa-label"
- fxabrandname="&syncBrand.fxAccount.label;"/>
- </hbox>
- <toolbarseparator/>
- <toolbarbutton id="PanelUI-fxa-icon"
- oncommand="gSyncUI.doSync();"
- closemenu="none">
- <observes element="sync-status" attribute="syncstatus"/>
- <observes element="sync-status" attribute="tooltiptext"/>
- </toolbarbutton>
- </hbox>
<hbox id="PanelUI-footer-inner">
<toolbarbutton id="PanelUI-customize" label="&appMenuCustomize.label;"
@@ -103,95 +82,6 @@
oncommand="PlacesCommandHook.showPlacesOrganizer('History'); CustomizableUI.hidePanelForNode(this);"/>
</panelview>
- <panelview id="PanelUI-remotetabs" flex="1" class="PanelUI-subView">
- <label value="&appMenuRemoteTabs.label;" class="panel-subview-header"/>
- <vbox class="panel-subview-body">
- <!-- this widget has 3 boxes in the body, but only 1 is ever visible -->
- <!-- When Sync is ready to sync -->
- <vbox id="PanelUI-remotetabs-main" observes="sync-syncnow-state">
- <vbox id="PanelUI-remotetabs-buttons">
- <toolbarbutton id="PanelUI-remotetabs-view-sidebar"
- class="subviewbutton"
- oncommand="BrowserOpenSyncTabs();"
- label="&appMenuRemoteTabs.sidebar.label;"/>
- <toolbarbutton id="PanelUI-remotetabs-syncnow"
- observes="sync-status"
- class="subviewbutton"
- oncommand="gSyncUI.doSync();"
- closemenu="none"/>
- <menuseparator id="PanelUI-remotetabs-separator"/>
- </vbox>
- <deck id="PanelUI-remotetabs-deck">
- <!-- Sync is ready to Sync and the "tabs" engine is enabled -->
- <vbox id="PanelUI-remotetabs-tabspane">
- <vbox id="PanelUI-remotetabs-tabslist"
- notabsforclientlabel="&appMenuRemoteTabs.notabs.label;"
- />
- </vbox>
- <!-- Sync is ready to Sync but the "tabs" engine isn't enabled-->
- <hbox id="PanelUI-remotetabs-tabsdisabledpane" pack="center" flex="1">
- <vbox class="PanelUI-remotetabs-instruction-box">
- <hbox pack="center">
- <image class="fxaSyncIllustration" alt=""/>
- </hbox>
- <label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.tabsnotsyncing.label;</label>
- <hbox pack="center">
- <toolbarbutton class="PanelUI-remotetabs-prefs-button"
- label="&appMenuRemoteTabs.openprefs.label;"
- oncommand="gSyncUI.openSetup(null, 'synced-tabs');"/>
- </hbox>
- </vbox>
- </hbox>
- <!-- Sync is ready to Sync but we are still fetching the tabs to show -->
- <vbox id="PanelUI-remotetabs-fetching">
- <!-- Show intentionally blank panel, see bug 1239845 -->
- </vbox>
- <!-- Sync has only 1 (ie, this) device connected -->
- <hbox id="PanelUI-remotetabs-nodevicespane" pack="center" flex="1">
- <vbox class="PanelUI-remotetabs-instruction-box">
- <hbox pack="center">
- <image class="fxaSyncIllustration" alt=""/>
- </hbox>
- <label class="PanelUI-remotetabs-instruction-title">&appMenuRemoteTabs.noclients.title;</label>
- <label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.noclients.subtitle;</label>
- <!-- The inner HTML for PanelUI-remotetabs-mobile-promo is built at runtime -->
- <label id="PanelUI-remotetabs-mobile-promo" fxAccountsBrand="&syncBrand.fxAccount.label;"/>
- </vbox>
- </hbox>
- </deck>
- </vbox>
- <!-- a box to ensure contained boxes are centered horizonally -->
- <hbox pack="center" flex="1">
- <!-- When Sync is not configured -->
- <vbox id="PanelUI-remotetabs-setupsync"
- flex="1"
- align="center"
- class="PanelUI-remotetabs-instruction-box"
- observes="sync-setup-state">
- <image class="fxaSyncIllustration" alt=""/>
- <label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.notsignedin.label;</label>
- <toolbarbutton class="PanelUI-remotetabs-prefs-button"
- label="&appMenuRemoteTabs.signin.label;"
- oncommand="gSyncUI.openSetup(null, 'synced-tabs');"/>
- </vbox>
- <!-- When Sync needs re-authentication. This uses the exact same messaging
- as "Sync is not configured" but remains a separate box so we get
- the goodness of observing broadcasters to manage the hidden states -->
- <vbox id="PanelUI-remotetabs-reauthsync"
- flex="1"
- align="center"
- class="PanelUI-remotetabs-instruction-box"
- observes="sync-reauth-state">
- <image class="fxaSyncIllustration" alt=""/>
- <label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.notsignedin.label;</label>
- <toolbarbutton class="PanelUI-remotetabs-prefs-button"
- label="&appMenuRemoteTabs.signin.label;"
- oncommand="gSyncUI.openSetup(null, 'synced-tabs');"/>
- </vbox>
- </hbox>
- </vbox>
- </panelview>
-
<panelview id="PanelUI-bookmarks" flex="1" class="PanelUI-subView">
<label value="&bookmarksMenu.label;" class="panel-subview-header"/>
<vbox class="panel-subview-body">
diff --git a/application/basilisk/components/customizableui/moz.build b/application/basilisk/components/customizableui/moz.build
index 034630dc9..5797a03b0 100644
--- a/application/basilisk/components/customizableui/moz.build
+++ b/application/basilisk/components/customizableui/moz.build
@@ -9,7 +9,6 @@ DIRS += [
]
EXTRA_JS_MODULES += [
- 'CustomizableUI.jsm',
'CustomizableWidgets.jsm',
'CustomizeMode.jsm',
'DragPositionManager.jsm',
@@ -17,5 +16,9 @@ EXTRA_JS_MODULES += [
'ScrollbarSampler.jsm',
]
+EXTRA_PP_JS_MODULES += [
+ 'CustomizableUI.jsm',
+]
+
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
diff --git a/application/basilisk/components/distribution.js b/application/basilisk/components/distribution.js
index 589129a5a..c30e4dcfe 100644
--- a/application/basilisk/components/distribution.js
+++ b/application/basilisk/components/distribution.js
@@ -22,10 +22,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
this.DistributionCustomizer = function DistributionCustomizer() {
// For parallel xpcshell testing purposes allow loading the distribution.ini
// file from the profile folder through an hidden pref.
- let loadFromProfile = false;
- try {
- loadFromProfile = Services.prefs.getBoolPref("distribution.testing.loadFromProfile");
- } catch (ex) {}
+ loadFromProfile = Services.prefs.getBoolPref("distribution.testing.loadFromProfile", false);
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
try {
@@ -60,13 +57,7 @@ DistributionCustomizer.prototype = {
},
get _locale() {
- let locale;
- try {
- locale = this._prefs.getCharPref("general.useragent.locale");
- }
- catch (e) {
- locale = "en-US";
- }
+ let locale = this._prefs.getCharPref("general.useragent.locale", "en-US");
this.__defineGetter__("_locale", () => locale);
return this._locale;
},
@@ -291,11 +282,7 @@ DistributionCustomizer.prototype = {
this._ini.getString("Global", "id") + ".bookmarksProcessed";
}
- let bmProcessed = false;
- try {
- bmProcessed = this._prefs.getBoolPref(bmProcessedPref);
- }
- catch (e) {}
+ let bmProcessed = this._prefs.getBoolPref(bmProcessedPref, false);
if (!bmProcessed) {
if (sections["BookmarksMenu"])
diff --git a/application/basilisk/components/feeds/FeedWriter.js b/application/basilisk/components/feeds/FeedWriter.js
index 20f1399b0..ceb2a7e2f 100644
--- a/application/basilisk/components/feeds/FeedWriter.js
+++ b/application/basilisk/components/feeds/FeedWriter.js
@@ -19,12 +19,7 @@ function LOG(str) {
let prefB = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
- let shouldLog = false;
- try {
- shouldLog = prefB.getBoolPref("feeds.log");
- }
- catch (ex) {
- }
+ let shouldLog = prefB.getBoolPref("feeds.log", false);
if (shouldLog)
dump("*** Feeds: " + str + "\n");
diff --git a/application/basilisk/components/feeds/WebContentConverter.js b/application/basilisk/components/feeds/WebContentConverter.js
index 2cb5cd145..159eca7c2 100644
--- a/application/basilisk/components/feeds/WebContentConverter.js
+++ b/application/basilisk/components/feeds/WebContentConverter.js
@@ -187,13 +187,8 @@ const Utils = {
// check if it is in the black list
let pb = Services.prefs;
- let allowed;
- try {
- allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "." + aProtocol);
- }
- catch (e) {
- allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "-default");
- }
+ let allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "." + aProtocol,
+ pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "-default"));
if (!allowed) {
throw this.getSecurityError(
`Not allowed to register a protocol handler for ${aProtocol}`,
diff --git a/application/basilisk/components/moz.build b/application/basilisk/components/moz.build
index a7685cbfc..a9c29936b 100644
--- a/application/basilisk/components/moz.build
+++ b/application/basilisk/components/moz.build
@@ -6,7 +6,6 @@
DIRS += [
'about',
- 'contextualidentity',
'customizableui',
'dirprovider',
'downloads',
@@ -20,10 +19,12 @@ DIRS += [
'sessionstore',
'shell',
'selfsupport',
- 'syncedtabs',
'translation',
]
+if CONFIG['MOZ_SERVICES_SYNC']:
+ DIRS += ['sync']
+
DIRS += ['build']
XPIDL_SOURCES += [
@@ -36,6 +37,9 @@ XPIDL_MODULE = 'browsercompsbase'
EXTRA_COMPONENTS += [
'BrowserComponents.manifest',
'nsBrowserContentHandler.js',
+]
+
+EXTRA_PP_COMPONENTS += [
'nsBrowserGlue.js',
]
diff --git a/application/basilisk/components/newtab/NewTabPrefsProvider.jsm b/application/basilisk/components/newtab/NewTabPrefsProvider.jsm
index c1d8b4149..ad0d1e581 100644
--- a/application/basilisk/components/newtab/NewTabPrefsProvider.jsm
+++ b/application/basilisk/components/newtab/NewTabPrefsProvider.jsm
@@ -21,7 +21,6 @@ const gPrefsMap = new Map([
["browser.newtabpage.remote.mode", "str"],
["browser.newtabpage.remote.version", "str"],
["browser.newtabpage.enabled", "bool"],
- ["browser.newtabpage.enhanced", "bool"],
["browser.newtabpage.introShown", "bool"],
["browser.newtabpage.updateIntroShown", "bool"],
["browser.newtabpage.pinned", "str"],
@@ -34,7 +33,6 @@ const gPrefsMap = new Map([
// prefs that are important for the newtab page
const gNewtabPagePrefs = new Set([
"browser.newtabpage.enabled",
- "browser.newtabpage.enhanced",
"browser.newtabpage.pinned",
"browser.newtabpage.blocked",
"browser.newtabpage.introShown",
diff --git a/application/basilisk/components/nsBrowserContentHandler.js b/application/basilisk/components/nsBrowserContentHandler.js
index 74144fc1b..d65e52594 100644
--- a/application/basilisk/components/nsBrowserContentHandler.js
+++ b/application/basilisk/components/nsBrowserContentHandler.js
@@ -100,20 +100,14 @@ const OVERRIDE_NEW_BUILD_ID = 3;
* OVERRIDE_NONE otherwise.
*/
function needHomepageOverride(prefb) {
- var savedmstone = null;
- try {
- savedmstone = prefb.getCharPref("browser.startup.homepage_override.mstone");
- } catch (e) {}
+ var savedmstone = prefb.getCharPref("browser.startup.homepage_override.mstone", "");
if (savedmstone == "ignore")
return OVERRIDE_NONE;
var mstone = Services.appinfo.platformVersion;
- var savedBuildID = null;
- try {
- savedBuildID = prefb.getCharPref("browser.startup.homepage_override.buildID");
- } catch (e) {}
+ var savedBuildID = prefb.getCharPref("browser.startup.homepage_override.buildID", "");
var buildID = Services.appinfo.platformBuildID;
@@ -489,10 +483,7 @@ nsBrowserContentHandler.prototype = {
// URL if we do end up showing an overridePage. This makes it possible
// to have the overridePage's content vary depending on the version we're
// upgrading from.
- let old_mstone = "unknown";
- try {
- old_mstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone");
- } catch (ex) {}
+ let old_mstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone", "unknown");
override = needHomepageOverride(prefb);
if (override != OVERRIDE_NONE) {
switch (override) {
diff --git a/application/basilisk/components/nsBrowserGlue.js b/application/basilisk/components/nsBrowserGlue.js
index d77e97f87..d29009b13 100644
--- a/application/basilisk/components/nsBrowserGlue.js
+++ b/application/basilisk/components/nsBrowserGlue.js
@@ -32,7 +32,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "AlertsService", "@mozilla.org/alerts-s
["ContentPrefServiceParent", "resource://gre/modules/ContentPrefServiceParent.jsm"],
["ContentSearch", "resource:///modules/ContentSearch.jsm"],
["DateTimePickerHelper", "resource://gre/modules/DateTimePickerHelper.jsm"],
- ["DirectoryLinksProvider", "resource:///modules/DirectoryLinksProvider.jsm"],
["Feeds", "resource:///modules/Feeds.jsm"],
["FileUtils", "resource://gre/modules/FileUtils.jsm"],
["FormValidationHandler", "resource:///modules/FormValidationHandler.jsm"],
@@ -143,6 +142,7 @@ BrowserGlue.prototype = {
Services.prefs.savePrefFile(null);
},
+#ifdef MOZ_SERVICES_SYNC
_setSyncAutoconnectDelay: function BG__setSyncAutoconnectDelay() {
// Assume that a non-zero value for services.sync.autoconnectDelay should override
if (Services.prefs.prefHasUserValue("services.sync.autoconnectDelay")) {
@@ -164,6 +164,7 @@ BrowserGlue.prototype = {
Cu.import("resource://services-sync/main.js");
Weave.Service.scheduler.delayedAutoConnect(delay);
},
+#endif
// nsIObserver implementation
observe: function BG_observe(subject, topic, data) {
@@ -210,18 +211,14 @@ BrowserGlue.prototype = {
this._setPrefToSaveSession();
}
break;
+#ifdef MOZ_SERVICES_SYNC
case "weave:service:ready":
this._setSyncAutoconnectDelay();
break;
- case "fxaccounts:onverified":
- this._showSyncStartedDoorhanger();
- break;
- case "fxaccounts:device_disconnected":
- this._onDeviceDisconnected();
- break;
- case "weave:engine:clients:display-uris":
- this._onDisplaySyncURIs(subject);
- break;
+ case "weave:engine:clients:display-uri":
+ this._onDisplaySyncURI(subject);
+ break;
+#endif
case "session-save":
this._setPrefToSaveSession(true);
subject.QueryInterface(Ci.nsISupportsPRBool);
@@ -428,10 +425,10 @@ BrowserGlue.prototype = {
os.addObserver(this, "browser-lastwindow-close-requested", false);
os.addObserver(this, "browser-lastwindow-close-granted", false);
}
+#ifdef MOZ_SERVICES_SYNC
os.addObserver(this, "weave:service:ready", false);
- os.addObserver(this, "fxaccounts:onverified", false);
- os.addObserver(this, "fxaccounts:device_disconnected", false);
- os.addObserver(this, "weave:engine:clients:display-uris", false);
+ os.addObserver(this, "weave:engine:clients:display-uri", false);
+#endif
os.addObserver(this, "session-save", false);
os.addObserver(this, "places-init-complete", false);
this._isPlacesInitObserver = true;
@@ -479,10 +476,10 @@ BrowserGlue.prototype = {
os.removeObserver(this, "browser-lastwindow-close-requested");
os.removeObserver(this, "browser-lastwindow-close-granted");
}
+#ifdef MOZ_SERVICES_SYNC
os.removeObserver(this, "weave:service:ready");
- os.removeObserver(this, "fxaccounts:onverified");
- os.removeObserver(this, "fxaccounts:device_disconnected");
- os.removeObserver(this, "weave:engine:clients:display-uris");
+ os.removeObserver(this, "weave:engine:clients:display-uri");
+#endif
os.removeObserver(this, "session-save");
if (this._bookmarksBackupIdleTime) {
this._idleService.removeIdleObserver(this, this._bookmarksBackupIdleTime);
@@ -657,9 +654,7 @@ BrowserGlue.prototype = {
webrtcUI.init();
AboutHome.init();
- DirectoryLinksProvider.init();
NewTabUtils.init();
- NewTabUtils.links.addProvider(DirectoryLinksProvider);
AboutNewTab.init();
NewTabMessages.init();
@@ -963,10 +958,7 @@ BrowserGlue.prototype = {
// Offer to reset a user's profile if it hasn't been used for 60 days.
const OFFER_PROFILE_RESET_INTERVAL_MS = 60 * 24 * 60 * 60 * 1000;
let lastUse = Services.appinfo.replacedLockTime;
- let disableResetPrompt = false;
- try {
- disableResetPrompt = Services.prefs.getBoolPref("browser.disableResetPrompt");
- } catch (e) {}
+ let disableResetPrompt = Services.prefs.getBoolPref("browser.disableResetPrompt", false);
if (!disableResetPrompt && lastUse &&
Date.now() - lastUse >= OFFER_PROFILE_RESET_INTERVAL_MS) {
@@ -1507,10 +1499,7 @@ BrowserGlue.prototype = {
} catch (ex) {}
// Support legacy bookmarks.html format for apps that depend on that format.
- let autoExportHTML = false;
- try {
- autoExportHTML = Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML");
- } catch (ex) {} // Do not export.
+ let autoExportHTML = Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML", false); // Do not export.
if (autoExportHTML) {
// Sqlite.jsm and Places shutdown happen at profile-before-change, thus,
// to be on the safe side, this should run earlier.
@@ -1580,10 +1569,7 @@ BrowserGlue.prototype = {
// An import operation is about to run.
// Don't try to recreate smart bookmarks if autoExportHTML is true or
// smart bookmarks are disabled.
- let smartBookmarksVersion = 0;
- try {
- smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion");
- } catch (ex) {}
+ let smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion", 0);
if (!autoExportHTML && smartBookmarksVersion != -1)
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
@@ -1934,10 +1920,7 @@ BrowserGlue.prototype = {
// Refactor urlbar suggestion preferences to make it extendable and
// allow new suggestion types (e.g: search suggestions).
let types = ["history", "bookmark", "openpage"];
- let defaultBehavior = 0;
- try {
- defaultBehavior = Services.prefs.getIntPref("browser.urlbar.default.behavior");
- } catch (ex) {}
+ let defaultBehavior = Services.prefs.getIntPref("browser.urlbar.default.behavior", 0);
try {
let autocompleteEnabled = Services.prefs.getBoolPref("browser.urlbar.autocomplete.enabled");
if (!autocompleteEnabled) {
@@ -1990,12 +1973,8 @@ BrowserGlue.prototype = {
if (currentUIVersion < 30) {
// Convert old devedition theme pref to lightweight theme storage
- let lightweightThemeSelected = false;
- let selectedThemeID = null;
- try {
- lightweightThemeSelected = Services.prefs.prefHasUserValue("lightweightThemes.selectedThemeID");
- selectedThemeID = Services.prefs.getCharPref("lightweightThemes.selectedThemeID");
- } catch (e) {}
+ let lightweightThemeSelected = Services.prefs.prefHasUserValue("lightweightThemes.selectedThemeID", false);
+ let selectedThemeID = Services.prefs.getCharPref("lightweightThemes.selectedThemeID", "");
let defaultThemeSelected = false;
try {
@@ -2145,10 +2124,7 @@ BrowserGlue.prototype = {
const MAX_RESULTS = 10;
// Get current smart bookmarks version. If not set, create them.
- let smartBookmarksCurrentVersion = 0;
- try {
- smartBookmarksCurrentVersion = Services.prefs.getIntPref(SMART_BOOKMARKS_PREF);
- } catch (ex) {}
+ let smartBookmarksCurrentVersion = Services.prefs.getIntPref(SMART_BOOKMARKS_PREF, 0);
// If version is current, or smart bookmarks are disabled, bail out.
if (smartBookmarksCurrentVersion == -1 ||
@@ -2274,90 +2250,29 @@ BrowserGlue.prototype = {
chromeWindow.openPreferences(...args);
},
+#ifdef MOZ_SERVICES_SYNC
/**
- * Called as an observer when Sync's "display URIs" notification is fired.
+ * Called as an observer when Sync's "display URI" notification is fired.
*
- * We open the received URIs in background tabs.
+ * We open the received URI in a background tab.
+ *
+ * Eventually, this will likely be replaced by a more robust tab syncing
+ * feature. This functionality is considered somewhat evil by UX because it
+ * opens a new tab automatically without any prompting. However, it is a
+ * lesser evil than sending a tab to a specific device (from e.g. Fennec)
+ * and having nothing happen on the receiving end.
*/
- _onDisplaySyncURIs: function _onDisplaySyncURIs(data) {
+ _onDisplaySyncURI: function _onDisplaySyncURI(data) {
try {
- // The payload is wrapped weirdly because of how Sync does notifications.
- const URIs = data.wrappedJSObject.object;
-
- const findWindow = () => RecentWindow.getMostRecentBrowserWindow({private: false});
-
- // win can be null, but it's ok, we'll assign it later in openTab()
- let win = findWindow();
+ let tabbrowser = RecentWindow.getMostRecentBrowserWindow({private: false}).gBrowser;
- const openTab = URI => {
- let tab;
- if (!win) {
- Services.appShell.hiddenDOMWindow.open(URI.uri);
- win = findWindow();
- tab = win.gBrowser.tabs[0];
- } else {
- tab = win.gBrowser.addTab(URI.uri);
- }
- tab.setAttribute("attention", true);
- return tab;
- };
-
- const firstTab = openTab(URIs[0]);
- URIs.slice(1).forEach(URI => openTab(URI));
-
- let title, body;
- const deviceName = Weave.Service.clientsEngine.getClientName(URIs[0].clientId);
- const bundle = Services.strings.createBundle("chrome://browser/locale/accounts.properties");
- if (URIs.length == 1) {
- // Due to bug 1305895, tabs from iOS may not have device information, so
- // we have separate strings to handle those cases. (See Also
- // unnamedTabsArrivingNotificationNoDevice.body below)
- if (deviceName) {
- title = bundle.formatStringFromName("tabArrivingNotificationWithDevice.title", [deviceName], 1);
- } else {
- title = bundle.GetStringFromName("tabArrivingNotification.title");
- }
- // Use the page URL as the body. We strip the fragment and query to
- // reduce size, and also format it the same way that the url bar would.
- body = URIs[0].uri.replace(/[?#].*$/, "");
- if (win.gURLBar) {
- body = win.gURLBar.trimValue(body);
- }
- } else {
- title = bundle.GetStringFromName("tabsArrivingNotification.title");
- const allSameDevice = URIs.every(URI => URI.clientId == URIs[0].clientId);
- const unknownDevice = allSameDevice && !deviceName;
- let tabArrivingBody;
- if (unknownDevice) {
- tabArrivingBody = "unnamedTabsArrivingNotificationNoDevice.body";
- } else if (allSameDevice) {
- tabArrivingBody = "unnamedTabsArrivingNotification2.body";
- } else {
- tabArrivingBody = "unnamedTabsArrivingNotificationMultiple2.body"
- }
-
- body = bundle.GetStringFromName(tabArrivingBody);
- body = PluralForm.get(URIs.length, body);
- body = body.replace("#1", URIs.length);
- body = body.replace("#2", deviceName);
- }
-
- const clickCallback = (subject, topic, data) => {
- if (topic == "alertclickcallback") {
- win.gBrowser.selectedTab = firstTab;
- }
- }
-
- // Specify an icon because on Windows no icon is shown at the moment
- let imageURL;
- if (AppConstants.platform == "win") {
- imageURL = "chrome://branding/content/icon64.png";
- }
- AlertsService.showAlertNotification(imageURL, title, body, true, null, clickCallback);
+ // The payload is wrapped weirdly because of how Sync does notifications.
+ tabbrowser.addTab(data.wrappedJSObject.object.uri);
} catch (ex) {
- Cu.reportError("Error displaying tab(s) received by Sync: " + ex);
+ Cu.reportError("Error displaying tab received by Sync: " + ex);
}
},
+#endif
_onDeviceDisconnected() {
let bundle = Services.strings.createBundle("chrome://browser/locale/accounts.properties");
diff --git a/application/basilisk/components/places/PlacesUIUtils.jsm b/application/basilisk/components/places/PlacesUIUtils.jsm
index 17fa276aa..035fc12c2 100644
--- a/application/basilisk/components/places/PlacesUIUtils.jsm
+++ b/application/basilisk/components/places/PlacesUIUtils.jsm
@@ -1418,9 +1418,9 @@ this.PlacesUIUtils = {
},
shouldShowTabsFromOtherComputersMenuitem: function() {
- let weaveOK = Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED &&
- Weave.Svc.Prefs.get("firstSync", "") != "notReady";
- return weaveOK;
+#ifdef MOZ_SERVICES_SYNC
+ // Weave code to enable menu item
+#endif
},
/**
diff --git a/application/basilisk/components/places/moz.build b/application/basilisk/components/places/moz.build
index 9e5a2c074..ea6d43538 100644
--- a/application/basilisk/components/places/moz.build
+++ b/application/basilisk/components/places/moz.build
@@ -6,6 +6,6 @@
JAR_MANIFESTS += ['jar.mn']
-EXTRA_JS_MODULES += [
+EXTRA_PP_JS_MODULES += [
'PlacesUIUtils.jsm',
]
diff --git a/application/basilisk/components/preferences/containers.js b/application/basilisk/components/preferences/containers.js
deleted file mode 100644
index 6ca5853f7..000000000
--- a/application/basilisk/components/preferences/containers.js
+++ /dev/null
@@ -1,176 +0,0 @@
-/* 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/. */
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/ContextualIdentityService.jsm");
-
-const containersBundle = Services.strings.createBundle("chrome://browser/locale/preferences/containers.properties");
-
-const HTMLNS = "http://www.w3.org/1999/xhtml";
-
-let gContainersManager = {
- icons: [
- "fingerprint",
- "briefcase",
- "dollar",
- "cart",
- "circle"
- ],
-
- colors: [
- "blue",
- "turquoise",
- "green",
- "yellow",
- "orange",
- "red",
- "pink",
- "purple"
- ],
-
- onLoad() {
- let params = window.arguments[0] || {};
- this.init(params);
- },
-
- init(aParams) {
- this.userContextId = aParams.userContextId || null;
- this.identity = aParams.identity;
-
- if (aParams.windowTitle) {
- document.title = aParams.windowTitle;
- }
-
- const iconWrapper = document.getElementById("iconWrapper");
- iconWrapper.appendChild(this.createIconButtons());
-
- const colorWrapper = document.getElementById("colorWrapper");
- colorWrapper.appendChild(this.createColorSwatches());
-
- if (this.identity.name) {
- const name = document.getElementById("name");
- name.value = this.identity.name;
- this.checkForm();
- }
-
- this.setLabelsMinWidth();
-
- // This is to prevent layout jank caused by the svgs and outlines rendering at different times
- document.getElementById("containers-content").removeAttribute("hidden");
- },
-
- setLabelsMinWidth() {
- const labelMinWidth = containersBundle.GetStringFromName("containers.labelMinWidth");
- const labels = [
- document.getElementById("nameLabel"),
- document.getElementById("iconLabel"),
- document.getElementById("colorLabel")
- ];
- for (let label of labels) {
- label.style.minWidth = labelMinWidth;
- }
- },
-
- uninit() {
- },
-
- // Check if name string as to if the form can be submitted
- checkForm() {
- const name = document.getElementById("name");
- let btnApplyChanges = document.getElementById("btnApplyChanges");
- if (!name.value) {
- btnApplyChanges.setAttribute("disabled", true);
- } else {
- btnApplyChanges.removeAttribute("disabled");
- }
- },
-
- createIconButtons(defaultIcon) {
- let radiogroup = document.createElement("radiogroup");
- radiogroup.setAttribute("id", "icon");
- radiogroup.className = "icon-buttons";
-
- for (let icon of this.icons) {
- let iconSwatch = document.createElement("radio");
- iconSwatch.id = "iconbutton-" + icon;
- iconSwatch.name = "icon";
- iconSwatch.type = "radio";
- iconSwatch.value = icon;
-
- if (this.identity.icon && this.identity.icon == icon) {
- iconSwatch.setAttribute("selected", true);
- }
-
- iconSwatch.setAttribute("label",
- containersBundle.GetStringFromName(`containers.${icon}.label`));
- let iconElement = document.createElement("hbox");
- iconElement.className = 'userContext-icon';
- iconElement.setAttribute("data-identity-icon", icon);
-
- iconSwatch.appendChild(iconElement);
- radiogroup.appendChild(iconSwatch);
- }
-
- return radiogroup;
- },
-
- createColorSwatches(defaultColor) {
- let radiogroup = document.createElement("radiogroup");
- radiogroup.setAttribute("id", "color");
-
- for (let color of this.colors) {
- let colorSwatch = document.createElement("radio");
- colorSwatch.id = "colorswatch-" + color;
- colorSwatch.name = "color";
- colorSwatch.type = "radio";
- colorSwatch.value = color;
-
- if (this.identity.color && this.identity.color == color) {
- colorSwatch.setAttribute("selected", true);
- }
-
- colorSwatch.setAttribute("label",
- containersBundle.GetStringFromName(`containers.${color}.label`));
- let iconElement = document.createElement("hbox");
- iconElement.className = 'userContext-icon';
- iconElement.setAttribute("data-identity-icon", "circle");
- iconElement.setAttribute("data-identity-color", color);
-
- colorSwatch.appendChild(iconElement);
- radiogroup.appendChild(colorSwatch);
- }
- return radiogroup;
- },
-
- onApplyChanges() {
- let icon = document.getElementById("icon").value;
- let color = document.getElementById("color").value;
- let name = document.getElementById("name").value;
-
- if (this.icons.indexOf(icon) == -1) {
- throw "Internal error. The icon value doesn't match.";
- }
-
- if (this.colors.indexOf(color) == -1) {
- throw "Internal error. The color value doesn't match.";
- }
-
- if (this.userContextId) {
- ContextualIdentityService.update(this.userContextId,
- name,
- icon,
- color);
- } else {
- ContextualIdentityService.create(name,
- icon,
- color);
- }
- window.parent.location.reload()
- },
-
- onWindowKeyPress(aEvent) {
- if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE)
- window.close();
- }
-}
diff --git a/application/basilisk/components/preferences/containers.xul b/application/basilisk/components/preferences/containers.xul
deleted file mode 100644
index 62a775fe4..000000000
--- a/application/basilisk/components/preferences/containers.xul
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- 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/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/preferences/containers.css" type="text/css"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/containers.dtd" >
-
-<window id="ContainersDialog" class="windowDialog"
- windowtype="Browser:Permissions"
- title="&window.title;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- style="width: &window.width;;"
- onload="gContainersManager.onLoad();"
- onunload="gContainersManager.uninit();"
- persist="screenX screenY width height"
- onkeypress="gContainersManager.onWindowKeyPress(event);">
-
- <script src="chrome://global/content/treeUtils.js"/>
- <script src="chrome://browser/content/preferences/containers.js"/>
-
- <stringbundle id="bundlePreferences"
- src="chrome://browser/locale/preferences/preferences.properties"/>
-
- <keyset>
- <key key="&windowClose.key;" modifiers="accel" oncommand="window.close();"/>
- </keyset>
-
- <vbox class="contentPane largeDialogContainer" flex="1" hidden="true" id="containers-content">
- <description id="permissionsText" control="url"/>
- <separator class="thin"/>
- <hbox align="start">
- <label id="nameLabel" control="url" value="&name.label;" accesskey="&name.accesskey;"/>
- <textbox id="name" flex="1" onkeyup="gContainersManager.checkForm();" />
- </hbox>
- <hbox align="center" id="iconWrapper">
- <label id="iconLabel" control="url" value="&icon.label;" accesskey="&icon.accesskey;"/>
- </hbox>
- <hbox align="center" id="colorWrapper">
- <label id="colorLabel" control="url" value="&color.label;" accesskey="&color.accesskey;"/>
- </hbox>
- </vbox>
- <vbox>
- <hbox class="actionButtons" align="right" flex="1">
- <button id="btnApplyChanges" disabled="true" oncommand="gContainersManager.onApplyChanges();" icon="save"
- label="&button.ok.label;" accesskey="&button.ok.accesskey;"/>
- </hbox>
- </vbox>
-</window>
diff --git a/application/basilisk/components/preferences/cookies.js b/application/basilisk/components/preferences/cookies.js
index c420855f8..4ede5b6e6 100644
--- a/application/basilisk/components/preferences/cookies.js
+++ b/application/basilisk/components/preferences/cookies.js
@@ -7,12 +7,8 @@ const nsICookie = Components.interfaces.nsICookie;
Components.utils.import("resource://gre/modules/AppConstants.jsm");
Components.utils.import("resource://gre/modules/PluralForm.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm")
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
- "resource://gre/modules/ContextualIdentityService.jsm");
-
var gCookiesWindow = {
_cm : Components.classes["@mozilla.org/cookiemanager;1"]
.getService(Components.interfaces.nsICookieManager),
@@ -38,10 +34,6 @@ var gCookiesWindow = {
this._populateList(true);
document.getElementById("filter").focus();
-
- if (!Services.prefs.getBoolPref("privacy.userContext.enabled")) {
- document.getElementById("userContextRow").hidden = true;
- }
},
uninit: function () {
@@ -82,24 +74,11 @@ var gCookiesWindow = {
aCookieB.originAttributes);
},
- _isPrivateCookie: function (aCookie) {
- let { userContextId } = aCookie.originAttributes;
- if (!userContextId) {
- // Default identity is public.
- return false;
- }
- return !ContextualIdentityService.getIdentityFromId(userContextId).public;
- },
-
observe: function (aCookie, aTopic, aData) {
if (aTopic != "cookie-changed")
return;
if (aCookie instanceof Components.interfaces.nsICookie) {
- if (this._isPrivateCookie(aCookie)) {
- return;
- }
-
var strippedHost = this._makeStrippedHost(aCookie.host);
if (aData == "changed")
this._handleCookieChanged(aCookie, strippedHost);
@@ -498,9 +477,6 @@ var gCookiesWindow = {
while (e.hasMoreElements()) {
var cookie = e.getNext();
if (cookie && cookie instanceof Components.interfaces.nsICookie) {
- if (this._isPrivateCookie(cookie)) {
- continue;
- }
var strippedHost = this._makeStrippedHost(cookie.host);
this._addCookie(strippedHost, cookie, hostCount);
@@ -524,17 +500,9 @@ var gCookiesWindow = {
return this._bundle.getString("expireAtEndOfSession");
},
- _getUserContextString: function(aUserContextId) {
- if (parseInt(aUserContextId) == 0) {
- return this._bundle.getString("defaultUserContextLabel");
- }
-
- return ContextualIdentityService.getUserContextLabel(aUserContextId);
- },
-
_updateCookieData: function (aItem) {
var seln = this._view.selection;
- var ids = ["name", "value", "host", "path", "isSecure", "expires", "userContext"];
+ var ids = ["name", "value", "host", "path", "isSecure", "expires"];
var properties;
if (aItem && !aItem.container && seln.count > 0) {
@@ -543,8 +511,7 @@ var gCookiesWindow = {
isDomain: aItem.isDomain ? this._bundle.getString("domainColon")
: this._bundle.getString("hostColon"),
isSecure: aItem.isSecure ? this._bundle.getString("forSecureOnly")
- : this._bundle.getString("forAnyConnection"),
- userContext: this._getUserContextString(aItem.originAttributes.userContextId) };
+ : this._bundle.getString("forAnyConnection") };
for (let id of ids) {
document.getElementById(id).disabled = false;
}
@@ -553,7 +520,7 @@ var gCookiesWindow = {
var noneSelected = this._bundle.getString("noCookieSelected");
properties = { name: noneSelected, value: noneSelected, host: noneSelected,
path: noneSelected, expires: noneSelected,
- isSecure: noneSelected, userContext: noneSelected };
+ isSecure: noneSelected };
for (let id of ids) {
document.getElementById(id).disabled = true;
}
diff --git a/application/basilisk/components/preferences/cookies.xul b/application/basilisk/components/preferences/cookies.xul
index bd60d9346..d5fefdef7 100644
--- a/application/basilisk/components/preferences/cookies.xul
+++ b/application/basilisk/components/preferences/cookies.xul
@@ -85,10 +85,6 @@
<hbox pack="end"><label id="expiresLabel" control="expires" value="&props.expires.label;"/></hbox>
<textbox id="expires" readonly="true" class="plain"/>
</row>
- <row align="center" id="userContextRow">
- <hbox pack="end"><label id="userContextLabel" control="userContext" value="&props.container.label;"/></hbox>
- <textbox id="userContext" readonly="true" class="plain"/>
- </row>
</rows>
</grid>
</hbox>
diff --git a/application/basilisk/components/preferences/handlers.css b/application/basilisk/components/preferences/handlers.css
index 6af75a08b..d5f100831 100644
--- a/application/basilisk/components/preferences/handlers.css
+++ b/application/basilisk/components/preferences/handlers.css
@@ -10,10 +10,6 @@
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler-selected");
}
-#containersView > richlistitem {
- -moz-binding: url("chrome://browser/content/preferences/handlers.xml#container");
-}
-
/**
* Make the icons appear.
* Note: we display the icon box for every item whether or not it has an icon
diff --git a/application/basilisk/components/preferences/handlers.xml b/application/basilisk/components/preferences/handlers.xml
index 0c629d759..ad07a493c 100644
--- a/application/basilisk/components/preferences/handlers.xml
+++ b/application/basilisk/components/preferences/handlers.xml
@@ -69,29 +69,6 @@
</binding>
- <binding id="container">
- <content>
- <xul:hbox flex="1" equalsize="always">
- <xul:hbox flex="1" align="center">
- <xul:hbox xbl:inherits="data-identity-icon=containerIcon,data-identity-color=containerColor" height="24" width="24" class="userContext-icon"/>
- <xul:label flex="1" crop="end" xbl:inherits="value=containerName"/>
- </xul:hbox>
- <xul:hbox flex="1" align="right">
- <xul:button anonid="preferencesButton"
- xbl:inherits="value=userContextId"
- onclick="gContainersPane.onPeferenceClick(event.originalTarget)">
- Preferences
- </xul:button>
- <xul:button anonid="removeButton"
- xbl:inherits="value=userContextId"
- onclick="gContainersPane.onRemoveClick(event.originalTarget)">
- Remove
- </xul:button>
- </xul:hbox>
- </xul:hbox>
- </content>
- </binding>
-
<binding id="offlineapp"
extends="chrome://global/content/bindings/listbox.xml#listitem">
<content>
diff --git a/application/basilisk/components/preferences/in-content/containers.js b/application/basilisk/components/preferences/in-content/containers.js
deleted file mode 100644
index 758e45fff..000000000
--- a/application/basilisk/components/preferences/in-content/containers.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/* 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/. */
-
-Components.utils.import("resource://gre/modules/AppConstants.jsm");
-Components.utils.import("resource://gre/modules/ContextualIdentityService.jsm");
-
-const containersBundle = Services.strings.createBundle("chrome://browser/locale/preferences/containers.properties");
-
-const defaultContainerIcon = "fingerprint";
-const defaultContainerColor = "blue";
-
-let gContainersPane = {
-
- init() {
- this._list = document.getElementById("containersView");
-
- document.getElementById("backContainersLink").addEventListener("click", function () {
- gotoPref("privacy");
- });
-
- this._rebuildView();
- },
-
- _rebuildView() {
- const containers = ContextualIdentityService.getIdentities();
- while (this._list.firstChild) {
- this._list.firstChild.remove();
- }
- for (let container of containers) {
- let item = document.createElement("richlistitem");
- item.setAttribute("containerName", ContextualIdentityService.getUserContextLabel(container.userContextId));
- item.setAttribute("containerIcon", container.icon);
- item.setAttribute("containerColor", container.color);
- item.setAttribute("userContextId", container.userContextId);
-
- this._list.appendChild(item);
- }
- },
-
- onRemoveClick(button) {
- let userContextId = button.getAttribute("value");
- ContextualIdentityService.remove(userContextId);
- this._rebuildView();
- },
- onPeferenceClick(button) {
- this.openPreferenceDialog(button.getAttribute("value"));
- },
-
- onAddButtonClick(button) {
- this.openPreferenceDialog(null);
- },
-
- openPreferenceDialog(userContextId) {
- let identity = {
- name: "",
- icon: defaultContainerIcon,
- color: defaultContainerColor
- };
- let title;
- if (userContextId) {
- identity = ContextualIdentityService.getIdentityFromId(userContextId);
- // This is required to get the translation string from defaults
- identity.name = ContextualIdentityService.getUserContextLabel(identity.userContextId);
- title = containersBundle.formatStringFromName("containers.updateContainerTitle", [identity.name], 1);
- }
-
- const params = { userContextId, identity, windowTitle: title };
- gSubDialog.open("chrome://browser/content/preferences/containers.xul",
- null, params);
- }
-
-};
diff --git a/application/basilisk/components/preferences/in-content/containers.xul b/application/basilisk/components/preferences/in-content/containers.xul
deleted file mode 100644
index e83bac1c3..000000000
--- a/application/basilisk/components/preferences/in-content/containers.xul
+++ /dev/null
@@ -1,54 +0,0 @@
-# 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/.
-
-<!-- Containers panel -->
-
-<script type="application/javascript"
- src="chrome://browser/content/preferences/in-content/containers.js"/>
-
-<preferences id="containerPreferences" hidden="true" data-category="paneContainer">
- <!-- Containers -->
- <preference id="privacy.userContext.enabled"
- name="privacy.userContext.enabled"
- type="bool"/>
-
-</preferences>
-
-<hbox hidden="true"
- class="container-header-links"
- data-category="paneContainers">
- <label class="text-link" id="backContainersLink" value="&backLink.label;" />
-</hbox>
-
-<hbox id="header-containers"
- class="header"
- hidden="true"
- data-category="paneContainers">
- <label class="header-name" flex="1">&paneContainers.title;</label>
- <button class="help-button"
- aria-label="&helpButton.label;"/>
-</hbox>
-
-<!-- Containers -->
-<groupbox id="browserContainersGroup" data-category="paneContainers" hidden="true">
- <vbox id="browserContainersbox">
-
- <richlistbox id="containersView" orient="vertical" persist="lastSelectedType"
- flex="1">
- <listheader equalsize="always">
- <treecol id="typeColumn" label="&label.label;" value="type"
- persist="sortDirection"
- flex="1" sortDirection="ascending"/>
- <treecol id="actionColumn" value="action"
- persist="sortDirection"
- flex="1"/>
- </listheader>
- </richlistbox>
- </vbox>
- <vbox>
- <hbox flex="1">
- <button onclick="gContainersPane.onAddButtonClick();" accesskey="&addButton.accesskey;" label="&addButton.label;"/>
- </hbox>
- </vbox>
-</groupbox>
diff --git a/application/basilisk/components/preferences/in-content/jar.mn b/application/basilisk/components/preferences/in-content/jar.mn
index e61a88856..21f5ccf38 100644
--- a/application/basilisk/components/preferences/in-content/jar.mn
+++ b/application/basilisk/components/preferences/in-content/jar.mn
@@ -3,16 +3,17 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
browser.jar:
- content/browser/preferences/in-content/preferences.js
+* content/browser/preferences/in-content/preferences.js
* content/browser/preferences/in-content/preferences.xul
content/browser/preferences/in-content/subdialogs.js
content/browser/preferences/in-content/main.js
* content/browser/preferences/in-content/privacy.js
- content/browser/preferences/in-content/containers.js
content/browser/preferences/in-content/advanced.js
content/browser/preferences/in-content/applications.js
* content/browser/preferences/in-content/content.js
+#ifdef MOZ_SERVICES_SYNC
content/browser/preferences/in-content/sync.js
+#endif
* content/browser/preferences/in-content/security.js
content/browser/preferences/in-content/search.js
diff --git a/application/basilisk/components/preferences/in-content/preferences.js b/application/basilisk/components/preferences/in-content/preferences.js
index e18ab4b04..69cb180d5 100644
--- a/application/basilisk/components/preferences/in-content/preferences.js
+++ b/application/basilisk/components/preferences/in-content/preferences.js
@@ -61,11 +61,12 @@ function init_all() {
register_module("paneGeneral", gMainPane);
register_module("paneSearch", gSearchPane);
register_module("panePrivacy", gPrivacyPane);
- register_module("paneContainers", gContainersPane);
register_module("paneAdvanced", gAdvancedPane);
register_module("paneApplications", gApplicationsPane);
register_module("paneContent", gContentPane);
+#ifdef MOZ_SERVICES_SYNC
register_module("paneSync", gSyncPane);
+#endif
register_module("paneSecurity", gSecurityPane);
let categories = document.getElementById("categories");
diff --git a/application/basilisk/components/preferences/in-content/preferences.xul b/application/basilisk/components/preferences/in-content/preferences.xul
index 7ec7ef119..61639aa19 100644
--- a/application/basilisk/components/preferences/in-content/preferences.xul
+++ b/application/basilisk/components/preferences/in-content/preferences.xul
@@ -13,7 +13,6 @@
href="chrome://browser/content/preferences/handlers.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/applications.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/in-content/search.css"?>
-<?xml-stylesheet href="chrome://browser/skin/preferences/in-content/containers.css"?>
<!DOCTYPE page [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
@@ -23,12 +22,12 @@
<!ENTITY % privacyDTD SYSTEM "chrome://browser/locale/preferences/privacy.dtd">
<!ENTITY % tabsDTD SYSTEM "chrome://browser/locale/preferences/tabs.dtd">
<!ENTITY % searchDTD SYSTEM "chrome://browser/locale/preferences/search.dtd">
+#ifdef MOZ_SERVICES_SYNC
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
<!ENTITY % syncDTD SYSTEM "chrome://browser/locale/preferences/sync.dtd">
+#endif
<!ENTITY % securityDTD SYSTEM
"chrome://browser/locale/preferences/security.dtd">
-<!ENTITY % containersDTD SYSTEM
- "chrome://browser/locale/preferences/containers.dtd">
<!ENTITY % sanitizeDTD SYSTEM "chrome://browser/locale/sanitize.dtd">
<!ENTITY % mainDTD SYSTEM "chrome://browser/locale/preferences/main.dtd">
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
@@ -43,10 +42,11 @@
%privacyDTD;
%tabsDTD;
%searchDTD;
+#ifdef MOZ_SERVICES_SYNC
%syncBrandDTD;
%syncDTD;
+#endif
%securityDTD;
-%containersDTD;
%sanitizeDTD;
%mainDTD;
%aboutHomeDTD;
@@ -134,12 +134,6 @@
<label class="category-name" flex="1">&panePrivacy.title;</label>
</richlistitem>
- <richlistitem id="category-containers"
- class="category"
- value="paneContainers"
- helpTopic="prefs-containers"
- hidden="true"/>
-
<richlistitem id="category-security"
class="category"
value="paneSecurity"
@@ -150,6 +144,7 @@
<label class="category-name" flex="1">&paneSecurity.title;</label>
</richlistitem>
+#ifdef MOZ_SERVICES_SYNC
<richlistitem id="category-sync"
class="category"
value="paneSync"
@@ -159,6 +154,7 @@
<image class="category-icon"/>
<label class="category-name" flex="1">&paneSync.title;</label>
</richlistitem>
+#endif
<richlistitem id="category-advanced"
class="category"
@@ -183,12 +179,13 @@
#include main.xul
#include search.xul
#include privacy.xul
-#include containers.xul
#include advanced.xul
#include applications.xul
#include content.xul
#include security.xul
+#ifdef MOZ_SERVICES_SYNC
#include sync.xul
+#endif
</prefpane>
</vbox>
diff --git a/application/basilisk/components/preferences/in-content/privacy.js b/application/basilisk/components/preferences/in-content/privacy.js
index eab606e36..a976fb4fa 100644
--- a/application/basilisk/components/preferences/in-content/privacy.js
+++ b/application/basilisk/components/preferences/in-content/privacy.js
@@ -5,8 +5,6 @@
Components.utils.import("resource://gre/modules/AppConstants.jsm");
Components.utils.import("resource://gre/modules/PluralForm.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
- "resource://gre/modules/ContextualIdentityService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
@@ -62,59 +60,6 @@ var gPrivacyPane = {
},
/**
- * Show the Containers UI depending on the privacy.userContext.ui.enabled pref.
- */
- _initBrowserContainers: function () {
- if (!Services.prefs.getBoolPref("privacy.userContext.ui.enabled")) {
- return;
- }
-
- let link = document.getElementById("browserContainersLearnMore");
- link.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "containers";
-
- document.getElementById("browserContainersbox").hidden = false;
-
- document.getElementById("browserContainersCheckbox").checked =
- Services.prefs.getBoolPref("privacy.userContext.enabled");
- },
-
- _checkBrowserContainers: function(event) {
- let checkbox = document.getElementById("browserContainersCheckbox");
- if (checkbox.checked) {
- Services.prefs.setBoolPref("privacy.userContext.enabled", true);
- return;
- }
-
- let count = ContextualIdentityService.countContainerTabs();
- if (count == 0) {
- Services.prefs.setBoolPref("privacy.userContext.enabled", false);
- return;
- }
-
- let bundlePreferences = document.getElementById("bundlePreferences");
-
- let title = bundlePreferences.getString("disableContainersAlertTitle");
- let message = PluralForm.get(count, bundlePreferences.getString("disableContainersMsg"))
- .replace("#S", count)
- let okButton = PluralForm.get(count, bundlePreferences.getString("disableContainersOkButton"))
- .replace("#S", count)
- let cancelButton = bundlePreferences.getString("disableContainersButton2");
-
- let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
- (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1);
-
- let rv = Services.prompt.confirmEx(window, title, message, buttonFlags,
- okButton, cancelButton, null, null, {});
- if (rv == 0) {
- ContextualIdentityService.closeAllContainerTabs();
- Services.prefs.setBoolPref("privacy.userContext.enabled", false);
- return;
- }
-
- checkbox.checked = true;
- },
-
- /**
* Sets up the UI for the number of days of history to keep, and updates the
* label of the "Clear Now..." button.
*/
@@ -136,7 +81,6 @@ var gPrivacyPane = {
this._initTrackingProtectionPBM();
#endif
this._initAutocomplete();
- this._initBrowserContainers();
setEventListener("privacy.sanitize.sanitizeOnShutdown", "change",
gPrivacyPane._updateSanitizeSettingsButton);
@@ -184,10 +128,6 @@ var gPrivacyPane = {
setEventListener("changeBlockListPBM", "command",
gPrivacyPane.showBlockLists);
#endif
- setEventListener("browserContainersCheckbox", "command",
- gPrivacyPane._checkBrowserContainers);
- setEventListener("browserContainersSettings", "command",
- gPrivacyPane.showContainerSettings);
},
#ifdef MOZ_SAFE_BROWSING
@@ -489,13 +429,6 @@ var gPrivacyPane = {
},
#endif
- /**
- * Displays container panel for customising and adding containers.
- */
- showContainerSettings() {
- gotoPref("containers");
- },
-
#ifdef MOZ_SAFE_BROWSING
/**
* Displays the available block lists for tracking protection.
@@ -702,25 +635,4 @@ var gPrivacyPane = {
settingsButton.disabled = !sanitizeOnShutdownPref.value;
},
-
- // CONTAINERS
-
- /*
- * preferences:
- *
- * privacy.userContext.enabled
- * - true if containers is enabled
- */
-
- /**
- * Enables/disables the Settings button used to configure containers
- */
- readBrowserContainersCheckbox: function ()
- {
- var pref = document.getElementById("privacy.userContext.enabled");
- var settings = document.getElementById("browserContainersSettings");
-
- settings.disabled = !pref.value;
- }
-
};
diff --git a/application/basilisk/components/preferences/in-content/privacy.xul b/application/basilisk/components/preferences/in-content/privacy.xul
index e6cdc5dd2..691cd6bf9 100644
--- a/application/basilisk/components/preferences/in-content/privacy.xul
+++ b/application/basilisk/components/preferences/in-content/privacy.xul
@@ -302,28 +302,3 @@
&suggestionSettings.label;
</label>
</groupbox>
-
-<!-- Containers -->
-<groupbox id="browserContainersGroup" data-category="panePrivacy" hidden="true">
- <vbox id="browserContainersbox" hidden="true">
- <caption><label>&browserContainersHeader.label;
- <label id="browserContainersLearnMore" class="text-link"
- value="&browserContainersLearnMore.label;"/>
- </label></caption>
- <hbox align="start">
- <vbox>
- <checkbox id="browserContainersCheckbox"
- label="&browserContainersEnabled.label;"
- accesskey="&browserContainersEnabled.accesskey;"
- preference="privacy.userContext.enabled"
- onsyncfrompreference="return gPrivacyPane.readBrowserContainersCheckbox();"/>
- </vbox>
- <spacer flex="1"/>
- <vbox>
- <button id="browserContainersSettings"
- label="&browserContainersSettings.label;"
- accesskey="&browserContainersSettings.accesskey;"/>
- </vbox>
- </hbox>
- </vbox>
-</groupbox>
diff --git a/application/basilisk/components/preferences/in-content/sync.js b/application/basilisk/components/preferences/in-content/sync.js
index 2600677a8..917b5f123 100644
--- a/application/basilisk/components/preferences/in-content/sync.js
+++ b/application/basilisk/components/preferences/in-content/sync.js
@@ -1,32 +1,16 @@
/* 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/. */
+ * 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/. */
Components.utils.import("resource://services-sync/main.js");
Components.utils.import("resource://gre/modules/Services.jsm");
-XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
- return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {});
-});
-
-XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
- "resource://gre/modules/FxAccounts.jsm");
-
const PAGE_NO_ACCOUNT = 0;
const PAGE_HAS_ACCOUNT = 1;
const PAGE_NEEDS_UPDATE = 2;
-const FXA_PAGE_LOGGED_OUT = 3;
-const FXA_PAGE_LOGGED_IN = 4;
-
-// Indexes into the "login status" deck.
-// We are in a successful verified state - everything should work!
-const FXA_LOGIN_VERIFIED = 0;
-// We have logged in to an unverified account.
-const FXA_LOGIN_UNVERIFIED = 1;
-// We are logged in locally, but the server rejected our credentials.
-const FXA_LOGIN_FAILED = 2;
var gSyncPane = {
+ _stringBundle: null,
prefArray: ["engine.bookmarks", "engine.passwords", "engine.prefs",
"engine.tabs", "engine.history"],
@@ -45,13 +29,11 @@ var gSyncPane = {
needsUpdate: function () {
this.page = PAGE_NEEDS_UPDATE;
let label = document.getElementById("loginError");
- label.textContent = Weave.Utils.getErrorString(Weave.Status.login);
+ label.value = Weave.Utils.getErrorString(Weave.Status.login);
label.className = "error";
},
init: function () {
- this._setupEventListeners();
-
// If the Service hasn't finished initializing, wait for it.
let xps = Components.classes["@mozilla.org/weave/service;1"]
.getService(Components.interfaces.nsISupports)
@@ -62,10 +44,6 @@ var gSyncPane = {
return;
}
- // it may take some time before we can determine what provider to use
- // and the state of that provider, so show the "please wait" page.
- this._showLoadPage(xps);
-
let onUnload = function () {
window.removeEventListener("unload", onUnload, false);
try {
@@ -85,247 +63,50 @@ var gSyncPane = {
xps.ensureLoaded();
},
- _showLoadPage: function (xps) {
- let username;
- try {
- username = Services.prefs.getCharPref("services.sync.username");
- } catch (e) {}
- if (!username) {
- this.page = FXA_PAGE_LOGGED_OUT;
- } else if (xps.fxAccountsEnabled) {
- // Use cached values while we wait for the up-to-date values
- let cachedComputerName;
- try {
- cachedComputerName = Services.prefs.getCharPref("services.sync.client.name");
- }
- catch (e) {
- cachedComputerName = "";
- }
- document.getElementById("fxaEmailAddress1").textContent = username;
- this._populateComputerName(cachedComputerName);
- this.page = FXA_PAGE_LOGGED_IN;
- } else { // Old Sync
- this.page = PAGE_HAS_ACCOUNT;
- }
- },
-
_init: function () {
let topics = ["weave:service:login:error",
"weave:service:login:finish",
- "weave:service:start-over:finish",
+ "weave:service:start-over",
"weave:service:setup-complete",
- "weave:service:logout:finish",
- FxAccountsCommon.ONVERIFIED_NOTIFICATION,
- FxAccountsCommon.ONLOGIN_NOTIFICATION,
- FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION,
- ];
+ "weave:service:logout:finish"];
+
// Add the observers now and remove them on unload
- // XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
+ //XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
// of `this`. Fix in a followup. (bug 583347)
topics.forEach(function (topic) {
Weave.Svc.Obs.add(topic, this.updateWeavePrefs, this);
}, this);
-
window.addEventListener("unload", function() {
topics.forEach(function (topic) {
Weave.Svc.Obs.remove(topic, this.updateWeavePrefs, this);
}, gSyncPane);
}, false);
- XPCOMUtils.defineLazyGetter(this, '_stringBundle', () => {
- return Services.strings.createBundle("chrome://browser/locale/preferences/preferences.properties");
- });
-
- XPCOMUtils.defineLazyGetter(this, '_accountsStringBundle', () => {
- return Services.strings.createBundle("chrome://browser/locale/accounts.properties");
- });
-
- let url = Services.prefs.getCharPref("identity.mobilepromo.android") + "sync-preferences";
- document.getElementById("fxaMobilePromo-android").setAttribute("href", url);
- document.getElementById("fxaMobilePromo-android-hasFxaAccount").setAttribute("href", url);
- url = Services.prefs.getCharPref("identity.mobilepromo.ios") + "sync-preferences";
- document.getElementById("fxaMobilePromo-ios").setAttribute("href", url);
- document.getElementById("fxaMobilePromo-ios-hasFxaAccount").setAttribute("href", url);
-
- document.getElementById("tosPP-small-ToS").setAttribute("href", gSyncUtils.tosURL);
- document.getElementById("tosPP-normal-ToS").setAttribute("href", gSyncUtils.tosURL);
- document.getElementById("tosPP-small-PP").setAttribute("href", gSyncUtils.privacyPolicyURL);
- document.getElementById("tosPP-normal-PP").setAttribute("href", gSyncUtils.privacyPolicyURL);
-
- fxAccounts.promiseAccountsManageURI(this._getEntryPoint()).then(url => {
- document.getElementById("verifiedManage").setAttribute("href", url);
- });
-
+ this._stringBundle =
+ Services.strings.createBundle("chrome://browser/locale/preferences/preferences.properties");
this.updateWeavePrefs();
-
- this._initProfileImageUI();
- },
-
- _toggleComputerNameControls: function(editMode) {
- let textbox = document.getElementById("fxaSyncComputerName");
- textbox.disabled = !editMode;
- document.getElementById("fxaChangeDeviceName").hidden = editMode;
- document.getElementById("fxaCancelChangeDeviceName").hidden = !editMode;
- document.getElementById("fxaSaveChangeDeviceName").hidden = !editMode;
- },
-
- _focusComputerNameTextbox: function() {
- let textbox = document.getElementById("fxaSyncComputerName");
- let valLength = textbox.value.length;
- textbox.focus();
- textbox.setSelectionRange(valLength, valLength);
- },
-
- _blurComputerNameTextbox: function() {
- document.getElementById("fxaSyncComputerName").blur();
- },
-
- _focusAfterComputerNameTextbox: function() {
- // Focus the most appropriate element that's *not* the "computer name" box.
- Services.focus.moveFocus(window,
- document.getElementById("fxaSyncComputerName"),
- Services.focus.MOVEFOCUS_FORWARD, 0);
- },
-
- _updateComputerNameValue: function(save) {
- if (save) {
- let textbox = document.getElementById("fxaSyncComputerName");
- Weave.Service.clientsEngine.localName = textbox.value;
- }
- this._populateComputerName(Weave.Service.clientsEngine.localName);
- },
-
- _setupEventListeners: function() {
- function setEventListener(aId, aEventType, aCallback)
- {
- document.getElementById(aId)
- .addEventListener(aEventType, aCallback.bind(gSyncPane));
- }
-
- setEventListener("noAccountSetup", "click", function (aEvent) {
- aEvent.stopPropagation();
- gSyncPane.openSetup(null);
- });
- setEventListener("noAccountPair", "click", function (aEvent) {
- aEvent.stopPropagation();
- gSyncPane.openSetup('pair');
- });
- setEventListener("syncChangePassword", "command",
- () => gSyncUtils.changePassword());
- setEventListener("syncResetPassphrase", "command",
- () => gSyncUtils.resetPassphrase());
- setEventListener("syncReset", "command", gSyncPane.resetSync);
- setEventListener("syncAddDeviceLabel", "click", function () {
- gSyncPane.openAddDevice();
- return false;
- });
- setEventListener("syncEnginesList", "select", function () {
- if (this.selectedCount)
- this.clearSelection();
- });
- setEventListener("syncComputerName", "change", function (e) {
- gSyncUtils.changeName(e.target);
- });
- setEventListener("fxaChangeDeviceName", "command", function () {
- this._toggleComputerNameControls(true);
- this._focusComputerNameTextbox();
- });
- setEventListener("fxaCancelChangeDeviceName", "command", function () {
- // We explicitly blur the textbox because of bug 75324, then after
- // changing the state of the buttons, force focus to whatever the focus
- // manager thinks should be next (which on the mac, depends on an OSX
- // keyboard access preference)
- this._blurComputerNameTextbox();
- this._toggleComputerNameControls(false);
- this._updateComputerNameValue(false);
- this._focusAfterComputerNameTextbox();
- });
- setEventListener("fxaSaveChangeDeviceName", "command", function () {
- // Work around bug 75324 - see above.
- this._blurComputerNameTextbox();
- this._toggleComputerNameControls(false);
- this._updateComputerNameValue(true);
- this._focusAfterComputerNameTextbox();
- });
- setEventListener("unlinkDevice", "click", function () {
- gSyncPane.startOver(true);
- return false;
- });
- setEventListener("loginErrorUpdatePass", "click", function () {
- gSyncPane.updatePass();
- return false;
- });
- setEventListener("loginErrorResetPass", "click", function () {
- gSyncPane.resetPass();
- return false;
- });
- setEventListener("loginErrorStartOver", "click", function () {
- gSyncPane.startOver(true);
- return false;
- });
- setEventListener("noFxaSignUp", "command", function () {
- gSyncPane.signUp();
- return false;
- });
- setEventListener("noFxaSignIn", "command", function () {
- gSyncPane.signIn();
- return false;
- });
- setEventListener("fxaUnlinkButton", "command", function () {
- gSyncPane.unlinkFirefoxAccount(true);
- });
- setEventListener("verifyFxaAccount", "command",
- gSyncPane.verifyFirefoxAccount);
- setEventListener("unverifiedUnlinkFxaAccount", "command", function () {
- /* no warning as account can't have previously synced */
- gSyncPane.unlinkFirefoxAccount(false);
- });
- setEventListener("rejectReSignIn", "command",
- gSyncPane.reSignIn);
- setEventListener("rejectUnlinkFxaAccount", "command", function () {
- gSyncPane.unlinkFirefoxAccount(true);
- });
- setEventListener("fxaSyncComputerName", "keypress", function (e) {
- if (e.keyCode == KeyEvent.DOM_VK_RETURN) {
- document.getElementById("fxaSaveChangeDeviceName").click();
- } else if (e.keyCode == KeyEvent.DOM_VK_ESCAPE) {
- document.getElementById("fxaCancelChangeDeviceName").click();
- }
- });
- },
-
- _initProfileImageUI: function () {
- try {
- if (Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled")) {
- document.getElementById("fxaProfileImage").hidden = false;
- }
- } catch (e) { }
+ document.getElementById("weavePrefsDeck").setAttribute("hidden", "");
},
updateWeavePrefs: function () {
- let service = Components.classes["@mozilla.org/weave/service;1"]
- .getService(Components.interfaces.nsISupports)
- .wrappedJSObject;
if (Weave.Status.service == Weave.CLIENT_NOT_CONFIGURED ||
Weave.Svc.Prefs.get("firstSync", "") == "notReady") {
this.page = PAGE_NO_ACCOUNT;
- // else: sync was previously configured for the legacy provider, so we
- // make the "old" panels available.
} else if (Weave.Status.login == Weave.LOGIN_FAILED_INVALID_PASSPHRASE ||
Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
this.needsUpdate();
} else {
this.page = PAGE_HAS_ACCOUNT;
- document.getElementById("accountName").textContent = Weave.Service.identity.account;
+ document.getElementById("accountName").value = Weave.Service.identity.account;
document.getElementById("syncComputerName").value = Weave.Service.clientsEngine.localName;
- document.getElementById("tosPP-normal").hidden = this._usingCustomServer;
+ document.getElementById("tosPP").hidden = this._usingCustomServer;
}
},
startOver: function (showDialog) {
if (showDialog) {
let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
- Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL +
+ Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL +
Services.prompt.BUTTON_POS_1_DEFAULT;
let buttonChoice =
Services.prompt.confirmEx(window,
@@ -336,8 +117,9 @@ var gSyncPane = {
null, null, null, {});
// If the user selects cancel, just bail
- if (buttonChoice == 1)
+ if (buttonChoice == 1) {
return;
+ }
}
Weave.Service.startOver();
@@ -345,33 +127,19 @@ var gSyncPane = {
},
updatePass: function () {
- if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED)
+ if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
gSyncUtils.changePassword();
- else
+ } else {
gSyncUtils.updatePassphrase();
+ }
},
resetPass: function () {
- if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED)
+ if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
gSyncUtils.resetPassword();
- else
+ } else {
gSyncUtils.resetPassphrase();
- },
-
- _getEntryPoint: function () {
- let params = new URLSearchParams(document.URL.split("#")[0].split("?")[1] || "");
- return params.get("entrypoint") || "preferences";
- },
-
- _openAboutAccounts: function(action) {
- let entryPoint = this._getEntryPoint();
- let params = new URLSearchParams();
- if (action) {
- params.set("action", action);
}
- params.set("entrypoint", entryPoint);
-
- this.replaceTabWithUrl("about:accounts?" + params);
},
/**
@@ -384,163 +152,16 @@ var gSyncPane = {
* "reset" -- reset sync
*/
openSetup: function (wizardType) {
- let service = Components.classes["@mozilla.org/weave/service;1"]
- .getService(Components.interfaces.nsISupports)
- .wrappedJSObject;
-
- if (service.fxAccountsEnabled) {
- this._openAboutAccounts();
+ let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
+ if (win) {
+ win.focus();
} else {
- let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
- if (win)
- win.focus();
- else {
- window.openDialog("chrome://browser/content/sync/setup.xul",
- "weaveSetup", "centerscreen,chrome,resizable=no",
- wizardType);
- }
- }
- },
-
- openContentInBrowser: function(url, options) {
- let win = Services.wm.getMostRecentWindow("navigator:browser");
- if (!win) {
- // no window to use, so use _openLink to create a new one. We don't
- // always use that as it prefers to open a new window rather than use
- // an existing one.
- gSyncUtils._openLink(url);
- return;
- }
- win.switchToTabHavingURI(url, true, options);
- },
-
- // Replace the current tab with the specified URL.
- replaceTabWithUrl(url) {
- // Get the <browser> element hosting us.
- let browser = window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell)
- .chromeEventHandler;
- // And tell it to load our URL.
- browser.loadURI(url);
- },
-
- signUp: function() {
- this._openAboutAccounts("signup");
- },
-
- signIn: function() {
- this._openAboutAccounts("signin");
- },
-
- reSignIn: function() {
- this._openAboutAccounts("reauth");
- },
-
-
- clickOrSpaceOrEnterPressed: function(event) {
- // Note: charCode is deprecated, but 'char' not yet implemented.
- // Replace charCode with char when implemented, see Bug 680830
- return ((event.type == "click" && event.button == 0) ||
- (event.type == "keypress" &&
- (event.charCode == KeyEvent.DOM_VK_SPACE || event.keyCode == KeyEvent.DOM_VK_RETURN)));
- },
-
- openChangeProfileImage: function(event) {
- if (this.clickOrSpaceOrEnterPressed(event)) {
- fxAccounts.promiseAccountsChangeProfileURI(this._getEntryPoint(), "avatar")
- .then(url => {
- this.openContentInBrowser(url, {
- replaceQueryString: true
- });
- });
- // Prevent page from scrolling on the space key.
- event.preventDefault();
+ window.openDialog("chrome://browser/content/sync/setup.xul",
+ "weaveSetup", "centerscreen,chrome,resizable=no",
+ wizardType);
}
},
- openManageFirefoxAccount: function(event) {
- if (this.clickOrSpaceOrEnterPressed(event)) {
- this.manageFirefoxAccount();
- // Prevent page from scrolling on the space key.
- event.preventDefault();
- }
- },
-
- manageFirefoxAccount: function() {
- fxAccounts.promiseAccountsManageURI(this._getEntryPoint())
- .then(url => {
- this.openContentInBrowser(url, {
- replaceQueryString: true
- });
- });
- },
-
- verifyFirefoxAccount: function() {
- let showVerifyNotification = (data) => {
- let isError = !data;
- let maybeNot = isError ? "Not" : "";
- let sb = this._accountsStringBundle;
- let title = sb.GetStringFromName("verification" + maybeNot + "SentTitle");
- let email = !isError && data ? data.email : "";
- let body = sb.formatStringFromName("verification" + maybeNot + "SentBody", [email], 1);
- new Notification(title, { body })
- }
-
- let onError = () => {
- showVerifyNotification();
- };
-
- let onSuccess = data => {
- if (data) {
- showVerifyNotification(data);
- } else {
- onError();
- }
- };
-
- fxAccounts.resendVerificationEmail()
- .then(fxAccounts.getSignedInUser, onError)
- .then(onSuccess, onError);
- },
-
- openOldSyncSupportPage: function() {
- let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "old-sync";
- this.openContentInBrowser(url);
- },
-
- unlinkFirefoxAccount: function(confirm) {
- if (confirm) {
- // We use a string bundle shared with aboutAccounts.
- let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
- let disconnectLabel = sb.GetStringFromName("disconnect.label");
- let title = sb.GetStringFromName("disconnect.verify.title");
- let body = sb.GetStringFromName("disconnect.verify.bodyHeading") +
- "\n\n" +
- sb.GetStringFromName("disconnect.verify.bodyText");
- let ps = Services.prompt;
- let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
- (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
- ps.BUTTON_POS_1_DEFAULT;
-
- let factory = Cc["@mozilla.org/prompter;1"]
- .getService(Ci.nsIPromptFactory);
- let prompt = factory.getPrompt(window, Ci.nsIPrompt);
- let bag = prompt.QueryInterface(Ci.nsIWritablePropertyBag2);
- bag.setPropertyAsBool("allowTabModal", true);
-
- let pressed = prompt.confirmEx(title, body, buttonFlags,
- disconnectLabel, null, null, null, {});
-
- if (pressed != 0) { // 0 is the "continue" button
- return;
- }
- }
- fxAccounts.signOut().then(() => {
- this.updateWeavePrefs();
- });
- },
-
openQuotaDialog: function () {
let win = Services.wm.getMostRecentWindow("Sync:ViewQuota");
if (win) {
@@ -552,27 +173,21 @@ var gSyncPane = {
},
openAddDevice: function () {
- if (!Weave.Utils.ensureMPUnlocked())
+ if (!Weave.Utils.ensureMPUnlocked()) {
return;
+ }
let win = Services.wm.getMostRecentWindow("Sync:AddDevice");
- if (win)
+ if (win) {
win.focus();
- else
+ } else {
window.openDialog("chrome://browser/content/sync/addDevice.xul",
"syncAddDevice", "centerscreen,chrome,resizable=no");
+ }
},
resetSync: function () {
this.openSetup("reset");
},
-
- _populateComputerName(value) {
- let textbox = document.getElementById("fxaSyncComputerName");
- if (!textbox.hasAttribute("placeholder")) {
- textbox.setAttribute("placeholder",
- Weave.Utils.getDefaultDeviceName());
- }
- textbox.value = value;
- },
};
+
diff --git a/application/basilisk/components/preferences/in-content/sync.xul b/application/basilisk/components/preferences/in-content/sync.xul
index cf0e81ca1..7ca075483 100644
--- a/application/basilisk/components/preferences/in-content/sync.xul
+++ b/application/basilisk/components/preferences/in-content/sync.xul
@@ -1,35 +1,22 @@
-# 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/.
-
-<!-- Sync panel -->
-
-<preferences id="syncEnginePrefs" hidden="true" data-category="paneSync">
- <preference id="engine.addons"
- name="services.sync.engine.addons"
- type="bool"/>
- <preference id="engine.bookmarks"
- name="services.sync.engine.bookmarks"
- type="bool"/>
- <preference id="engine.history"
- name="services.sync.engine.history"
- type="bool"/>
- <preference id="engine.tabs"
- name="services.sync.engine.tabs"
- type="bool"/>
- <preference id="engine.prefs"
- name="services.sync.engine.prefs"
- type="bool"/>
- <preference id="engine.passwords"
- name="services.sync.engine.passwords"
- type="bool"/>
-</preferences>
+<!-- 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/. -->
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content/sync.js"/>
<script type="application/javascript"
src="chrome://browser/content/sync/utils.js"/>
+<preferences>
+<!-- <preference id="engine.addons" name="services.sync.engine.addons" type="bool"/> -->
+ <preference id="engine.bookmarks" name="services.sync.engine.bookmarks" type="bool"/>
+ <preference id="engine.history" name="services.sync.engine.history" type="bool"/>
+ <preference id="engine.tabs" name="services.sync.engine.tabs" type="bool"/>
+ <preference id="engine.prefs" name="services.sync.engine.prefs" type="bool"/>
+ <preference id="engine.passwords" name="services.sync.engine.passwords" type="bool"/>
+</preferences>
+
+
<hbox id="header-sync"
class="header"
hidden="true"
@@ -39,22 +26,19 @@
</hbox>
<deck id="weavePrefsDeck" data-category="paneSync" hidden="true">
- <!-- These panels are for the "legacy" sync provider -->
<vbox id="noAccount" align="center">
<spacer flex="1"/>
<description id="syncDesc">
&weaveDesc.label;
</description>
<separator/>
- <label id="noAccountSetup" class="text-link">
- &setupButton.label;
- </label>
- <vbox id="pairDevice">
- <separator/>
- <label id="noAccountPair" class="text-link">
- &pairDevice.label;
- </label>
- </vbox>
+ <label class="text-link"
+ onclick="event.stopPropagation(); gSyncPane.openSetup(null);"
+ value="&setupButton.label;"/>
+ <separator/>
+ <label class="text-link"
+ onclick="event.stopPropagation(); gSyncPane.openSetup('pair');"
+ value="&pairDevice.label;"/>
<spacer flex="3"/>
</vbox>
@@ -63,7 +47,7 @@
<!-- label is set to account name -->
<caption id="accountCaption" align="center">
<image id="accountCaptionImage"/>
- <label id="accountName"/>
+ <label id="accountName" value=""/>
</caption>
<hbox>
@@ -71,28 +55,39 @@
label="&manageAccount.label;"
accesskey="&manageAccount.accesskey;">
<menupopup>
- <menuitem id="syncViewQuota" label="&viewQuota.label;"
+ <menuitem label="&viewQuota.label;"
oncommand="gSyncPane.openQuotaDialog();"/>
- <menuseparator/>
- <menuitem id="syncChangePassword" label="&changePassword2.label;"/>
- <menuitem id="syncResetPassphrase" label="&myRecoveryKey.label;"/>
<menuseparator/>
- <menuitem id="syncReset" label="&resetSync2.label;"/>
+ <menuitem label="&changePassword2.label;"
+ oncommand="gSyncUtils.changePassword();"/>
+ <menuitem label="&myRecoveryKey.label;"
+ oncommand="gSyncUtils.resetPassphrase();"/>
+ <menuseparator/>
+ <menuitem label="&resetSync2.label;"
+ oncommand="gSyncPane.resetSync();"/>
</menupopup>
</button>
</hbox>
<hbox>
<label id="syncAddDeviceLabel"
- class="text-link">
- &pairDevice.label;
- </label>
+ class="text-link"
+ onclick="gSyncPane.openAddDevice(); return false;"
+ value="&pairDevice.label;"/>
</hbox>
<vbox>
- <label>&syncMy.label;</label>
+ <label value="&syncMy.label;" />
<richlistbox id="syncEnginesList"
- orient="vertical">
+ orient="vertical"
+ onselect="if (this.selectedCount) this.clearSelection();">
+ <!--
+ <richlistitem>
+ <checkbox label="&engine.addons.label;"
+ accesskey="&engine.addons.accesskey;"
+ preference="engine.addons"/>
+ </richlistitem>
+ -->
<richlistitem>
<checkbox label="&engine.bookmarks.label;"
accesskey="&engine.bookmarks.accesskey;"
@@ -130,228 +125,42 @@
</columns>
<rows>
<row align="center">
- <label control="syncComputerName">
- &syncDeviceName.label;
- </label>
- <textbox id="syncComputerName"/>
+ <label value="&syncDeviceName.label;"
+ accesskey="&syncDeviceName.accesskey;"
+ control="syncComputerName"/>
+ <textbox id="syncComputerName"
+ onchange="gSyncUtils.changeName(this)"/>
</row>
</rows>
</grid>
<hbox>
- <label id="unlinkDevice" class="text-link">
- &unlinkDevice.label;
- </label>
+ <label class="text-link"
+ onclick="gSyncPane.startOver(true); return false;"
+ value="&unlinkDevice.label;"/>
</hbox>
</groupbox>
- <vbox id="tosPP-normal">
- <label id="tosPP-normal-ToS" class="text-link">
- &prefs.tosLink.label;
- </label>
- <label id="tosPP-normal-PP" class="text-link">
- &prefs.ppLink.label;
- </label>
- </vbox>
- </vbox>
-
- <vbox id="needsUpdate" align="center" pack="center">
- <hbox>
- <label id="loginError"/>
- <label id="loginErrorUpdatePass" class="text-link">
- &updatePass.label;
- </label>
- <label id="loginErrorResetPass" class="text-link">
- &resetPass.label;
- </label>
+ <hbox id="tosPP" pack="center">
+ <label class="text-link"
+ onclick="event.stopPropagation();gSyncUtils.openToS();"
+ value="&prefs.tosLink.label;"/>
+ <label class="text-link"
+ onclick="event.stopPropagation();gSyncUtils.openPrivacyPolicy();"
+ value="&prefs.ppLink.label;"/>
</hbox>
- <label id="loginErrorStartOver" class="text-link">
- &unlinkDevice.label;
- </label>
</vbox>
- <!-- These panels are for the Firefox Accounts identity provider -->
- <vbox id="noFxaAccount">
- <hbox>
- <vbox id="fxaContentWrapper">
- <groupbox id="noFxaGroup">
- <vbox>
- <label id="noFxaCaption">&signedOut.caption;</label>
- <description id="noFxaDescription" flex="1">&signedOut.description;</description>
- <hbox class="fxaAccountBox">
- <vbox>
- <image class="fxaFirefoxLogo"/>
- </vbox>
- <vbox flex="1">
- <label id="signedOutAccountBoxTitle">&signedOut.accountBox.title;</label>
- <hbox class="fxaAccountBoxButtons">
- <button id="noFxaSignUp" label="&signedOut.accountBox.create;" accesskey="&signedOut.accountBox.create.accesskey;"></button>
- <button id="noFxaSignIn" label="&signedOut.accountBox.signin;" accesskey="&signedOut.accountBox.signin.accesskey;"></button>
- </hbox>
- </vbox>
- </hbox>
- </vbox>
- </groupbox>
- </vbox>
- <vbox>
- <image class="fxaSyncIllustration"/>
- </vbox>
- </hbox>
- <label class="fxaMobilePromo">
- &mobilePromo3.start;<!-- We put these comments to avoid inserting white spaces
- --><label id="fxaMobilePromo-android"
- class="androidLink text-link"><!--
- -->&mobilePromo3.androidLink;</label><!--
- -->&mobilePromo3.iOSBefore;<!--
- --><label id="fxaMobilePromo-ios"
- class="iOSLink text-link"><!--
- -->&mobilePromo3.iOSLink;</label><!--
- -->&mobilePromo3.end;
- </label>
- </vbox>
-
- <vbox id="hasFxaAccount">
+ <vbox id="needsUpdate" align="center" pack="center">
<hbox>
- <vbox id="fxaContentWrapper">
- <groupbox id="fxaGroup">
- <caption><label>&syncBrand.fxAccount.label;</label></caption>
- <deck id="fxaLoginStatus">
-
- <!-- logged in and verified and all is good -->
- <hbox id="fxaLoginVerified" class="fxaAccountBox">
- <vbox align="center" pack="center">
- <image id="fxaProfileImage" class="actionable"
- role="button"
- onclick="gSyncPane.openChangeProfileImage(event);" hidden="true"
- onkeypress="gSyncPane.openChangeProfileImage(event);"
- tooltiptext="&profilePicture.tooltip;"/>
- </vbox>
- <vbox flex="1" pack="center">
- <label id="fxaDisplayName" hidden="true"/>
- <label id="fxaEmailAddress1"/>
- <hbox class="fxaAccountBoxButtons">
- <button id="fxaUnlinkButton" label="&disconnect.label;" accesskey="&disconnect.accesskey;"/>
- <html:a id="verifiedManage" target="_blank"
- accesskey="&verifiedManage.accesskey;"
- onkeypress="gSyncPane.openManageFirefoxAccount(event);"><!--
- -->&verifiedManage.label;</html:a>
- </hbox>
- </vbox>
- </hbox>
-
- <!-- logged in to an unverified account -->
- <hbox id="fxaLoginUnverified" class="fxaAccountBox">
- <vbox>
- <image id="fxaProfileImage"/>
- </vbox>
- <vbox flex="1">
- <hbox>
- <vbox><image id="fxaLoginRejectedWarning"/></vbox>
- <description flex="1">
- &signedInUnverified.beforename.label;
- <label id="fxaEmailAddress2"/>
- &signedInUnverified.aftername.label;
- </description>
- </hbox>
- <hbox class="fxaAccountBoxButtons">
- <button id="verifyFxaAccount" accesskey="&verify.accesskey;">&verify.label;</button>
- <button id="unverifiedUnlinkFxaAccount" accesskey="&forget.accesskey;">&forget.label;</button>
- </hbox>
- </vbox>
- </hbox>
-
- <!-- logged in locally but server rejected credentials -->
- <hbox id="fxaLoginRejected" class="fxaAccountBox">
- <vbox>
- <image id="fxaProfileImage"/>
- </vbox>
- <vbox flex="1">
- <hbox>
- <vbox><image id="fxaLoginRejectedWarning"/></vbox>
- <description flex="1">
- &signedInLoginFailure.beforename.label;
- <label id="fxaEmailAddress3"/>
- &signedInLoginFailure.aftername.label;
- </description>
- </hbox>
- <hbox class="fxaAccountBoxButtons">
- <button id="rejectReSignIn" accessky="&signIn.accesskey;">&signIn.label;</button>
- <button id="rejectUnlinkFxaAccount" accesskey="&forget.accesskey;">&forget.label;</button>
- </hbox>
- </vbox>
- </hbox>
- </deck>
- </groupbox>
- <groupbox id="syncOptions">
- <caption><label>&signedIn.engines.label;</label></caption>
- <hbox id="fxaSyncEngines">
- <vbox align="start" flex="1">
- <checkbox label="&engine.tabs.label;"
- accesskey="&engine.tabs.accesskey;"
- preference="engine.tabs"/>
- <checkbox label="&engine.bookmarks.label;"
- accesskey="&engine.bookmarks.accesskey;"
- preference="engine.bookmarks"/>
- <checkbox label="&engine.passwords.label;"
- accesskey="&engine.passwords.accesskey;"
- preference="engine.passwords"/>
- </vbox>
- <vbox align="start" flex="1">
- <checkbox label="&engine.history.label;"
- accesskey="&engine.history.accesskey;"
- preference="engine.history"/>
- <checkbox label="&engine.addons.label;"
- accesskey="&engine.addons.accesskey;"
- preference="engine.addons"/>
- <checkbox label="&engine.prefs.label;"
- accesskey="&engine.prefs.accesskey;"
- preference="engine.prefs"/>
- </vbox>
- <spacer/>
- </hbox>
- </groupbox>
- </vbox>
- <vbox>
- <image class="fxaSyncIllustration"/>
- </vbox>
+ <label id="loginError" value=""/>
+ <label class="text-link"
+ onclick="gSyncPane.updatePass(); return false;"
+ value="&updatePass.label;"/>
+ <label class="text-link"
+ onclick="gSyncPane.resetPass(); return false;"
+ value="&resetPass.label;"/>
</hbox>
- <groupbox>
- <caption>
- <label control="fxaSyncComputerName">
- &fxaSyncDeviceName.label;
- </label>
- </caption>
- <hbox id="fxaDeviceName">
- <textbox id="fxaSyncComputerName" disabled="true"/>
- <hbox>
- <button id="fxaChangeDeviceName"
- label="&changeSyncDeviceName.label;"
- accesskey="&changeSyncDeviceName.accesskey;"/>
- <button id="fxaCancelChangeDeviceName"
- label="&cancelChangeSyncDeviceName.label;"
- accesskey="&cancelChangeSyncDeviceName.accesskey;"
- hidden="true"/>
- <button id="fxaSaveChangeDeviceName"
- label="&saveChangeSyncDeviceName.label;"
- accesskey="&saveChangeSyncDeviceName.accesskey;"
- hidden="true"/>
- </hbox>
- </hbox>
- </groupbox>
- <label class="fxaMobilePromo">
- &mobilePromo3.start;<!-- We put these comments to avoid inserting white spaces
- --><label class="androidLink text-link" id="fxaMobilePromo-android-hasFxaAccount"><!--
- -->&mobilePromo3.androidLink;</label><!--
- -->&mobilePromo3.iOSBefore;<!--
- --><label class="iOSLink text-link" id="fxaMobilePromo-ios-hasFxaAccount"><!--
- -->&mobilePromo3.iOSLink;</label><!--
- -->&mobilePromo3.end;
- </label>
- <vbox id="tosPP-small" align="start">
- <label id="tosPP-small-ToS" class="text-link">
- &prefs.tosLink.label;
- </label>
- <label id="tosPP-small-PP" class="text-link">
- &fxaPrivacyNotice.link.label;
- </label>
- </vbox>
+ <label class="text-link"
+ onclick="gSyncPane.startOver(true); return false;"
+ value="&unlinkDevice.label;"/>
</vbox>
</deck>
diff --git a/application/basilisk/components/preferences/jar.mn b/application/basilisk/components/preferences/jar.mn
index 5b24e89df..f74be0820 100644
--- a/application/basilisk/components/preferences/jar.mn
+++ b/application/basilisk/components/preferences/jar.mn
@@ -24,8 +24,6 @@ browser.jar:
* content/browser/preferences/languages.xul
content/browser/preferences/languages.js
content/browser/preferences/permissions.xul
- content/browser/preferences/containers.xul
- content/browser/preferences/containers.js
content/browser/preferences/permissions.js
content/browser/preferences/sanitize.xul
content/browser/preferences/sanitize.js
diff --git a/application/basilisk/components/search/moz.build b/application/basilisk/components/search/moz.build
index aac3a838c..b406d5f16 100644
--- a/application/basilisk/components/search/moz.build
+++ b/application/basilisk/components/search/moz.build
@@ -4,4 +4,6 @@
# 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/.
+DIRS += ['service']
+
JAR_MANIFESTS += ['jar.mn']
diff --git a/application/basilisk/components/search/service/SearchStaticData.jsm b/application/basilisk/components/search/service/SearchStaticData.jsm
new file mode 100644
index 000000000..de2be695c
--- /dev/null
+++ b/application/basilisk/components/search/service/SearchStaticData.jsm
@@ -0,0 +1,43 @@
+/* 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 module contains additional data about default search engines that is the
+ * same across all languages. This information is defined outside of the actual
+ * search engine definition files, so that localizers don't need to update them
+ * when a change is made.
+ *
+ * This separate module is also easily overridable, in case a hotfix is needed.
+ * No high-level processing logic is applied here.
+ */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = [
+ "SearchStaticData",
+];
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+// To update this list of known alternate domains, just cut-and-paste from
+// https://www.google.com/supported_domains
+const gGoogleDomainsSource = ".google.com .google.ad .google.ae .google.com.af .google.com.ag .google.com.ai .google.al .google.am .google.co.ao .google.com.ar .google.as .google.at .google.com.au .google.az .google.ba .google.com.bd .google.be .google.bf .google.bg .google.com.bh .google.bi .google.bj .google.com.bn .google.com.bo .google.com.br .google.bs .google.bt .google.co.bw .google.by .google.com.bz .google.ca .google.cd .google.cf .google.cg .google.ch .google.ci .google.co.ck .google.cl .google.cm .google.cn .google.com.co .google.co.cr .google.com.cu .google.cv .google.com.cy .google.cz .google.de .google.dj .google.dk .google.dm .google.com.do .google.dz .google.com.ec .google.ee .google.com.eg .google.es .google.com.et .google.fi .google.com.fj .google.fm .google.fr .google.ga .google.ge .google.gg .google.com.gh .google.com.gi .google.gl .google.gm .google.gp .google.gr .google.com.gt .google.gy .google.com.hk .google.hn .google.hr .google.ht .google.hu .google.co.id .google.ie .google.co.il .google.im .google.co.in .google.iq .google.is .google.it .google.je .google.com.jm .google.jo .google.co.jp .google.co.ke .google.com.kh .google.ki .google.kg .google.co.kr .google.com.kw .google.kz .google.la .google.com.lb .google.li .google.lk .google.co.ls .google.lt .google.lu .google.lv .google.com.ly .google.co.ma .google.md .google.me .google.mg .google.mk .google.ml .google.com.mm .google.mn .google.ms .google.com.mt .google.mu .google.mv .google.mw .google.com.mx .google.com.my .google.co.mz .google.com.na .google.com.nf .google.com.ng .google.com.ni .google.ne .google.nl .google.no .google.com.np .google.nr .google.nu .google.co.nz .google.com.om .google.com.pa .google.com.pe .google.com.pg .google.com.ph .google.com.pk .google.pl .google.pn .google.com.pr .google.ps .google.pt .google.com.py .google.com.qa .google.ro .google.ru .google.rw .google.com.sa .google.com.sb .google.sc .google.se .google.com.sg .google.sh .google.si .google.sk .google.com.sl .google.sn .google.so .google.sm .google.sr .google.st .google.com.sv .google.td .google.tg .google.co.th .google.com.tj .google.tk .google.tl .google.tm .google.tn .google.to .google.com.tr .google.tt .google.com.tw .google.co.tz .google.com.ua .google.co.ug .google.co.uk .google.com.uy .google.co.uz .google.com.vc .google.co.ve .google.vg .google.co.vi .google.com.vn .google.vu .google.ws .google.rs .google.co.za .google.co.zm .google.co.zw .google.cat";
+const gGoogleDomains = gGoogleDomainsSource.split(" ").map(d => "www" + d);
+
+this.SearchStaticData = {
+ /**
+ * Returns a list of alternate domains for a given search engine domain.
+ *
+ * @param aDomain
+ * Lowercase host name to look up. For example, if this argument is
+ * "www.google.com" or "www.google.co.uk", the function returns the
+ * full list of supported Google domains.
+ *
+ * @return Array containing one entry for each alternate host name, or empty
+ * array if none is known. The returned array should not be modified.
+ */
+ getAlternateDomains: function (aDomain) {
+ return gGoogleDomains.indexOf(aDomain) == -1 ? [] : gGoogleDomains;
+ },
+};
diff --git a/application/basilisk/components/search/service/SearchSuggestionController.jsm b/application/basilisk/components/search/service/SearchSuggestionController.jsm
new file mode 100644
index 000000000..952838c0c
--- /dev/null
+++ b/application/basilisk/components/search/service/SearchSuggestionController.jsm
@@ -0,0 +1,398 @@
+/* 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.EXPORTED_SYMBOLS = ["SearchSuggestionController"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Promise.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NS_ASSERT", "resource://gre/modules/debug.js");
+
+const SEARCH_RESPONSE_SUGGESTION_JSON = "application/x-suggestions+json";
+const DEFAULT_FORM_HISTORY_PARAM = "searchbar-history";
+const HTTP_OK = 200;
+const REMOTE_TIMEOUT = 500; // maximum time (ms) to wait before giving up on a remote suggestions
+const BROWSER_SUGGEST_PREF = "browser.search.suggest.enabled";
+
+/**
+ * Remote search suggestions will be shown if gRemoteSuggestionsEnabled
+ * is true. Global because only one pref observer is needed for all instances.
+ */
+var gRemoteSuggestionsEnabled = Services.prefs.getBoolPref(BROWSER_SUGGEST_PREF);
+Services.prefs.addObserver(BROWSER_SUGGEST_PREF, function(aSubject, aTopic, aData) {
+ gRemoteSuggestionsEnabled = Services.prefs.getBoolPref(BROWSER_SUGGEST_PREF);
+}, false);
+
+/**
+ * SearchSuggestionController.jsm exists as a helper module to allow multiple consumers to request and display
+ * search suggestions from a given engine, regardless of the base implementation. Much of this
+ * code was originally in nsSearchSuggestions.js until it was refactored to separate it from the
+ * nsIAutoCompleteSearch dependency.
+ * One instance of SearchSuggestionController should be used per field since form history results are cached.
+ */
+
+/**
+ * @param {function} [callback] - Callback for search suggestion results. You can use the promise
+ * returned by the search method instead if you prefer.
+ * @constructor
+ */
+this.SearchSuggestionController = function SearchSuggestionController(callback = null) {
+ this._callback = callback;
+};
+
+this.SearchSuggestionController.prototype = {
+ /**
+ * The maximum number of local form history results to return. This limit is
+ * only enforced if remote results are also returned.
+ */
+ maxLocalResults: 5,
+
+ /**
+ * The maximum number of remote search engine results to return.
+ * We'll actually only display at most
+ * maxRemoteResults - <displayed local results count> remote results.
+ */
+ maxRemoteResults: 10,
+
+ /**
+ * The maximum time (ms) to wait before giving up on a remote suggestions.
+ */
+ remoteTimeout: REMOTE_TIMEOUT,
+
+ /**
+ * The additional parameter used when searching form history.
+ */
+ formHistoryParam: DEFAULT_FORM_HISTORY_PARAM,
+
+ // Private properties
+ /**
+ * The last form history result used to improve the performance of subsequent searches.
+ * This shouldn't be used for any other purpose as it is never cleared and therefore could be stale.
+ */
+ _formHistoryResult: null,
+
+ /**
+ * The remote server timeout timer, if applicable. The timer starts when form history
+ * search is completed.
+ */
+ _remoteResultTimer: null,
+
+ /**
+ * The deferred for the remote results before its promise is resolved.
+ */
+ _deferredRemoteResult: null,
+
+ /**
+ * The optional result callback registered from the constructor.
+ */
+ _callback: null,
+
+ /**
+ * The XMLHttpRequest object for remote results.
+ */
+ _request: null,
+
+ // Public methods
+
+ /**
+ * Fetch search suggestions from all of the providers. Fetches in progress will be stopped and
+ * results from them will not be provided.
+ *
+ * @param {string} searchTerm - the term to provide suggestions for
+ * @param {bool} privateMode - whether the request is being made in the context of private browsing
+ * @param {nsISearchEngine} engine - search engine for the suggestions.
+ * @param {int} userContextId - the userContextId of the selected tab.
+ *
+ * @return {Promise} resolving to an object containing results or null.
+ */
+ fetch: function(searchTerm, privateMode, engine, userContextId) {
+ // There is no smart filtering from previous results here (as there is when looking through
+ // history/form data) because the result set returned by the server is different for every typed
+ // value - e.g. "ocean breathes" does not return a subset of the results returned for "ocean".
+
+ this.stop();
+
+ if (!Services.search.isInitialized) {
+ throw new Error("Search not initialized yet (how did you get here?)");
+ }
+ if (typeof privateMode === "undefined") {
+ throw new Error("The privateMode argument is required to avoid unintentional privacy leaks");
+ }
+ if (!(engine instanceof Ci.nsISearchEngine)) {
+ throw new Error("Invalid search engine");
+ }
+ if (!this.maxLocalResults && !this.maxRemoteResults) {
+ throw new Error("Zero results expected, what are you trying to do?");
+ }
+ if (this.maxLocalResults < 0 || this.maxRemoteResults < 0) {
+ throw new Error("Number of requested results must be positive");
+ }
+
+ // Array of promises to resolve before returning results.
+ let promises = [];
+ this._searchString = searchTerm;
+
+ // Remote results
+ if (searchTerm && gRemoteSuggestionsEnabled && this.maxRemoteResults &&
+ engine.supportsResponseType(SEARCH_RESPONSE_SUGGESTION_JSON)) {
+ this._deferredRemoteResult = this._fetchRemote(searchTerm, engine, privateMode, userContextId);
+ promises.push(this._deferredRemoteResult.promise);
+ }
+
+ // Local results from form history
+ if (this.maxLocalResults) {
+ let deferredHistoryResult = this._fetchFormHistory(searchTerm);
+ promises.push(deferredHistoryResult.promise);
+ }
+
+ function handleRejection(reason) {
+ if (reason == "HTTP request aborted") {
+ // Do nothing since this is normal.
+ return null;
+ }
+ Cu.reportError("SearchSuggestionController rejection: " + reason);
+ return null;
+ }
+ return Promise.all(promises).then(this._dedupeAndReturnResults.bind(this), handleRejection);
+ },
+
+ /**
+ * Stop pending fetches so no results are returned from them.
+ *
+ * Note: If there was no remote results fetched, the fetching cannot be stopped and local results
+ * will still be returned because stopping relies on aborting the XMLHTTPRequest to reject the
+ * promise for Promise.all.
+ */
+ stop: function() {
+ if (this._request) {
+ this._request.abort();
+ } else if (!this.maxRemoteResults) {
+ Cu.reportError("SearchSuggestionController: Cannot stop fetching if remote results were not "+
+ "requested");
+ }
+ this._reset();
+ },
+
+ // Private methods
+
+ _fetchFormHistory: function(searchTerm) {
+ let deferredFormHistory = Promise.defer();
+
+ let acSearchObserver = {
+ // Implements nsIAutoCompleteSearch
+ onSearchResult: (search, result) => {
+ this._formHistoryResult = result;
+
+ if (this._request) {
+ this._remoteResultTimer = Cc["@mozilla.org/timer;1"].
+ createInstance(Ci.nsITimer);
+ this._remoteResultTimer.initWithCallback(this._onRemoteTimeout.bind(this),
+ this.remoteTimeout || REMOTE_TIMEOUT,
+ Ci.nsITimer.TYPE_ONE_SHOT);
+ }
+
+ switch (result.searchResult) {
+ case Ci.nsIAutoCompleteResult.RESULT_SUCCESS:
+ case Ci.nsIAutoCompleteResult.RESULT_NOMATCH:
+ if (result.searchString !== this._searchString) {
+ deferredFormHistory.resolve("Unexpected response, this._searchString does not match form history response");
+ return;
+ }
+ let fhEntries = [];
+ for (let i = 0; i < result.matchCount; ++i) {
+ fhEntries.push(result.getValueAt(i));
+ }
+ deferredFormHistory.resolve({
+ result: fhEntries,
+ formHistoryResult: result,
+ });
+ break;
+ case Ci.nsIAutoCompleteResult.RESULT_FAILURE:
+ case Ci.nsIAutoCompleteResult.RESULT_IGNORED:
+ deferredFormHistory.resolve("Form History returned RESULT_FAILURE or RESULT_IGNORED");
+ break;
+ }
+ },
+ };
+
+ let formHistory = Cc["@mozilla.org/autocomplete/search;1?name=form-history"].
+ createInstance(Ci.nsIAutoCompleteSearch);
+ formHistory.startSearch(searchTerm, this.formHistoryParam || DEFAULT_FORM_HISTORY_PARAM,
+ this._formHistoryResult,
+ acSearchObserver);
+ return deferredFormHistory;
+ },
+
+ /**
+ * Fetch suggestions from the search engine over the network.
+ */
+ _fetchRemote: function(searchTerm, engine, privateMode, userContextId) {
+ let deferredResponse = Promise.defer();
+ this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
+ createInstance(Ci.nsIXMLHttpRequest);
+ let submission = engine.getSubmission(searchTerm,
+ SEARCH_RESPONSE_SUGGESTION_JSON);
+ let method = (submission.postData ? "POST" : "GET");
+ this._request.open(method, submission.uri.spec, true);
+
+ this._request.setOriginAttributes({userContextId,
+ privateBrowsingId: privateMode ? 1 : 0});
+
+ this._request.mozBackgroundRequest = true; // suppress dialogs and fail silently
+
+ this._request.addEventListener("load", this._onRemoteLoaded.bind(this, deferredResponse));
+ this._request.addEventListener("error", (evt) => deferredResponse.resolve("HTTP error"));
+ // Reject for an abort assuming it's always from .stop() in which case we shouldn't return local
+ // or remote results for existing searches.
+ this._request.addEventListener("abort", (evt) => deferredResponse.reject("HTTP request aborted"));
+
+ this._request.send(submission.postData);
+
+ return deferredResponse;
+ },
+
+ /**
+ * Called when the request completed successfully (thought the HTTP status could be anything)
+ * so we can handle the response data.
+ * @private
+ */
+ _onRemoteLoaded: function(deferredResponse) {
+ if (!this._request) {
+ deferredResponse.resolve("Got HTTP response after the request was cancelled");
+ return;
+ }
+
+ let status, serverResults;
+ try {
+ status = this._request.status;
+ } catch (e) {
+ // The XMLHttpRequest can throw NS_ERROR_NOT_AVAILABLE.
+ deferredResponse.resolve("Unknown HTTP status: " + e);
+ return;
+ }
+
+ if (status != HTTP_OK || this._request.responseText == "") {
+ deferredResponse.resolve("Non-200 status or empty HTTP response: " + status);
+ return;
+ }
+
+ try {
+ serverResults = JSON.parse(this._request.responseText);
+ } catch (ex) {
+ deferredResponse.resolve("Failed to parse suggestion JSON: " + ex);
+ return;
+ }
+
+ if (!serverResults[0] ||
+ this._searchString.localeCompare(serverResults[0], undefined,
+ { sensitivity: "base" })) {
+ // something is wrong here so drop remote results
+ deferredResponse.resolve("Unexpected response, this._searchString does not match remote response");
+ return;
+ }
+ let results = serverResults[1] || [];
+ deferredResponse.resolve({ result: results });
+ },
+
+ /**
+ * Called when this._remoteResultTimer fires indicating the remote request took too long.
+ */
+ _onRemoteTimeout: function () {
+ this._request = null;
+
+ // FIXME: bug 387341
+ // Need to break the cycle between us and the timer.
+ this._remoteResultTimer = null;
+
+ // The XMLHTTPRequest for suggest results is taking too long
+ // so send out the form history results and cancel the request.
+ if (this._deferredRemoteResult) {
+ this._deferredRemoteResult.resolve("HTTP Timeout");
+ this._deferredRemoteResult = null;
+ }
+ },
+
+ /**
+ * @param {Array} suggestResults - an array of result objects from different sources (local or remote)
+ * @return {Object}
+ */
+ _dedupeAndReturnResults: function(suggestResults) {
+ if (this._searchString === null) {
+ // _searchString can be null if stop() was called and remote suggestions
+ // were disabled (stopping if we are fetching remote suggestions will
+ // cause a promise rejection before we reach _dedupeAndReturnResults).
+ return null;
+ }
+
+ let results = {
+ term: this._searchString,
+ remote: [],
+ local: [],
+ formHistoryResult: null,
+ };
+
+ for (let result of suggestResults) {
+ if (typeof result === "string") { // Failure message
+ Cu.reportError("SearchSuggestionController: " + result);
+ } else if (result.formHistoryResult) { // Local results have a formHistoryResult property.
+ results.formHistoryResult = result.formHistoryResult;
+ results.local = result.result || [];
+ } else { // Remote result
+ results.remote = result.result || [];
+ }
+ }
+
+ // If we have remote results, cap the number of local results
+ if (results.remote.length) {
+ results.local = results.local.slice(0, this.maxLocalResults);
+ }
+
+ // We don't want things to appear in both history and suggestions so remove entries from
+ // remote results that are already in local.
+ if (results.remote.length && results.local.length) {
+ for (let i = 0; i < results.local.length; ++i) {
+ let term = results.local[i];
+ let dupIndex = results.remote.indexOf(term);
+ if (dupIndex != -1) {
+ results.remote.splice(dupIndex, 1);
+ }
+ }
+ }
+
+ // Trim the number of results to the maximum requested (now that we've pruned dupes).
+ results.remote =
+ results.remote.slice(0, this.maxRemoteResults - results.local.length);
+
+ if (this._callback) {
+ this._callback(results);
+ }
+ this._reset();
+
+ return results;
+ },
+
+ _reset: function() {
+ this._request = null;
+ if (this._remoteResultTimer) {
+ this._remoteResultTimer.cancel();
+ this._remoteResultTimer = null;
+ }
+ this._deferredRemoteResult = null;
+ this._searchString = null;
+ },
+};
+
+/**
+ * Determines whether the given engine offers search suggestions.
+ *
+ * @param {nsISearchEngine} engine - The search engine
+ * @return {boolean} True if the engine offers suggestions and false otherwise.
+ */
+this.SearchSuggestionController.engineOffersSuggestions = function(engine) {
+ return engine.supportsResponseType(SEARCH_RESPONSE_SUGGESTION_JSON);
+};
diff --git a/application/basilisk/components/search/service/moz.build b/application/basilisk/components/search/service/moz.build
new file mode 100644
index 000000000..423faeffd
--- /dev/null
+++ b/application/basilisk/components/search/service/moz.build
@@ -0,0 +1,24 @@
+# -*- 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/.
+
+DIST_SUBDIR = ''
+
+DEFINES['HAVE_SIDEBAR'] = True
+
+EXTRA_COMPONENTS += [
+ 'nsSearchSuggestions.js',
+ 'nsSidebar.js',
+]
+
+EXTRA_PP_COMPONENTS += [
+ 'nsSearchService.js',
+ 'toolkitsearch.manifest',
+]
+
+EXTRA_JS_MODULES += [
+ 'SearchStaticData.jsm',
+ 'SearchSuggestionController.jsm',
+]
diff --git a/application/basilisk/components/search/service/nsSearchService.js b/application/basilisk/components/search/service/nsSearchService.js
new file mode 100644
index 000000000..b4db31dee
--- /dev/null
+++ b/application/basilisk/components/search/service/nsSearchService.js
@@ -0,0 +1,4324 @@
+/* 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/. */
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+const Cr = Components.results;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/debug.js");
+Cu.import("resource://gre/modules/AppConstants.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
+ "resource://gre/modules/AsyncShutdown.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
+ "resource://gre/modules/DeferredTask.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "OS",
+ "resource://gre/modules/osfile.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Task",
+ "resource://gre/modules/Task.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
+ "resource://gre/modules/Deprecated.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "SearchStaticData",
+ "resource://gre/modules/SearchStaticData.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
+ "resource://gre/modules/Timer.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "clearTimeout",
+ "resource://gre/modules/Timer.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Lz4",
+ "resource://gre/modules/lz4.js");
+
+XPCOMUtils.defineLazyServiceGetter(this, "gTextToSubURI",
+ "@mozilla.org/intl/texttosuburi;1",
+ "nsITextToSubURI");
+XPCOMUtils.defineLazyServiceGetter(this, "gEnvironment",
+ "@mozilla.org/process/environment;1",
+ "nsIEnvironment");
+
+Cu.importGlobalProperties(["XMLHttpRequest"]);
+
+// A text encoder to UTF8, used whenever we commit the cache to disk.
+XPCOMUtils.defineLazyGetter(this, "gEncoder",
+ function() {
+ return new TextEncoder();
+ });
+
+const MODE_RDONLY = 0x01;
+const MODE_WRONLY = 0x02;
+const MODE_CREATE = 0x08;
+const MODE_APPEND = 0x10;
+const MODE_TRUNCATE = 0x20;
+
+// Directory service keys
+const NS_APP_SEARCH_DIR_LIST = "SrchPluginsDL";
+const NS_APP_DISTRIBUTION_SEARCH_DIR_LIST = "SrchPluginsDistDL";
+const NS_APP_USER_SEARCH_DIR = "UsrSrchPlugns";
+const NS_APP_SEARCH_DIR = "SrchPlugns";
+const NS_APP_USER_PROFILE_50_DIR = "ProfD";
+
+// Loading plugins from NS_APP_SEARCH_DIR is no longer supported.
+// Instead, we now load plugins from APP_SEARCH_PREFIX, where a
+// list.txt file needs to exist to list available engines.
+const APP_SEARCH_PREFIX = "resource://search-plugins/";
+
+// See documentation in nsIBrowserSearchService.idl.
+const SEARCH_ENGINE_TOPIC = "browser-search-engine-modified";
+const QUIT_APPLICATION_TOPIC = "quit-application";
+
+const SEARCH_ENGINE_REMOVED = "engine-removed";
+const SEARCH_ENGINE_ADDED = "engine-added";
+const SEARCH_ENGINE_CHANGED = "engine-changed";
+const SEARCH_ENGINE_LOADED = "engine-loaded";
+const SEARCH_ENGINE_CURRENT = "engine-current";
+const SEARCH_ENGINE_DEFAULT = "engine-default";
+
+// The following constants are left undocumented in nsIBrowserSearchService.idl
+// For the moment, they are meant for testing/debugging purposes only.
+
+/**
+ * Topic used for events involving the service itself.
+ */
+const SEARCH_SERVICE_TOPIC = "browser-search-service";
+
+/**
+ * Sent whenever the cache is fully written to disk.
+ */
+const SEARCH_SERVICE_CACHE_WRITTEN = "write-cache-to-disk-complete";
+
+// Delay for lazy serialization (ms)
+const LAZY_SERIALIZE_DELAY = 100;
+
+// Delay for batching invalidation of the JSON cache (ms)
+const CACHE_INVALIDATION_DELAY = 1000;
+
+// Current cache version. This should be incremented if the format of the cache
+// file is modified.
+const CACHE_VERSION = 1;
+
+const CACHE_FILENAME = "search.json.mozlz4";
+
+const NEW_LINES = /(\r\n|\r|\n)/;
+
+// Set an arbitrary cap on the maximum icon size. Without this, large icons can
+// cause big delays when loading them at startup.
+const MAX_ICON_SIZE = 32768;
+
+// Default charset to use for sending search parameters. ISO-8859-1 is used to
+// match previous nsInternetSearchService behavior.
+const DEFAULT_QUERY_CHARSET = "ISO-8859-1";
+
+const SEARCH_BUNDLE = "chrome://global/locale/search/search.properties";
+const BRAND_BUNDLE = "chrome://branding/locale/brand.properties";
+
+const OPENSEARCH_NS_10 = "http://a9.com/-/spec/opensearch/1.0/";
+const OPENSEARCH_NS_11 = "http://a9.com/-/spec/opensearch/1.1/";
+
+// Although the specification at http://opensearch.a9.com/spec/1.1/description/
+// gives the namespace names defined above, many existing OpenSearch engines
+// are using the following versions. We therefore allow either.
+const OPENSEARCH_NAMESPACES = [
+ OPENSEARCH_NS_11, OPENSEARCH_NS_10,
+ "http://a9.com/-/spec/opensearchdescription/1.1/",
+ "http://a9.com/-/spec/opensearchdescription/1.0/"
+];
+
+const OPENSEARCH_LOCALNAME = "OpenSearchDescription";
+
+const MOZSEARCH_NS_10 = "http://www.mozilla.org/2006/browser/search/";
+const MOZSEARCH_LOCALNAME = "SearchPlugin";
+
+const URLTYPE_SUGGEST_JSON = "application/x-suggestions+json";
+const URLTYPE_SEARCH_HTML = "text/html";
+const URLTYPE_OPENSEARCH = "application/opensearchdescription+xml";
+
+const BROWSER_SEARCH_PREF = "browser.search.";
+const LOCALE_PREF = "general.useragent.locale";
+
+const USER_DEFINED = "{searchTerms}";
+
+// Custom search parameters
+const MOZ_OFFICIAL = AppConstants.MOZ_OFFICIAL_BRANDING ? "official" : "unofficial";
+
+const MOZ_PARAM_LOCALE = /\{moz:locale\}/g;
+const MOZ_PARAM_DIST_ID = /\{moz:distributionID\}/g;
+const MOZ_PARAM_OFFICIAL = /\{moz:official\}/g;
+
+// Supported OpenSearch parameters
+// See http://opensearch.a9.com/spec/1.1/querysyntax/#core
+const OS_PARAM_USER_DEFINED = /\{searchTerms\??\}/g;
+const OS_PARAM_INPUT_ENCODING = /\{inputEncoding\??\}/g;
+const OS_PARAM_LANGUAGE = /\{language\??\}/g;
+const OS_PARAM_OUTPUT_ENCODING = /\{outputEncoding\??\}/g;
+
+// Default values
+const OS_PARAM_LANGUAGE_DEF = "*";
+const OS_PARAM_OUTPUT_ENCODING_DEF = "UTF-8";
+const OS_PARAM_INPUT_ENCODING_DEF = "UTF-8";
+
+// "Unsupported" OpenSearch parameters. For example, we don't support
+// page-based results, so if the engine requires that we send the "page index"
+// parameter, we'll always send "1".
+const OS_PARAM_COUNT = /\{count\??\}/g;
+const OS_PARAM_START_INDEX = /\{startIndex\??\}/g;
+const OS_PARAM_START_PAGE = /\{startPage\??\}/g;
+
+// Default values
+const OS_PARAM_COUNT_DEF = "20"; // 20 results
+const OS_PARAM_START_INDEX_DEF = "1"; // start at 1st result
+const OS_PARAM_START_PAGE_DEF = "1"; // 1st page
+
+// Optional parameter
+const OS_PARAM_OPTIONAL = /\{(?:\w+:)?\w+\?\}/g;
+
+// A array of arrays containing parameters that we don't fully support, and
+// their default values. We will only send values for these parameters if
+// required, since our values are just really arbitrary "guesses" that should
+// give us the output we want.
+var OS_UNSUPPORTED_PARAMS = [
+ [OS_PARAM_COUNT, OS_PARAM_COUNT_DEF],
+ [OS_PARAM_START_INDEX, OS_PARAM_START_INDEX_DEF],
+ [OS_PARAM_START_PAGE, OS_PARAM_START_PAGE_DEF],
+];
+
+// The default engine update interval, in days. This is only used if an engine
+// specifies an updateURL, but not an updateInterval.
+const SEARCH_DEFAULT_UPDATE_INTERVAL = 7;
+
+// The default interval before checking again for the name of the
+// default engine for the region, in seconds. Only used if the response
+// from the server doesn't specify an interval.
+const SEARCH_GEO_DEFAULT_UPDATE_INTERVAL = 2592000; // 30 days.
+
+this.__defineGetter__("FileUtils", function() {
+ delete this.FileUtils;
+ Components.utils.import("resource://gre/modules/FileUtils.jsm");
+ return FileUtils;
+});
+
+this.__defineGetter__("NetUtil", function() {
+ delete this.NetUtil;
+ Components.utils.import("resource://gre/modules/NetUtil.jsm");
+ return NetUtil;
+});
+
+this.__defineGetter__("gChromeReg", function() {
+ delete this.gChromeReg;
+ return this.gChromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
+ getService(Ci.nsIChromeRegistry);
+});
+
+/**
+ * Prefixed to all search debug output.
+ */
+const SEARCH_LOG_PREFIX = "*** Search: ";
+
+/**
+ * Outputs aText to the JavaScript console as well as to stdout.
+ */
+function DO_LOG(aText) {
+ dump(SEARCH_LOG_PREFIX + aText + "\n");
+ Services.console.logStringMessage(aText);
+}
+
+/**
+ * In debug builds, use a live, pref-based (browser.search.log) LOG function
+ * to allow enabling/disabling without a restart. Otherwise, don't log at all by
+ * default. This can be overridden at startup by the pref, see SearchService's
+ * _init method.
+ */
+var LOG = function() {};
+
+if (AppConstants.DEBUG) {
+ LOG = function (aText) {
+ if (Services.prefs.getBoolPref(BROWSER_SEARCH_PREF + "log", false)) {
+ DO_LOG(aText);
+ }
+ };
+}
+
+/**
+ * Presents an assertion dialog in non-release builds and throws.
+ * @param message
+ * A message to display
+ * @param resultCode
+ * The NS_ERROR_* value to throw.
+ * @throws resultCode
+ */
+function ERROR(message, resultCode) {
+ NS_ASSERT(false, SEARCH_LOG_PREFIX + message);
+ throw Components.Exception(message, resultCode);
+}
+
+/**
+ * Logs the failure message (if browser.search.log is enabled) and throws.
+ * @param message
+ * A message to display
+ * @param resultCode
+ * The NS_ERROR_* value to throw.
+ * @throws resultCode or NS_ERROR_INVALID_ARG if resultCode isn't specified.
+ */
+function FAIL(message, resultCode) {
+ LOG(message);
+ throw Components.Exception(message, resultCode || Cr.NS_ERROR_INVALID_ARG);
+}
+
+/**
+ * Truncates big blobs of (data-)URIs to console-friendly sizes
+ * @param str
+ * String to tone down
+ * @param len
+ * Maximum length of the string to return. Defaults to the length of a tweet.
+ */
+function limitURILength(str, len) {
+ len = len || 140;
+ if (str.length > len)
+ return str.slice(0, len) + "...";
+ return str;
+}
+
+/**
+ * Ensures an assertion is met before continuing. Should be used to indicate
+ * fatal errors.
+ * @param assertion
+ * An assertion that must be met
+ * @param message
+ * A message to display if the assertion is not met
+ * @param resultCode
+ * The NS_ERROR_* value to throw if the assertion is not met
+ * @throws resultCode
+ */
+function ENSURE_WARN(assertion, message, resultCode) {
+ NS_ASSERT(assertion, SEARCH_LOG_PREFIX + message);
+ if (!assertion)
+ throw Components.Exception(message, resultCode);
+}
+
+function loadListener(aChannel, aEngine, aCallback) {
+ this._channel = aChannel;
+ this._bytes = [];
+ this._engine = aEngine;
+ this._callback = aCallback;
+}
+loadListener.prototype = {
+ _callback: null,
+ _channel: null,
+ _countRead: 0,
+ _engine: null,
+ _stream: null,
+
+ QueryInterface: XPCOMUtils.generateQI([
+ Ci.nsIRequestObserver,
+ Ci.nsIStreamListener,
+ Ci.nsIChannelEventSink,
+ Ci.nsIInterfaceRequestor,
+ // See FIXME comment below.
+ Ci.nsIHttpEventSink,
+ Ci.nsIProgressEventSink
+ ]),
+
+ // nsIRequestObserver
+ onStartRequest: function SRCH_loadStartR(aRequest, aContext) {
+ LOG("loadListener: Starting request: " + aRequest.name);
+ this._stream = Cc["@mozilla.org/binaryinputstream;1"].
+ createInstance(Ci.nsIBinaryInputStream);
+ },
+
+ onStopRequest: function SRCH_loadStopR(aRequest, aContext, aStatusCode) {
+ LOG("loadListener: Stopping request: " + aRequest.name);
+
+ var requestFailed = !Components.isSuccessCode(aStatusCode);
+ if (!requestFailed && (aRequest instanceof Ci.nsIHttpChannel))
+ requestFailed = !aRequest.requestSucceeded;
+
+ if (requestFailed || this._countRead == 0) {
+ LOG("loadListener: request failed!");
+ // send null so the callback can deal with the failure
+ this._callback(null, this._engine);
+ } else
+ this._callback(this._bytes, this._engine);
+ this._channel = null;
+ this._engine = null;
+ },
+
+ // nsIStreamListener
+ onDataAvailable: function SRCH_loadDAvailable(aRequest, aContext,
+ aInputStream, aOffset,
+ aCount) {
+ this._stream.setInputStream(aInputStream);
+
+ // Get a byte array of the data
+ this._bytes = this._bytes.concat(this._stream.readByteArray(aCount));
+ this._countRead += aCount;
+ },
+
+ // nsIChannelEventSink
+ asyncOnChannelRedirect: function SRCH_loadCRedirect(aOldChannel, aNewChannel,
+ aFlags, callback) {
+ this._channel = aNewChannel;
+ callback.onRedirectVerifyCallback(Components.results.NS_OK);
+ },
+
+ // nsIInterfaceRequestor
+ getInterface: function SRCH_load_GI(aIID) {
+ return this.QueryInterface(aIID);
+ },
+
+ // FIXME: bug 253127
+ // nsIHttpEventSink
+ onRedirect: function (aChannel, aNewChannel) {},
+ // nsIProgressEventSink
+ onProgress: function (aRequest, aContext, aProgress, aProgressMax) {},
+ onStatus: function (aRequest, aContext, aStatus, aStatusArg) {}
+}
+
+function isPartnerBuild() {
+ try {
+ let distroID = Services.prefs.getCharPref("distribution.id");
+
+ // Mozilla-provided builds (i.e. funnelcake) are not partner builds
+ if (distroID && !distroID.startsWith("mozilla")) {
+ return true;
+ }
+ } catch (e) {}
+
+ return false;
+}
+
+function getVerificationHash(aName) {
+ let disclaimer = "By modifying this file, I agree that I am doing so " +
+ "only within $appName itself, using official, user-driven search " +
+ "engine selection processes, and in a way which does not circumvent " +
+ "user consent. I acknowledge that any attempt to change this file " +
+ "from outside of $appName is a malicious act, and will be responded " +
+ "to accordingly."
+
+ let salt = OS.Path.basename(OS.Constants.Path.profileDir) + aName +
+ disclaimer.replace(/\$appName/g, Services.appinfo.name);
+
+ let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+ .createInstance(Ci.nsIScriptableUnicodeConverter);
+ converter.charset = "UTF-8";
+
+ // Data is an array of bytes.
+ let data = converter.convertToByteArray(salt, {});
+ let hasher = Cc["@mozilla.org/security/hash;1"]
+ .createInstance(Ci.nsICryptoHash);
+ hasher.init(hasher.SHA256);
+ hasher.update(data, data.length);
+
+ return hasher.finish(true);
+}
+
+/**
+ * Safely close a nsISafeOutputStream.
+ * @param aFOS
+ * The file output stream to close.
+ */
+function closeSafeOutputStream(aFOS) {
+ if (aFOS instanceof Ci.nsISafeOutputStream) {
+ try {
+ aFOS.finish();
+ return;
+ } catch (e) { }
+ }
+ aFOS.close();
+}
+
+/**
+ * Wrapper function for nsIIOService::newURI.
+ * @param aURLSpec
+ * The URL string from which to create an nsIURI.
+ * @returns an nsIURI object, or null if the creation of the URI failed.
+ */
+function makeURI(aURLSpec, aCharset) {
+ try {
+ return NetUtil.newURI(aURLSpec, aCharset);
+ } catch (ex) { }
+
+ return null;
+}
+
+/**
+ * Wrapper function for nsIIOService::newChannel2.
+ * @param url
+ * The URL string from which to create an nsIChannel.
+ * @returns an nsIChannel object, or null if the url is invalid.
+ */
+function makeChannel(url) {
+ try {
+ return NetUtil.newChannel({
+ uri: url,
+ loadUsingSystemPrincipal: true
+ });
+ } catch (ex) { }
+
+ return null;
+}
+
+/**
+ * Gets a directory from the directory service.
+ * @param aKey
+ * The directory service key indicating the directory to get.
+ */
+function getDir(aKey, aIFace) {
+ if (!aKey)
+ FAIL("getDir requires a directory key!");
+
+ return Services.dirsvc.get(aKey, aIFace || Ci.nsIFile);
+}
+
+/**
+ * Gets the current value of the locale. It's possible for this preference to
+ * be localized, so we have to do a little extra work here. Similar code
+ * exists in nsHttpHandler.cpp when building the UA string.
+ */
+function getLocale() {
+ let locale = getLocalizedPref(LOCALE_PREF);
+ if (locale)
+ return locale;
+
+ // Not localized.
+ return Services.prefs.getCharPref(LOCALE_PREF);
+}
+
+/**
+ * Wrapper for nsIPrefBranch::getComplexValue.
+ * @param aPrefName
+ * The name of the pref to get.
+ * @returns aDefault if the requested pref doesn't exist.
+ */
+function getLocalizedPref(aPrefName, aDefault) {
+ const nsIPLS = Ci.nsIPrefLocalizedString;
+ try {
+ return Services.prefs.getComplexValue(aPrefName, nsIPLS).data;
+ } catch (ex) {}
+
+ return aDefault;
+}
+
+/**
+ * @return a sanitized name to be used as a filename, or a random name
+ * if a sanitized name cannot be obtained (if aName contains
+ * no valid characters).
+ */
+function sanitizeName(aName) {
+ const maxLength = 60;
+ const minLength = 1;
+ var name = aName.toLowerCase();
+ name = name.replace(/\s+/g, "-");
+ name = name.replace(/[^-a-z0-9]/g, "");
+
+ // Use a random name if our input had no valid characters.
+ if (name.length < minLength)
+ name = Math.random().toString(36).replace(/^.*\./, '');
+
+ // Force max length.
+ return name.substring(0, maxLength);
+}
+
+/**
+ * Retrieve a pref from the search param branch.
+ *
+ * @param prefName
+ * The name of the pref.
+ **/
+function getMozParamPref(prefName) {
+ let branch = Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF + "param.");
+ return encodeURIComponent(branch.getCharPref(prefName));
+}
+
+/**
+ * Notifies watchers of SEARCH_ENGINE_TOPIC about changes to an engine or to
+ * the state of the search service.
+ *
+ * @param aEngine
+ * The nsISearchEngine object to which the change applies.
+ * @param aVerb
+ * A verb describing the change.
+ *
+ * @see nsIBrowserSearchService.idl
+ */
+var gInitialized = false;
+function notifyAction(aEngine, aVerb) {
+ if (gInitialized) {
+ LOG("NOTIFY: Engine: \"" + aEngine.name + "\"; Verb: \"" + aVerb + "\"");
+ Services.obs.notifyObservers(aEngine, SEARCH_ENGINE_TOPIC, aVerb);
+ }
+}
+
+function parseJsonFromStream(aInputStream) {
+ const json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
+ const data = json.decodeFromStream(aInputStream, aInputStream.available());
+ return data;
+}
+
+/**
+ * Simple object representing a name/value pair.
+ */
+function QueryParameter(aName, aValue, aPurpose) {
+ if (!aName || (aValue == null))
+ FAIL("missing name or value for QueryParameter!");
+
+ this.name = aName;
+ this.value = aValue;
+ this.purpose = aPurpose;
+}
+
+/**
+ * Perform OpenSearch parameter substitution on aParamValue.
+ *
+ * @param aParamValue
+ * A string containing OpenSearch search parameters.
+ * @param aSearchTerms
+ * The user-provided search terms. This string will inserted into
+ * aParamValue as the value of the OS_PARAM_USER_DEFINED parameter.
+ * This value must already be escaped appropriately - it is inserted
+ * as-is.
+ * @param aEngine
+ * The engine which owns the string being acted on.
+ *
+ * @see http://opensearch.a9.com/spec/1.1/querysyntax/#core
+ */
+function ParamSubstitution(aParamValue, aSearchTerms, aEngine) {
+ var value = aParamValue;
+
+ var distributionID = Services.prefs.getCharPref(BROWSER_SEARCH_PREF + "distributionID",
+ Services.appinfo.distributionID || "");
+ var official = MOZ_OFFICIAL;
+ try {
+ if (Services.prefs.getBoolPref(BROWSER_SEARCH_PREF + "official"))
+ official = "official";
+ else
+ official = "unofficial";
+ }
+ catch (ex) { }
+
+ // Custom search parameters. These are only available to default search
+ // engines.
+ if (aEngine._isDefault) {
+ value = value.replace(MOZ_PARAM_LOCALE, getLocale());
+ value = value.replace(MOZ_PARAM_DIST_ID, distributionID);
+ value = value.replace(MOZ_PARAM_OFFICIAL, official);
+ }
+
+ // Insert the OpenSearch parameters we're confident about
+ value = value.replace(OS_PARAM_USER_DEFINED, aSearchTerms);
+ value = value.replace(OS_PARAM_INPUT_ENCODING, aEngine.queryCharset);
+ value = value.replace(OS_PARAM_LANGUAGE,
+ getLocale() || OS_PARAM_LANGUAGE_DEF);
+ value = value.replace(OS_PARAM_OUTPUT_ENCODING,
+ OS_PARAM_OUTPUT_ENCODING_DEF);
+
+ // Replace any optional parameters
+ value = value.replace(OS_PARAM_OPTIONAL, "");
+
+ // Insert any remaining required params with our default values
+ for (var i = 0; i < OS_UNSUPPORTED_PARAMS.length; ++i) {
+ value = value.replace(OS_UNSUPPORTED_PARAMS[i][0],
+ OS_UNSUPPORTED_PARAMS[i][1]);
+ }
+
+ return value;
+}
+
+/**
+ * Creates an engineURL object, which holds the query URL and all parameters.
+ *
+ * @param aType
+ * A string containing the name of the MIME type of the search results
+ * returned by this URL.
+ * @param aMethod
+ * The HTTP request method. Must be a case insensitive value of either
+ * "GET" or "POST".
+ * @param aTemplate
+ * The URL to which search queries should be sent. For GET requests,
+ * must contain the string "{searchTerms}", to indicate where the user
+ * entered search terms should be inserted.
+ * @param aResultDomain
+ * The root domain for this URL. Defaults to the template's host.
+ *
+ * @see http://opensearch.a9.com/spec/1.1/querysyntax/#urltag
+ *
+ * @throws NS_ERROR_NOT_IMPLEMENTED if aType is unsupported.
+ */
+function EngineURL(aType, aMethod, aTemplate, aResultDomain) {
+ if (!aType || !aMethod || !aTemplate)
+ FAIL("missing type, method or template for EngineURL!");
+
+ var method = aMethod.toUpperCase();
+ var type = aType.toLowerCase();
+
+ if (method != "GET" && method != "POST")
+ FAIL("method passed to EngineURL must be \"GET\" or \"POST\"");
+
+ this.type = type;
+ this.method = method;
+ this.params = [];
+ this.rels = [];
+ // Don't serialize expanded mozparams
+ this.mozparams = {};
+
+ var templateURI = makeURI(aTemplate);
+ if (!templateURI)
+ FAIL("new EngineURL: template is not a valid URI!", Cr.NS_ERROR_FAILURE);
+
+ switch (templateURI.scheme) {
+ case "http":
+ case "https":
+ // Disable these for now, see bug 295018
+ // case "file":
+ // case "resource":
+ this.template = aTemplate;
+ break;
+ default:
+ FAIL("new EngineURL: template uses invalid scheme!", Cr.NS_ERROR_FAILURE);
+ }
+
+ // If no resultDomain was specified in the engine definition file, use the
+ // host from the template.
+ this.resultDomain = aResultDomain || templateURI.host;
+ // We never want to return a "www." prefix, so eventually strip it.
+ if (this.resultDomain.startsWith("www.")) {
+ this.resultDomain = this.resultDomain.substr(4);
+ }
+}
+EngineURL.prototype = {
+
+ addParam: function SRCH_EURL_addParam(aName, aValue, aPurpose) {
+ this.params.push(new QueryParameter(aName, aValue, aPurpose));
+ },
+
+ // Note: This method requires that aObj has a unique name or the previous MozParams entry with
+ // that name will be overwritten.
+ _addMozParam: function SRCH_EURL__addMozParam(aObj) {
+ aObj.mozparam = true;
+ this.mozparams[aObj.name] = aObj;
+ },
+
+ getSubmission: function SRCH_EURL_getSubmission(aSearchTerms, aEngine, aPurpose) {
+ var url = ParamSubstitution(this.template, aSearchTerms, aEngine);
+ // Default to searchbar if the purpose is not provided
+ var purpose = aPurpose || "searchbar";
+
+ // If a particular purpose isn't defined in the plugin, fallback to 'searchbar'.
+ if (!this.params.some(p => p.purpose !== undefined && p.purpose == purpose))
+ purpose = "searchbar";
+
+ // Create an application/x-www-form-urlencoded representation of our params
+ // (name=value&name=value&name=value)
+ var dataString = "";
+ for (var i = 0; i < this.params.length; ++i) {
+ var param = this.params[i];
+
+ // If this parameter has a purpose, only add it if the purpose matches
+ if (param.purpose !== undefined && param.purpose != purpose)
+ continue;
+
+ var value = ParamSubstitution(param.value, aSearchTerms, aEngine);
+
+ dataString += (i > 0 ? "&" : "") + param.name + "=" + value;
+ }
+
+ var postData = null;
+ if (this.method == "GET") {
+ // GET method requests have no post data, and append the encoded
+ // query string to the url...
+ if (url.indexOf("?") == -1 && dataString)
+ url += "?";
+ url += dataString;
+ } else if (this.method == "POST") {
+ // POST method requests must wrap the encoded text in a MIME
+ // stream and supply that as POSTDATA.
+ var stringStream = Cc["@mozilla.org/io/string-input-stream;1"].
+ createInstance(Ci.nsIStringInputStream);
+ stringStream.data = dataString;
+
+ postData = Cc["@mozilla.org/network/mime-input-stream;1"].
+ createInstance(Ci.nsIMIMEInputStream);
+ postData.addHeader("Content-Type", "application/x-www-form-urlencoded");
+ postData.addContentLength = true;
+ postData.setData(stringStream);
+ }
+
+ return new Submission(makeURI(url), postData);
+ },
+
+ _getTermsParameterName: function SRCH_EURL__getTermsParameterName() {
+ let queryParam = this.params.find(p => p.value == USER_DEFINED);
+ return queryParam ? queryParam.name : "";
+ },
+
+ _hasRelation: function SRC_EURL__hasRelation(aRel) {
+ return this.rels.some(e => e == aRel.toLowerCase());
+ },
+
+ _initWithJSON: function SRC_EURL__initWithJSON(aJson, aEngine) {
+ if (!aJson.params)
+ return;
+
+ this.rels = aJson.rels;
+
+ for (let i = 0; i < aJson.params.length; ++i) {
+ let param = aJson.params[i];
+ if (param.mozparam) {
+ if (param.condition == "pref") {
+ let value = getMozParamPref(param.pref);
+ this.addParam(param.name, value);
+ }
+ this._addMozParam(param);
+ }
+ else
+ this.addParam(param.name, param.value, param.purpose || undefined);
+ }
+ },
+
+ /**
+ * Creates a JavaScript object that represents this URL.
+ * @returns An object suitable for serialization as JSON.
+ **/
+ toJSON: function SRCH_EURL_toJSON() {
+ var json = {
+ template: this.template,
+ rels: this.rels,
+ resultDomain: this.resultDomain
+ };
+
+ if (this.type != URLTYPE_SEARCH_HTML)
+ json.type = this.type;
+ if (this.method != "GET")
+ json.method = this.method;
+
+ function collapseMozParams(aParam) {
+ return this.mozparams[aParam.name] || aParam;
+ }
+ json.params = this.params.map(collapseMozParams, this);
+
+ return json;
+ }
+};
+
+/**
+ * nsISearchEngine constructor.
+ * @param aLocation
+ * A nsILocalFile or nsIURI object representing the location of the
+ * search engine data file.
+ * @param aIsReadOnly
+ * Boolean indicating whether the engine should be treated as read-only.
+ */
+function Engine(aLocation, aIsReadOnly) {
+ this._readOnly = aIsReadOnly;
+ this._urls = [];
+ this._metaData = {};
+
+ let file, uri;
+ if (typeof aLocation == "string") {
+ this._shortName = aLocation;
+ } else if (aLocation instanceof Ci.nsILocalFile) {
+ if (!aIsReadOnly) {
+ // This is an engine that was installed in NS_APP_USER_SEARCH_DIR by a
+ // previous version. We are converting the file to an engine stored only
+ // in JSON, but we need to keep the reference to the profile file to
+ // remove it if the user ever removes the engine.
+ this._filePath = aLocation.persistentDescriptor;
+ }
+ file = aLocation;
+ } else if (aLocation instanceof Ci.nsIURI) {
+ switch (aLocation.scheme) {
+ case "https":
+ case "http":
+ case "ftp":
+ case "data":
+ case "file":
+ case "resource":
+ case "chrome":
+ uri = aLocation;
+ break;
+ default:
+ ERROR("Invalid URI passed to the nsISearchEngine constructor",
+ Cr.NS_ERROR_INVALID_ARG);
+ }
+ } else
+ ERROR("Engine location is neither a File nor a URI object",
+ Cr.NS_ERROR_INVALID_ARG);
+
+ if (!this._shortName) {
+ // If we don't have a shortName at this point, it's the first time we load
+ // this engine, so let's generate the shortName, id and loadPath values.
+ let shortName;
+ if (file) {
+ shortName = file.leafName;
+ }
+ else if (uri && uri instanceof Ci.nsIURL) {
+ if (aIsReadOnly || (gEnvironment.get("XPCSHELL_TEST_PROFILE_DIR") &&
+ uri.scheme == "resource")) {
+ shortName = uri.fileName;
+ }
+ }
+ if (shortName && shortName.endsWith(".xml")) {
+ this._shortName = shortName.slice(0, -4);
+ }
+ this._loadPath = this.getAnonymizedLoadPath(file, uri);
+
+ if (!shortName && !aIsReadOnly) {
+ // We are in the process of downloading and installing the engine.
+ // We'll have the shortName and id once we are done parsing it.
+ return;
+ }
+
+ // Build the id used for the legacy metadata storage, so that we
+ // can do a one-time import of data from old profiles.
+ if (this._isDefault ||
+ (uri && uri.spec.startsWith(APP_SEARCH_PREFIX))) {
+ // The second part of the check is to catch engines from language packs.
+ // They aren't default engines (because they aren't app-shipped), but we
+ // still need to give their id an [app] prefix for backward compat.
+ this._id = "[app]/" + this._shortName + ".xml";
+ }
+ else if (!aIsReadOnly) {
+ this._id = "[profile]/" + this._shortName + ".xml";
+ }
+ else {
+ // If the engine is neither a default one, nor a user-installed one,
+ // it must be extension-shipped, so use the full path as id.
+ LOG("Setting _id to full path for engine from " + this._loadPath);
+ this._id = file ? file.path : uri.spec;
+ }
+ }
+}
+
+Engine.prototype = {
+ // Data set by the user.
+ _metaData: null,
+ // The data describing the engine, in the form of an XML document element.
+ _data: null,
+ // Whether or not the engine is readonly.
+ _readOnly: true,
+ // Anonymized path of where we initially loaded the engine from.
+ // This will stay null for engines installed in the profile before we moved
+ // to a JSON storage.
+ _loadPath: null,
+ // The engine's description
+ _description: "",
+ // Used to store the engine to replace, if we're an update to an existing
+ // engine.
+ _engineToUpdate: null,
+ // Set to true if the engine has a preferred icon (an icon that should not be
+ // overridden by a non-preferred icon).
+ _hasPreferredIcon: null,
+ // The engine's name.
+ _name: null,
+ // The name of the charset used to submit the search terms.
+ _queryCharset: null,
+ // The engine's raw SearchForm value (URL string pointing to a search form).
+ __searchForm: null,
+ get _searchForm() {
+ return this.__searchForm;
+ },
+ set _searchForm(aValue) {
+ if (/^https?:/i.test(aValue))
+ this.__searchForm = aValue;
+ else
+ LOG("_searchForm: Invalid URL dropped for " + this._name ||
+ "the current engine");
+ },
+ // Whether to obtain user confirmation before adding the engine. This is only
+ // used when the engine is first added to the list.
+ _confirm: false,
+ // Whether to set this as the current engine as soon as it is loaded. This
+ // is only used when the engine is first added to the list.
+ _useNow: false,
+ // A function to be invoked when this engine object's addition completes (or
+ // fails). Only used for installation via addEngine.
+ _installCallback: null,
+ // The number of days between update checks for new versions
+ _updateInterval: null,
+ // The url to check at for a new update
+ _updateURL: null,
+ // The url to check for a new icon
+ _iconUpdateURL: null,
+ /* The extension ID if added by an extension. */
+ _extensionID: null,
+
+ /**
+ * Retrieves the data from the engine's file.
+ * The document element is placed in the engine's data field.
+ */
+ _initFromFile: function SRCH_ENG_initFromFile(file) {
+ if (!file || !file.exists())
+ FAIL("File must exist before calling initFromFile!", Cr.NS_ERROR_UNEXPECTED);
+
+ var fileInStream = Cc["@mozilla.org/network/file-input-stream;1"].
+ createInstance(Ci.nsIFileInputStream);
+
+ fileInStream.init(file, MODE_RDONLY, FileUtils.PERMS_FILE, false);
+
+ var domParser = Cc["@mozilla.org/xmlextras/domparser;1"].
+ createInstance(Ci.nsIDOMParser);
+ var doc = domParser.parseFromStream(fileInStream, "UTF-8",
+ file.fileSize,
+ "text/xml");
+
+ this._data = doc.documentElement;
+ fileInStream.close();
+
+ // Now that the data is loaded, initialize the engine object
+ this._initFromData();
+ },
+
+ /**
+ * Retrieves the data from the engine's file asynchronously.
+ * The document element is placed in the engine's data field.
+ *
+ * @param file The file to load the search plugin from.
+ *
+ * @returns {Promise} A promise, resolved successfully if initializing from
+ * data succeeds, rejected if it fails.
+ */
+ _asyncInitFromFile: Task.async(function* (file) {
+ if (!file || !(yield OS.File.exists(file.path)))
+ FAIL("File must exist before calling initFromFile!", Cr.NS_ERROR_UNEXPECTED);
+
+ let fileURI = NetUtil.ioService.newFileURI(file);
+ yield this._retrieveSearchXMLData(fileURI.spec);
+
+ // Now that the data is loaded, initialize the engine object
+ this._initFromData();
+ }),
+
+ /**
+ * Retrieves the engine data from a URI. Initializes the engine, flushes to
+ * disk, and notifies the search service once initialization is complete.
+ *
+ * @param uri The uri to load the search plugin from.
+ */
+ _initFromURIAndLoad: function SRCH_ENG_initFromURIAndLoad(uri) {
+ ENSURE_WARN(uri instanceof Ci.nsIURI,
+ "Must have URI when calling _initFromURIAndLoad!",
+ Cr.NS_ERROR_UNEXPECTED);
+
+ LOG("_initFromURIAndLoad: Downloading engine from: \"" + uri.spec + "\".");
+
+ var chan = NetUtil.newChannel({
+ uri: uri,
+ loadUsingSystemPrincipal: true
+ });
+
+ if (this._engineToUpdate && (chan instanceof Ci.nsIHttpChannel)) {
+ var lastModified = this._engineToUpdate.getAttr("updatelastmodified");
+ if (lastModified)
+ chan.setRequestHeader("If-Modified-Since", lastModified, false);
+ }
+ this._uri = uri;
+ var listener = new loadListener(chan, this, this._onLoad);
+ chan.notificationCallbacks = listener;
+ chan.asyncOpen2(listener);
+ },
+
+ /**
+ * Retrieves the engine data from a URI asynchronously and initializes it.
+ *
+ * @param uri The uri to load the search plugin from.
+ *
+ * @returns {Promise} A promise, resolved successfully if retrieveing data
+ * succeeds.
+ */
+ _asyncInitFromURI: Task.async(function* (uri) {
+ LOG("_asyncInitFromURI: Loading engine from: \"" + uri.spec + "\".");
+ yield this._retrieveSearchXMLData(uri.spec);
+ // Now that the data is loaded, initialize the engine object
+ this._initFromData();
+ }),
+
+ /**
+ * Retrieves the engine data for a given URI asynchronously.
+ *
+ * @returns {Promise} A promise, resolved successfully if retrieveing data
+ * succeeds.
+ */
+ _retrieveSearchXMLData: function SRCH_ENG__retrieveSearchXMLData(aURL) {
+ let deferred = Promise.defer();
+ let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
+ createInstance(Ci.nsIXMLHttpRequest);
+ request.overrideMimeType("text/xml");
+ request.onload = (aEvent) => {
+ let responseXML = aEvent.target.responseXML;
+ this._data = responseXML.documentElement;
+ deferred.resolve();
+ };
+ request.onerror = function(aEvent) {
+ deferred.resolve();
+ };
+ request.open("GET", aURL, true);
+ request.send();
+
+ return deferred.promise;
+ },
+
+ _initFromURISync: function SRCH_ENG_initFromURISync(uri) {
+ ENSURE_WARN(uri instanceof Ci.nsIURI,
+ "Must have URI when calling _initFromURISync!",
+ Cr.NS_ERROR_UNEXPECTED);
+
+ ENSURE_WARN(uri.schemeIs("resource"), "_initFromURISync called for non-resource URI",
+ Cr.NS_ERROR_FAILURE);
+
+ LOG("_initFromURISync: Loading engine from: \"" + uri.spec + "\".");
+
+ var chan = NetUtil.newChannel({
+ uri: uri,
+ loadUsingSystemPrincipal: true
+ });
+
+ var stream = chan.open2();
+ var parser = Cc["@mozilla.org/xmlextras/domparser;1"].
+ createInstance(Ci.nsIDOMParser);
+ var doc = parser.parseFromStream(stream, "UTF-8", stream.available(), "text/xml");
+
+ this._data = doc.documentElement;
+
+ // Now that the data is loaded, initialize the engine object
+ this._initFromData();
+ },
+
+ /**
+ * Attempts to find an EngineURL object in the set of EngineURLs for
+ * this Engine that has the given type string. (This corresponds to the
+ * "type" attribute in the "Url" node in the OpenSearch spec.)
+ * This method will return the first matching URL object found, or null
+ * if no matching URL is found.
+ *
+ * @param aType string to match the EngineURL's type attribute
+ * @param aRel [optional] only return URLs that with this rel value
+ */
+ _getURLOfType: function SRCH_ENG__getURLOfType(aType, aRel) {
+ for (var i = 0; i < this._urls.length; ++i) {
+ if (this._urls[i].type == aType && (!aRel || this._urls[i]._hasRelation(aRel)))
+ return this._urls[i];
+ }
+
+ return null;
+ },
+
+ _confirmAddEngine: function SRCH_SVC_confirmAddEngine() {
+ var stringBundle = Services.strings.createBundle(SEARCH_BUNDLE);
+ var titleMessage = stringBundle.GetStringFromName("addEngineConfirmTitle");
+
+ // Display only the hostname portion of the URL.
+ var dialogMessage =
+ stringBundle.formatStringFromName("addEngineConfirmation",
+ [this._name, this._uri.host], 2);
+ var checkboxMessage = null;
+ if (!Services.prefs.getBoolPref(BROWSER_SEARCH_PREF + "noCurrentEngine", false))
+ checkboxMessage = stringBundle.GetStringFromName("addEngineAsCurrentText");
+
+ var addButtonLabel =
+ stringBundle.GetStringFromName("addEngineAddButtonLabel");
+
+ var ps = Services.prompt;
+ var buttonFlags = (ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0) +
+ (ps.BUTTON_TITLE_CANCEL * ps.BUTTON_POS_1) +
+ ps.BUTTON_POS_0_DEFAULT;
+
+ var checked = {value: false};
+ // confirmEx returns the index of the button that was pressed. Since "Add"
+ // is button 0, we want to return the negation of that value.
+ var confirm = !ps.confirmEx(null,
+ titleMessage,
+ dialogMessage,
+ buttonFlags,
+ addButtonLabel,
+ null, null, // button 1 & 2 names not used
+ checkboxMessage,
+ checked);
+
+ return {confirmed: confirm, useNow: checked.value};
+ },
+
+ /**
+ * Handle the successful download of an engine. Initializes the engine and
+ * triggers parsing of the data. The engine is then flushed to disk. Notifies
+ * the search service once initialization is complete.
+ */
+ _onLoad: function SRCH_ENG_onLoad(aBytes, aEngine) {
+ /**
+ * Handle an error during the load of an engine by notifying the engine's
+ * error callback, if any.
+ */
+ function onError(errorCode = Ci.nsISearchInstallCallback.ERROR_UNKNOWN_FAILURE) {
+ // Notify the callback of the failure
+ if (aEngine._installCallback) {
+ aEngine._installCallback(errorCode);
+ }
+ }
+
+ function promptError(strings = {}, error = undefined) {
+ onError(error);
+
+ if (aEngine._engineToUpdate) {
+ // We're in an update, so just fail quietly
+ LOG("updating " + aEngine._engineToUpdate.name + " failed");
+ return;
+ }
+ var brandBundle = Services.strings.createBundle(BRAND_BUNDLE);
+ var brandName = brandBundle.GetStringFromName("brandShortName");
+
+ var searchBundle = Services.strings.createBundle(SEARCH_BUNDLE);
+ var msgStringName = strings.error || "error_loading_engine_msg2";
+ var titleStringName = strings.title || "error_loading_engine_title";
+ var title = searchBundle.GetStringFromName(titleStringName);
+ var text = searchBundle.formatStringFromName(msgStringName,
+ [brandName, aEngine._location],
+ 2);
+
+ Services.ww.getNewPrompter(null).alert(title, text);
+ }
+
+ if (!aBytes) {
+ promptError();
+ return;
+ }
+
+ var parser = Cc["@mozilla.org/xmlextras/domparser;1"].
+ createInstance(Ci.nsIDOMParser);
+ var doc = parser.parseFromBuffer(aBytes, aBytes.length, "text/xml");
+ aEngine._data = doc.documentElement;
+
+ try {
+ // Initialize the engine from the obtained data
+ aEngine._initFromData();
+ } catch (ex) {
+ LOG("_onLoad: Failed to init engine!\n" + ex);
+ // Report an error to the user
+ promptError();
+ return;
+ }
+
+ if (aEngine._engineToUpdate) {
+ let engineToUpdate = aEngine._engineToUpdate.wrappedJSObject;
+
+ // Make this new engine use the old engine's shortName, and preserve
+ // metadata.
+ aEngine._shortName = engineToUpdate._shortName;
+ Object.keys(engineToUpdate._metaData).forEach(key => {
+ aEngine.setAttr(key, engineToUpdate.getAttr(key));
+ });
+ aEngine._loadPath = engineToUpdate._loadPath;
+
+ // Keep track of the last modified date, so that we can make conditional
+ // requests for future updates.
+ aEngine.setAttr("updatelastmodified", (new Date()).toUTCString());
+
+ // Set the new engine's icon, if it doesn't yet have one.
+ if (!aEngine._iconURI && engineToUpdate._iconURI)
+ aEngine._iconURI = engineToUpdate._iconURI;
+ } else {
+ // Check that when adding a new engine (e.g., not updating an
+ // existing one), a duplicate engine does not already exist.
+ if (Services.search.getEngineByName(aEngine.name)) {
+ // If we're confirming the engine load, then display a "this is a
+ // duplicate engine" prompt; otherwise, fail silently.
+ if (aEngine._confirm) {
+ promptError({ error: "error_duplicate_engine_msg",
+ title: "error_invalid_engine_title"
+ }, Ci.nsISearchInstallCallback.ERROR_DUPLICATE_ENGINE);
+ } else {
+ onError(Ci.nsISearchInstallCallback.ERROR_DUPLICATE_ENGINE);
+ }
+ LOG("_onLoad: duplicate engine found, bailing");
+ return;
+ }
+
+ // If requested, confirm the addition now that we have the title.
+ // This property is only ever true for engines added via
+ // nsIBrowserSearchService::addEngine.
+ if (aEngine._confirm) {
+ var confirmation = aEngine._confirmAddEngine();
+ LOG("_onLoad: confirm is " + confirmation.confirmed +
+ "; useNow is " + confirmation.useNow);
+ if (!confirmation.confirmed) {
+ onError();
+ return;
+ }
+ aEngine._useNow = confirmation.useNow;
+ }
+
+ aEngine._shortName = sanitizeName(aEngine.name);
+ aEngine._loadPath = aEngine.getAnonymizedLoadPath(null, aEngine._uri);
+ aEngine.setAttr("loadPathHash", getVerificationHash(aEngine._loadPath));
+ }
+
+ // Notify the search service of the successful load. It will deal with
+ // updates by checking aEngine._engineToUpdate.
+ notifyAction(aEngine, SEARCH_ENGINE_LOADED);
+
+ // Notify the callback if needed
+ if (aEngine._installCallback) {
+ aEngine._installCallback();
+ }
+ },
+
+ /**
+ * Creates a key by serializing an object that contains the icon's width
+ * and height.
+ *
+ * @param aWidth
+ * Width of the icon.
+ * @param aHeight
+ * Height of the icon.
+ * @returns key string
+ */
+ _getIconKey: function SRCH_ENG_getIconKey(aWidth, aHeight) {
+ let keyObj = {
+ width: aWidth,
+ height: aHeight
+ };
+
+ return JSON.stringify(keyObj);
+ },
+
+ /**
+ * Add an icon to the icon map used by getIconURIBySize() and getIcons().
+ *
+ * @param aWidth
+ * Width of the icon.
+ * @param aHeight
+ * Height of the icon.
+ * @param aURISpec
+ * String with the icon's URI.
+ */
+ _addIconToMap: function SRCH_ENG_addIconToMap(aWidth, aHeight, aURISpec) {
+ if (aWidth == 16 && aHeight == 16) {
+ // The 16x16 icon is stored in _iconURL, we don't need to store it twice.
+ return;
+ }
+
+ // Use an object instead of a Map() because it needs to be serializable.
+ this._iconMapObj = this._iconMapObj || {};
+ let key = this._getIconKey(aWidth, aHeight);
+ this._iconMapObj[key] = aURISpec;
+ },
+
+ /**
+ * Sets the .iconURI property of the engine. If both aWidth and aHeight are
+ * provided an entry will be added to _iconMapObj that will enable accessing
+ * icon's data through getIcons() and getIconURIBySize() APIs.
+ *
+ * @param aIconURL
+ * A URI string pointing to the engine's icon. Must have a http[s],
+ * ftp, or data scheme. Icons with HTTP[S] or FTP schemes will be
+ * downloaded and converted to data URIs for storage in the engine
+ * XML files, if the engine is not readonly.
+ * @param aIsPreferred
+ * Whether or not this icon is to be preferred. Preferred icons can
+ * override non-preferred icons.
+ * @param aWidth (optional)
+ * Width of the icon.
+ * @param aHeight (optional)
+ * Height of the icon.
+ */
+ _setIcon: function SRCH_ENG_setIcon(aIconURL, aIsPreferred, aWidth, aHeight) {
+ var uri = makeURI(aIconURL);
+
+ // Ignore bad URIs
+ if (!uri)
+ return;
+
+ LOG("_setIcon: Setting icon url \"" + limitURILength(uri.spec) + "\" for engine \""
+ + this.name + "\".");
+ // Only accept remote icons from http[s] or ftp
+ switch (uri.scheme) {
+ case "resource":
+ case "chrome":
+ // We only allow chrome and resource icon URLs for built-in search engines
+ if (!this._isDefault) {
+ return;
+ }
+ // Fall through to the data case
+ case "data":
+ if (!this._hasPreferredIcon || aIsPreferred) {
+ this._iconURI = uri;
+ notifyAction(this, SEARCH_ENGINE_CHANGED);
+ this._hasPreferredIcon = aIsPreferred;
+ }
+
+ if (aWidth && aHeight) {
+ this._addIconToMap(aWidth, aHeight, aIconURL)
+ }
+ break;
+ case "http":
+ case "https":
+ case "ftp":
+ LOG("_setIcon: Downloading icon: \"" + uri.spec +
+ "\" for engine: \"" + this.name + "\"");
+ var chan = NetUtil.newChannel({
+ uri: uri,
+ loadUsingSystemPrincipal: true
+ });
+
+ let iconLoadCallback = function (aByteArray, aEngine) {
+ // This callback may run after we've already set a preferred icon,
+ // so check again.
+ if (aEngine._hasPreferredIcon && !aIsPreferred)
+ return;
+
+ if (!aByteArray || aByteArray.length > MAX_ICON_SIZE) {
+ LOG("iconLoadCallback: load failed, or the icon was too large!");
+ return;
+ }
+
+ let type = chan.contentType;
+ if (!type.startsWith("image/"))
+ type = "image/x-icon";
+ let dataURL = "data:" + type + ";base64," +
+ btoa(String.fromCharCode.apply(null, aByteArray));
+
+ aEngine._iconURI = makeURI(dataURL);
+
+ if (aWidth && aHeight) {
+ aEngine._addIconToMap(aWidth, aHeight, dataURL)
+ }
+
+ notifyAction(aEngine, SEARCH_ENGINE_CHANGED);
+ aEngine._hasPreferredIcon = aIsPreferred;
+ };
+
+ // If we're currently acting as an "update engine", then the callback
+ // should set the icon on the engine we're updating and not us, since
+ // |this| might be gone by the time the callback runs.
+ var engineToSet = this._engineToUpdate || this;
+
+ var listener = new loadListener(chan, engineToSet, iconLoadCallback);
+ chan.notificationCallbacks = listener;
+ chan.asyncOpen2(listener);
+ break;
+ }
+ },
+
+ /**
+ * Initialize this Engine object from the collected data.
+ */
+ _initFromData: function SRCH_ENG_initFromData() {
+ ENSURE_WARN(this._data, "Can't init an engine with no data!",
+ Cr.NS_ERROR_UNEXPECTED);
+
+ // Ensure we have a supported engine type before attempting to parse it.
+ let element = this._data;
+ if ((element.localName == MOZSEARCH_LOCALNAME &&
+ element.namespaceURI == MOZSEARCH_NS_10) ||
+ (element.localName == OPENSEARCH_LOCALNAME &&
+ OPENSEARCH_NAMESPACES.indexOf(element.namespaceURI) != -1)) {
+ LOG("_init: Initing search plugin from " + this._location);
+
+ this._parse();
+
+ } else
+ FAIL(this._location + " is not a valid search plugin.", Cr.NS_ERROR_FAILURE);
+
+ // No need to keep a ref to our data (which in some cases can be a document
+ // element) past this point
+ this._data = null;
+ },
+
+ /**
+ * Initialize this Engine object from a collection of metadata.
+ */
+ _initFromMetadata: function SRCH_ENG_initMetaData(aName, aIconURL, aAlias,
+ aDescription, aMethod,
+ aTemplate, aExtensionID) {
+ ENSURE_WARN(!this._readOnly,
+ "Can't call _initFromMetaData on a readonly engine!",
+ Cr.NS_ERROR_FAILURE);
+
+ this._urls.push(new EngineURL(URLTYPE_SEARCH_HTML, aMethod, aTemplate));
+
+ this._name = aName;
+ this.alias = aAlias;
+ this._description = aDescription;
+ this._setIcon(aIconURL, true);
+ this._extensionID = aExtensionID;
+ },
+
+ /**
+ * Extracts data from an OpenSearch URL element and creates an EngineURL
+ * object which is then added to the engine's list of URLs.
+ *
+ * @throws NS_ERROR_FAILURE if a URL object could not be created.
+ *
+ * @see http://opensearch.a9.com/spec/1.1/querysyntax/#urltag.
+ * @see EngineURL()
+ */
+ _parseURL: function SRCH_ENG_parseURL(aElement) {
+ var type = aElement.getAttribute("type");
+ // According to the spec, method is optional, defaulting to "GET" if not
+ // specified
+ var method = aElement.getAttribute("method") || "GET";
+ var template = aElement.getAttribute("template");
+ var resultDomain = aElement.getAttribute("resultdomain");
+
+ try {
+ var url = new EngineURL(type, method, template, resultDomain);
+ } catch (ex) {
+ FAIL("_parseURL: failed to add " + template + " as a URL",
+ Cr.NS_ERROR_FAILURE);
+ }
+
+ if (aElement.hasAttribute("rel"))
+ url.rels = aElement.getAttribute("rel").toLowerCase().split(/\s+/);
+
+ for (var i = 0; i < aElement.childNodes.length; ++i) {
+ var param = aElement.childNodes[i];
+ if (param.localName == "Param") {
+ try {
+ url.addParam(param.getAttribute("name"), param.getAttribute("value"));
+ } catch (ex) {
+ // Ignore failure
+ LOG("_parseURL: Url element has an invalid param");
+ }
+ } else if (param.localName == "MozParam" &&
+ // We only support MozParams for default search engines
+ this._isDefault) {
+ var value;
+ let condition = param.getAttribute("condition");
+
+ // MozParams must have a condition to be valid
+ if (!condition) {
+ let engineLoc = this._location;
+ let paramName = param.getAttribute("name");
+ LOG("_parseURL: MozParam (" + paramName + ") without a condition attribute found parsing engine: " + engineLoc);
+ continue;
+ }
+
+ switch (condition) {
+ case "purpose":
+ url.addParam(param.getAttribute("name"),
+ param.getAttribute("value"),
+ param.getAttribute("purpose"));
+ // _addMozParam is not needed here since it can be serialized fine without. _addMozParam
+ // also requires a unique "name" which is not normally the case when @purpose is used.
+ break;
+ case "pref":
+ try {
+ value = getMozParamPref(param.getAttribute("pref"), value);
+ url.addParam(param.getAttribute("name"), value);
+ url._addMozParam({"pref": param.getAttribute("pref"),
+ "name": param.getAttribute("name"),
+ "condition": "pref"});
+ } catch (e) { }
+ break;
+ default:
+ let engineLoc = this._location;
+ let paramName = param.getAttribute("name");
+ LOG("_parseURL: MozParam (" + paramName + ") has an unknown condition: " + condition + ". Found parsing engine: " + engineLoc);
+ break;
+ }
+ }
+ }
+
+ this._urls.push(url);
+ },
+
+ /**
+ * Get the icon from an OpenSearch Image element.
+ * @see http://opensearch.a9.com/spec/1.1/description/#image
+ */
+ _parseImage: function SRCH_ENG_parseImage(aElement) {
+ LOG("_parseImage: Image textContent: \"" + limitURILength(aElement.textContent) + "\"");
+
+ let width = parseInt(aElement.getAttribute("width"), 10);
+ let height = parseInt(aElement.getAttribute("height"), 10);
+ let isPrefered = width == 16 && height == 16;
+
+ if (isNaN(width) || isNaN(height) || width <= 0 || height <=0) {
+ LOG("OpenSearch image element must have positive width and height.");
+ return;
+ }
+
+ this._setIcon(aElement.textContent, isPrefered, width, height);
+ },
+
+ /**
+ * Extract search engine information from the collected data to initialize
+ * the engine object.
+ */
+ _parse: function SRCH_ENG_parse() {
+ var doc = this._data;
+
+ // The OpenSearch spec sets a default value for the input encoding.
+ this._queryCharset = OS_PARAM_INPUT_ENCODING_DEF;
+
+ for (var i = 0; i < doc.childNodes.length; ++i) {
+ var child = doc.childNodes[i];
+ switch (child.localName) {
+ case "ShortName":
+ this._name = child.textContent;
+ break;
+ case "Description":
+ this._description = child.textContent;
+ break;
+ case "Url":
+ try {
+ this._parseURL(child);
+ } catch (ex) {
+ // Parsing of the element failed, just skip it.
+ LOG("_parse: failed to parse URL child: " + ex);
+ }
+ break;
+ case "Image":
+ this._parseImage(child);
+ break;
+ case "InputEncoding":
+ this._queryCharset = child.textContent.toUpperCase();
+ break;
+
+ // Non-OpenSearch elements
+ case "SearchForm":
+ this._searchForm = child.textContent;
+ break;
+ case "UpdateUrl":
+ this._updateURL = child.textContent;
+ break;
+ case "UpdateInterval":
+ this._updateInterval = parseInt(child.textContent);
+ break;
+ case "IconUpdateUrl":
+ this._iconUpdateURL = child.textContent;
+ break;
+ case "ExtensionID":
+ this._extensionID = child.textContent;
+ break;
+ }
+ }
+ if (!this.name || (this._urls.length == 0))
+ FAIL("_parse: No name, or missing URL!", Cr.NS_ERROR_FAILURE);
+ if (!this.supportsResponseType(URLTYPE_SEARCH_HTML))
+ FAIL("_parse: No text/html result type!", Cr.NS_ERROR_FAILURE);
+ },
+
+ /**
+ * Init from a JSON record.
+ **/
+ _initWithJSON: function SRCH_ENG__initWithJSON(aJson) {
+ this._name = aJson._name;
+ this._shortName = aJson._shortName;
+ this._loadPath = aJson._loadPath;
+ this._description = aJson.description;
+ this._hasPreferredIcon = aJson._hasPreferredIcon == undefined;
+ this._queryCharset = aJson.queryCharset || DEFAULT_QUERY_CHARSET;
+ this.__searchForm = aJson.__searchForm;
+ this._updateInterval = aJson._updateInterval || null;
+ this._updateURL = aJson._updateURL || null;
+ this._iconUpdateURL = aJson._iconUpdateURL || null;
+ this._readOnly = aJson._readOnly == undefined;
+ this._iconURI = makeURI(aJson._iconURL);
+ this._iconMapObj = aJson._iconMapObj;
+ this._metaData = aJson._metaData || {};
+ if (aJson.filePath) {
+ this._filePath = aJson.filePath;
+ }
+ if (aJson.dirPath) {
+ this._dirPath = aJson.dirPath;
+ this._dirLastModifiedTime = aJson.dirLastModifiedTime;
+ }
+ if (aJson.extensionID) {
+ this._extensionID = aJson.extensionID;
+ }
+ for (let i = 0; i < aJson._urls.length; ++i) {
+ let url = aJson._urls[i];
+ let engineURL = new EngineURL(url.type || URLTYPE_SEARCH_HTML,
+ url.method || "GET", url.template,
+ url.resultDomain || undefined);
+ engineURL._initWithJSON(url, this);
+ this._urls.push(engineURL);
+ }
+ },
+
+ /**
+ * Creates a JavaScript object that represents this engine.
+ * @returns An object suitable for serialization as JSON.
+ **/
+ toJSON: function SRCH_ENG_toJSON() {
+ var json = {
+ _name: this._name,
+ _shortName: this._shortName,
+ _loadPath: this._loadPath,
+ description: this.description,
+ __searchForm: this.__searchForm,
+ _iconURL: this._iconURL,
+ _iconMapObj: this._iconMapObj,
+ _metaData: this._metaData,
+ _urls: this._urls
+ };
+
+ if (this._updateInterval)
+ json._updateInterval = this._updateInterval;
+ if (this._updateURL)
+ json._updateURL = this._updateURL;
+ if (this._iconUpdateURL)
+ json._iconUpdateURL = this._iconUpdateURL;
+ if (!this._hasPreferredIcon)
+ json._hasPreferredIcon = this._hasPreferredIcon;
+ if (this.queryCharset != DEFAULT_QUERY_CHARSET)
+ json.queryCharset = this.queryCharset;
+ if (!this._readOnly)
+ json._readOnly = this._readOnly;
+ if (this._filePath) {
+ // File path is stored so that we can remove legacy xml files
+ // from the profile if the user removes the engine.
+ json.filePath = this._filePath;
+ }
+ if (this._dirPath) {
+ // The directory path is only stored for extension-shipped engines,
+ // it's used to invalidate the cache.
+ json.dirPath = this._dirPath;
+ json.dirLastModifiedTime = this._dirLastModifiedTime;
+ }
+ if (this._extensionID) {
+ json.extensionID = this._extensionID;
+ }
+
+ return json;
+ },
+
+ setAttr(name, val) {
+ this._metaData[name] = val;
+ },
+
+ getAttr(name) {
+ return this._metaData[name] || undefined;
+ },
+
+ // nsISearchEngine
+ get alias() {
+ return this.getAttr("alias");
+ },
+ set alias(val) {
+ var value = val ? val.trim() : null;
+ this.setAttr("alias", value);
+ notifyAction(this, SEARCH_ENGINE_CHANGED);
+ },
+
+ /**
+ * Return the built-in identifier of app-provided engines.
+ *
+ * Note that this identifier is substantially similar to _id, with the
+ * following exceptions:
+ *
+ * * There is no trailing file extension.
+ * * There is no [app] prefix.
+ *
+ * @return a string identifier, or null.
+ */
+ get identifier() {
+ // No identifier if If the engine isn't app-provided
+ return this._isDefault ? this._shortName : null;
+ },
+
+ get description() {
+ return this._description;
+ },
+
+ get hidden() {
+ return this.getAttr("hidden") || false;
+ },
+ set hidden(val) {
+ var value = !!val;
+ if (value != this.hidden) {
+ this.setAttr("hidden", value);
+ notifyAction(this, SEARCH_ENGINE_CHANGED);
+ }
+ },
+
+ get iconURI() {
+ if (this._iconURI)
+ return this._iconURI;
+ return null;
+ },
+
+ get _iconURL() {
+ if (!this._iconURI)
+ return "";
+ return this._iconURI.spec;
+ },
+
+ // Where the engine is being loaded from: will return the URI's spec if the
+ // engine is being downloaded and does not yet have a file. This is only used
+ // for logging and error messages.
+ get _location() {
+ if (this._uri)
+ return this._uri.spec;
+
+ return this._loadPath;
+ },
+
+ // This indicates where we found the .xml file to load the engine,
+ // and attempts to hide user-identifiable data (such as username).
+ getAnonymizedLoadPath(file, uri) {
+ /* Examples of expected output:
+ * jar:[app]/omni.ja!browser/engine.xml
+ * 'browser' here is the name of the chrome package, not a folder.
+ * [profile]/searchplugins/engine.xml
+ * [distribution]/searchplugins/common/engine.xml
+ * [other]/engine.xml
+ */
+
+ const NS_XPCOM_CURRENT_PROCESS_DIR = "XCurProcD";
+ const NS_APP_USER_PROFILE_50_DIR = "ProfD";
+ const XRE_APP_DISTRIBUTION_DIR = "XREAppDist";
+
+ const knownDirs = {
+ app: NS_XPCOM_CURRENT_PROCESS_DIR,
+ profile: NS_APP_USER_PROFILE_50_DIR,
+ distribution: XRE_APP_DISTRIBUTION_DIR
+ };
+
+ let leafName = this._shortName;
+ if (!leafName)
+ return "null";
+ leafName += ".xml";
+
+ let prefix = "", suffix = "";
+ if (!file) {
+ if (uri.schemeIs("resource")) {
+ uri = makeURI(Services.io.getProtocolHandler("resource")
+ .QueryInterface(Ci.nsISubstitutingProtocolHandler)
+ .resolveURI(uri));
+ }
+ let scheme = uri.scheme;
+ let packageName = "";
+ if (scheme == "chrome") {
+ packageName = uri.hostPort;
+ uri = gChromeReg.convertChromeURL(uri);
+ }
+
+ if (AppConstants.platform == "android") {
+ // On Android the omni.ja file isn't at the same path as the binary
+ // used to start the process. We tweak the path here so that the code
+ // shared with Desktop will correctly identify files from the omni.ja
+ // file as coming from the [app] folder.
+ let appPath = Services.io.getProtocolHandler("resource")
+ .QueryInterface(Ci.nsIResProtocolHandler)
+ .getSubstitution("android");
+ if (appPath) {
+ appPath = appPath.spec;
+ let spec = uri.spec;
+ if (spec.includes(appPath)) {
+ let appURI = Services.io.newFileURI(getDir(knownDirs["app"]));
+ uri = NetUtil.newURI(spec.replace(appPath, appURI.spec));
+ }
+ }
+ }
+
+ if (uri instanceof Ci.nsINestedURI) {
+ prefix = "jar:";
+ suffix = "!" + packageName + "/" + leafName;
+ uri = uri.innermostURI;
+ }
+ if (uri instanceof Ci.nsIFileURL) {
+ file = uri.file;
+ } else {
+ let path = "[" + scheme + "]";
+ if (/^(?:https?|ftp)$/.test(scheme)) {
+ path += uri.host;
+ }
+ return path + "/" + leafName;
+ }
+ }
+
+ let id;
+ let enginePath = file.path;
+
+ for (let key in knownDirs) {
+ let path;
+ try {
+ path = getDir(knownDirs[key]).path;
+ } catch (e) {
+ // Getting XRE_APP_DISTRIBUTION_DIR throws during unit tests.
+ continue;
+ }
+ if (enginePath.startsWith(path)) {
+ id = "[" + key + "]" + enginePath.slice(path.length).replace(/\\/g, "/");
+ break;
+ }
+ }
+
+ // If the folder doesn't have a known ancestor, don't record its path to
+ // avoid leaking user identifiable data.
+ if (!id)
+ id = "[other]/" + file.leafName;
+
+ return prefix + id + suffix;
+ },
+
+ get _isDefault() {
+ // If we don't have a shortName, the engine is being parsed from a
+ // downloaded file, so this can't be a default engine.
+ if (!this._shortName)
+ return false;
+
+ // An engine is a default one if we initially loaded it from the application
+ // or distribution directory.
+ if (/^(?:jar:)?(?:\[app\]|\[distribution\])/.test(this._loadPath))
+ return true;
+
+ // If we are using a non-default locale or in the xpcshell test case,
+ // we'll accept as a 'default' engine anything that has been registered at
+ // resource://search-plugins/ even if the file doesn't come from the
+ // application folder. If not, skip costly additional checks.
+ if (!Services.prefs.prefHasUserValue(LOCALE_PREF) &&
+ !gEnvironment.get("XPCSHELL_TEST_PROFILE_DIR"))
+ return false;
+
+ // Some xpcshell tests use the search service without registering
+ // resource://search-plugins/.
+ if (!Services.io.getProtocolHandler("resource")
+ .QueryInterface(Ci.nsIResProtocolHandler)
+ .hasSubstitution("search-plugins"))
+ return false;
+
+ let uri = makeURI(APP_SEARCH_PREFIX + this._shortName + ".xml");
+ if (this.getAnonymizedLoadPath(null, uri) == this._loadPath) {
+ // This isn't a real default engine, but it's very close.
+ LOG("_isDefault, pretending " + this._loadPath + " is a default engine");
+ return true;
+ }
+
+ return false;
+ },
+
+ get _hasUpdates() {
+ // Whether or not the engine has an update URL
+ let selfURL = this._getURLOfType(URLTYPE_OPENSEARCH, "self");
+ return !!(this._updateURL || this._iconUpdateURL || selfURL);
+ },
+
+ get name() {
+ return this._name;
+ },
+
+ get searchForm() {
+ return this._getSearchFormWithPurpose();
+ },
+
+ _getSearchFormWithPurpose(aPurpose = "") {
+ // First look for a <Url rel="searchform">
+ var searchFormURL = this._getURLOfType(URLTYPE_SEARCH_HTML, "searchform");
+ if (searchFormURL) {
+ let submission = searchFormURL.getSubmission("", this, aPurpose);
+
+ // If the rel=searchform URL is not type="get" (i.e. has postData),
+ // ignore it, since we can only return a URL.
+ if (!submission.postData)
+ return submission.uri.spec;
+ }
+
+ if (!this._searchForm) {
+ // No SearchForm specified in the engine definition file, use the prePath
+ // (e.g. https://foo.com for https://foo.com/search.php?q=bar).
+ var htmlUrl = this._getURLOfType(URLTYPE_SEARCH_HTML);
+ ENSURE_WARN(htmlUrl, "Engine has no HTML URL!", Cr.NS_ERROR_UNEXPECTED);
+ this._searchForm = makeURI(htmlUrl.template).prePath;
+ }
+
+ return ParamSubstitution(this._searchForm, "", this);
+ },
+
+ get queryCharset() {
+ if (this._queryCharset)
+ return this._queryCharset;
+ return this._queryCharset = "windows-1252"; // the default
+ },
+
+ // from nsISearchEngine
+ addParam: function SRCH_ENG_addParam(aName, aValue, aResponseType) {
+ if (!aName || (aValue == null))
+ FAIL("missing name or value for nsISearchEngine::addParam!");
+ ENSURE_WARN(!this._readOnly,
+ "called nsISearchEngine::addParam on a read-only engine!",
+ Cr.NS_ERROR_FAILURE);
+ if (!aResponseType)
+ aResponseType = URLTYPE_SEARCH_HTML;
+
+ var url = this._getURLOfType(aResponseType);
+ if (!url)
+ FAIL("Engine object has no URL for response type " + aResponseType,
+ Cr.NS_ERROR_FAILURE);
+
+ url.addParam(aName, aValue);
+ },
+
+ get _defaultMobileResponseType() {
+ let type = URLTYPE_SEARCH_HTML;
+
+ let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
+ let isTablet = sysInfo.get("tablet");
+ if (isTablet && this.supportsResponseType("application/x-moz-tabletsearch")) {
+ // Check for a tablet-specific search URL override
+ type = "application/x-moz-tabletsearch";
+ } else if (!isTablet && this.supportsResponseType("application/x-moz-phonesearch")) {
+ // Check for a phone-specific search URL override
+ type = "application/x-moz-phonesearch";
+ }
+
+ delete this._defaultMobileResponseType;
+ return this._defaultMobileResponseType = type;
+ },
+
+ get _isWhiteListed() {
+ let url = this._getURLOfType(URLTYPE_SEARCH_HTML).template;
+ let hostname = makeURI(url).host;
+ let whitelist = Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF)
+ .getCharPref("reset.whitelist")
+ .split(",");
+ if (whitelist.includes(hostname)) {
+ LOG("The hostname " + hostname + " is white listed, " +
+ "we won't show the search reset prompt");
+ return true;
+ }
+
+ return false;
+ },
+
+ // from nsISearchEngine
+ getSubmission: function SRCH_ENG_getSubmission(aData, aResponseType, aPurpose) {
+ if (!aResponseType) {
+ aResponseType = AppConstants.platform == "android" ? this._defaultMobileResponseType :
+ URLTYPE_SEARCH_HTML;
+ }
+
+ if (aResponseType == URLTYPE_SEARCH_HTML &&
+ Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF).getBoolPref("reset.enabled") &&
+ this.name == Services.search.currentEngine.name &&
+ !this._isDefault &&
+ this.name != Services.search.originalDefaultEngine.name &&
+ (!this.getAttr("loadPathHash") ||
+ this.getAttr("loadPathHash") != getVerificationHash(this._loadPath)) &&
+ !this._isWhiteListed) {
+ let url = "about:searchreset";
+ let data = [];
+ if (aData)
+ data.push("data=" + encodeURIComponent(aData));
+ if (aPurpose)
+ data.push("purpose=" + aPurpose);
+ if (data.length)
+ url += "?" + data.join("&");
+ return new Submission(makeURI(url));
+ }
+
+ var url = this._getURLOfType(aResponseType);
+
+ if (!url)
+ return null;
+
+ if (!aData) {
+ // Return a dummy submission object with our searchForm attribute
+ return new Submission(makeURI(this._getSearchFormWithPurpose(aPurpose)));
+ }
+
+ LOG("getSubmission: In data: \"" + aData + "\"; Purpose: \"" + aPurpose + "\"");
+ var data = "";
+ try {
+ data = gTextToSubURI.ConvertAndEscape(this.queryCharset, aData);
+ } catch (ex) {
+ LOG("getSubmission: Falling back to default queryCharset!");
+ data = gTextToSubURI.ConvertAndEscape(DEFAULT_QUERY_CHARSET, aData);
+ }
+ LOG("getSubmission: Out data: \"" + data + "\"");
+ return url.getSubmission(data, this, aPurpose);
+ },
+
+ // from nsISearchEngine
+ supportsResponseType: function SRCH_ENG_supportsResponseType(type) {
+ return (this._getURLOfType(type) != null);
+ },
+
+ // from nsISearchEngine
+ getResultDomain: function SRCH_ENG_getResultDomain(aResponseType) {
+ if (!aResponseType) {
+ aResponseType = AppConstants.platform == "android" ? this._defaultMobileResponseType :
+ URLTYPE_SEARCH_HTML;
+ }
+
+ LOG("getResultDomain: responseType: \"" + aResponseType + "\"");
+
+ let url = this._getURLOfType(aResponseType);
+ if (url)
+ return url.resultDomain;
+ return "";
+ },
+
+ /**
+ * Returns URL parsing properties used by _buildParseSubmissionMap.
+ */
+ getURLParsingInfo: function () {
+ let responseType = AppConstants.platform == "android" ? this._defaultMobileResponseType :
+ URLTYPE_SEARCH_HTML;
+
+ LOG("getURLParsingInfo: responseType: \"" + responseType + "\"");
+
+ let url = this._getURLOfType(responseType);
+ if (!url || url.method != "GET") {
+ return null;
+ }
+
+ let termsParameterName = url._getTermsParameterName();
+ if (!termsParameterName) {
+ return null;
+ }
+
+ let templateUrl = NetUtil.newURI(url.template).QueryInterface(Ci.nsIURL);
+ return {
+ mainDomain: templateUrl.host,
+ path: templateUrl.filePath.toLowerCase(),
+ termsParameterName: termsParameterName,
+ };
+ },
+
+ // nsISupports
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISearchEngine]),
+
+ get wrappedJSObject() {
+ return this;
+ },
+
+ /**
+ * Returns a string with the URL to an engine's icon matching both width and
+ * height. Returns null if icon with specified dimensions is not found.
+ *
+ * @param width
+ * Width of the requested icon.
+ * @param height
+ * Height of the requested icon.
+ */
+ getIconURLBySize: function SRCH_ENG_getIconURLBySize(aWidth, aHeight) {
+ if (aWidth == 16 && aHeight == 16)
+ return this._iconURL;
+
+ if (!this._iconMapObj)
+ return null;
+
+ let key = this._getIconKey(aWidth, aHeight);
+ if (key in this._iconMapObj) {
+ return this._iconMapObj[key];
+ }
+ return null;
+ },
+
+ /**
+ * Gets an array of all available icons. Each entry is an object with
+ * width, height and url properties. width and height are numeric and
+ * represent the icon's dimensions. url is a string with the URL for
+ * the icon.
+ */
+ getIcons: function SRCH_ENG_getIcons() {
+ let result = [];
+ if (this._iconURL)
+ result.push({width: 16, height: 16, url: this._iconURL});
+
+ if (!this._iconMapObj)
+ return result;
+
+ for (let key of Object.keys(this._iconMapObj)) {
+ let iconSize = JSON.parse(key);
+ result.push({
+ width: iconSize.width,
+ height: iconSize.height,
+ url: this._iconMapObj[key]
+ });
+ }
+
+ return result;
+ },
+
+ /**
+ * Opens a speculative connection to the engine's search URI
+ * (and suggest URI, if different) to reduce request latency
+ *
+ * @param options
+ * An object that must contain the following fields:
+ * {window} the content window for the window performing the search
+ *
+ * @throws NS_ERROR_INVALID_ARG if options is omitted or lacks required
+ * elemeents
+ */
+ speculativeConnect: function SRCH_ENG_speculativeConnect(options) {
+ if (!options || !options.window) {
+ Cu.reportError("invalid options arg passed to nsISearchEngine.speculativeConnect");
+ throw Cr.NS_ERROR_INVALID_ARG;
+ }
+ let connector =
+ Services.io.QueryInterface(Components.interfaces.nsISpeculativeConnect);
+
+ let searchURI = this.getSubmission("dummy").uri;
+
+ let callbacks = options.window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebNavigation)
+ .QueryInterface(Components.interfaces.nsILoadContext);
+
+ connector.speculativeConnect(searchURI, callbacks);
+
+ if (this.supportsResponseType(URLTYPE_SUGGEST_JSON)) {
+ let suggestURI = this.getSubmission("dummy", URLTYPE_SUGGEST_JSON).uri;
+ if (suggestURI.prePath != searchURI.prePath)
+ connector.speculativeConnect(suggestURI, callbacks);
+ }
+ },
+};
+
+// nsISearchSubmission
+function Submission(aURI, aPostData = null) {
+ this._uri = aURI;
+ this._postData = aPostData;
+}
+Submission.prototype = {
+ get uri() {
+ return this._uri;
+ },
+ get postData() {
+ return this._postData;
+ },
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISearchSubmission])
+}
+
+// nsISearchParseSubmissionResult
+function ParseSubmissionResult(aEngine, aTerms, aTermsOffset, aTermsLength) {
+ this._engine = aEngine;
+ this._terms = aTerms;
+ this._termsOffset = aTermsOffset;
+ this._termsLength = aTermsLength;
+}
+ParseSubmissionResult.prototype = {
+ get engine() {
+ return this._engine;
+ },
+ get terms() {
+ return this._terms;
+ },
+ get termsOffset() {
+ return this._termsOffset;
+ },
+ get termsLength() {
+ return this._termsLength;
+ },
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISearchParseSubmissionResult]),
+}
+
+const gEmptyParseSubmissionResult =
+ Object.freeze(new ParseSubmissionResult(null, "", -1, 0));
+
+function executeSoon(func) {
+ Services.tm.mainThread.dispatch(func, Ci.nsIThread.DISPATCH_NORMAL);
+}
+
+/**
+ * Check for sync initialization has completed or not.
+ *
+ * @param {aPromise} A promise.
+ *
+ * @returns the value returned by the invoked method.
+ * @throws NS_ERROR_ALREADY_INITIALIZED if sync initialization has completed.
+ */
+function checkForSyncCompletion(aPromise) {
+ return aPromise.then(function(aValue) {
+ if (gInitialized) {
+ throw Components.Exception("Synchronous fallback was called and has " +
+ "finished so no need to pursue asynchronous " +
+ "initialization",
+ Cr.NS_ERROR_ALREADY_INITIALIZED);
+ }
+ return aValue;
+ });
+}
+
+// nsIBrowserSearchService
+function SearchService() {
+ // Replace empty LOG function with the useful one if the log pref is set.
+ if (Services.prefs.getBoolPref(BROWSER_SEARCH_PREF + "log", false))
+ LOG = DO_LOG;
+
+ this._initObservers = Promise.defer();
+}
+
+SearchService.prototype = {
+ classID: Components.ID("{7319788a-fe93-4db3-9f39-818cf08f4256}"),
+
+ // The current status of initialization. Note that it does not determine if
+ // initialization is complete, only if an error has been encountered so far.
+ _initRV: Cr.NS_OK,
+
+ // The boolean indicates that the initialization has started or not.
+ _initStarted: null,
+
+ // Reading the JSON cache file is the first thing done during initialization.
+ // During the async init, we save it in a field so that if we have to do a
+ // sync init before the async init finishes, we can avoid reading the cache
+ // with sync disk I/O and handling lz4 decompression synchronously.
+ // This is set back to null as soon as the initialization is finished.
+ _cacheFileJSON: null,
+
+ // If initialization has not been completed yet, perform synchronous
+ // initialization.
+ // Throws in case of initialization error.
+ _ensureInitialized: function SRCH_SVC__ensureInitialized() {
+ if (gInitialized) {
+ if (!Components.isSuccessCode(this._initRV)) {
+ LOG("_ensureInitialized: failure");
+ throw this._initRV;
+ }
+ return;
+ }
+
+ let performanceWarning =
+ "Search service falling back to synchronous initialization. " +
+ "This is generally the consequence of an add-on using a deprecated " +
+ "search service API.";
+ Deprecated.perfWarning(performanceWarning, "https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIBrowserSearchService#async_warning");
+ LOG(performanceWarning);
+
+ this._syncInit();
+ if (!Components.isSuccessCode(this._initRV)) {
+ throw this._initRV;
+ }
+ },
+
+ // Synchronous implementation of the initializer.
+ // Used by |_ensureInitialized| as a fallback if initialization is not
+ // complete.
+ _syncInit: function SRCH_SVC__syncInit() {
+ LOG("_syncInit start");
+ this._initStarted = true;
+
+ let cache = this._readCacheFile();
+ if (cache.metaData)
+ this._metaData = cache.metaData;
+
+ try {
+ this._syncLoadEngines(cache);
+ } catch (ex) {
+ this._initRV = Cr.NS_ERROR_FAILURE;
+ LOG("_syncInit: failure loading engines: " + ex);
+ }
+ this._addObservers();
+
+ gInitialized = true;
+ this._cacheFileJSON = null;
+
+ this._initObservers.resolve(this._initRV);
+
+ Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "init-complete");
+ Services.telemetry.getHistogramById("SEARCH_SERVICE_INIT_SYNC").add(true);
+ this._recordEngineTelemetry();
+
+ LOG("_syncInit end");
+ },
+
+ /**
+ * Asynchronous implementation of the initializer.
+ *
+ * @returns {Promise} A promise, resolved successfully if the initialization
+ * succeeds.
+ */
+ _asyncInit: Task.async(function* () {
+ LOG("_asyncInit start");
+
+ // See if we have a cache file so we don't have to parse a bunch of XML.
+ let cache = {};
+ // Not using checkForSyncCompletion here because we want to ensure we
+ // fetch the country code and geo specific defaults asynchronously even
+ // if a sync init has been forced.
+ cache = yield this._asyncReadCacheFile();
+
+ if (!gInitialized && cache.metaData)
+ this._metaData = cache.metaData;
+
+ try {
+ yield checkForSyncCompletion(this._asyncLoadEngines(cache));
+ } catch (ex) {
+ if (ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {
+ throw ex;
+ }
+ this._initRV = Cr.NS_ERROR_FAILURE;
+ LOG("_asyncInit: failure loading engines: " + ex);
+ }
+ this._addObservers();
+ gInitialized = true;
+ this._cacheFileJSON = null;
+ this._initObservers.resolve(this._initRV);
+ Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "init-complete");
+ Services.telemetry.getHistogramById("SEARCH_SERVICE_INIT_SYNC").add(false);
+ this._recordEngineTelemetry();
+
+ LOG("_asyncInit: Completed _asyncInit");
+ }),
+
+ _metaData: { },
+ setGlobalAttr(name, val) {
+ this._metaData[name] = val;
+ this.batchTask.disarm();
+ this.batchTask.arm();
+ },
+ setVerifiedGlobalAttr(name, val) {
+ this.setGlobalAttr(name, val);
+ this.setGlobalAttr(name + "Hash", getVerificationHash(val));
+ },
+
+ getGlobalAttr(name) {
+ return this._metaData[name] || undefined;
+ },
+ getVerifiedGlobalAttr(name) {
+ let val = this.getGlobalAttr(name);
+ if (val && this.getGlobalAttr(name + "Hash") != getVerificationHash(val)) {
+ LOG("getVerifiedGlobalAttr, invalid hash for " + name);
+ return "";
+ }
+ return val;
+ },
+
+ _engines: { },
+ __sortedEngines: null,
+ _visibleDefaultEngines: [],
+ get _sortedEngines() {
+ if (!this.__sortedEngines)
+ return this._buildSortedEngineList();
+ return this.__sortedEngines;
+ },
+
+ // Get the original Engine object that is the default for this region,
+ // ignoring changes the user may have subsequently made.
+ get originalDefaultEngine() {
+ let defaultEngine = this.getVerifiedGlobalAttr("searchDefault");
+ if (!defaultEngine) {
+ let defaultPrefB = Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF);
+ let nsIPLS = Ci.nsIPrefLocalizedString;
+
+ try {
+ defaultEngine = defaultPrefB.getComplexValue("defaultenginename", nsIPLS).data;
+ } catch (ex) {
+ // If the default pref is invalid (e.g. an add-on set it to a bogus value)
+ // getEngineByName will just return null, which is the best we can do.
+ }
+ }
+
+ return this.getEngineByName(defaultEngine);
+ },
+
+ resetToOriginalDefaultEngine: function SRCH_SVC__resetToOriginalDefaultEngine() {
+ this.currentEngine = this.originalDefaultEngine;
+ },
+
+ _buildCache: function SRCH_SVC__buildCache() {
+ if (this._batchTask)
+ this._batchTask.disarm();
+
+ let cache = {};
+ let locale = getLocale();
+ let buildID = Services.appinfo.platformBuildID;
+
+ // Allows us to force a cache refresh should the cache format change.
+ cache.version = CACHE_VERSION;
+ // We don't want to incur the costs of stat()ing each plugin on every
+ // startup when the only (supported) time they will change is during
+ // app updates (where the buildID is obviously going to change).
+ // Extension-shipped plugins are the only exception to this, but their
+ // directories are blown away during updates, so we'll detect their changes.
+ cache.buildID = buildID;
+ cache.locale = locale;
+
+ cache.visibleDefaultEngines = this._visibleDefaultEngines;
+ cache.metaData = this._metaData;
+ cache.engines = [];
+
+ for (let name in this._engines) {
+ cache.engines.push(this._engines[name]);
+ }
+
+ try {
+ if (!cache.engines.length)
+ throw "cannot write without any engine.";
+
+ LOG("_buildCache: Writing to cache file.");
+ let path = OS.Path.join(OS.Constants.Path.profileDir, CACHE_FILENAME);
+ let data = gEncoder.encode(JSON.stringify(cache));
+ let promise = OS.File.writeAtomic(path, data, {compression: "lz4",
+ tmpPath: path + ".tmp"});
+
+ promise.then(
+ function onSuccess() {
+ Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, SEARCH_SERVICE_CACHE_WRITTEN);
+ },
+ function onError(e) {
+ LOG("_buildCache: failure during writeAtomic: " + e);
+ }
+ );
+ } catch (ex) {
+ LOG("_buildCache: Could not write to cache file: " + ex);
+ }
+ },
+
+ _syncLoadEngines: function SRCH_SVC__syncLoadEngines(cache) {
+ LOG("_syncLoadEngines: start");
+ // See if we have a cache file so we don't have to parse a bunch of XML.
+ let chromeURIs = this._findJAREngines();
+
+ let distDirs = [];
+ let locations;
+ try {
+ locations = getDir(NS_APP_DISTRIBUTION_SEARCH_DIR_LIST,
+ Ci.nsISimpleEnumerator);
+ } catch (e) {
+ // NS_APP_DISTRIBUTION_SEARCH_DIR_LIST is defined by each app
+ // so this throws during unit tests (but not xpcshell tests).
+ locations = {hasMoreElements: () => false};
+ }
+ while (locations.hasMoreElements()) {
+ let dir = locations.getNext().QueryInterface(Ci.nsIFile);
+ if (dir.directoryEntries.hasMoreElements())
+ distDirs.push(dir);
+ }
+
+ let otherDirs = [];
+ let userSearchDir = getDir(NS_APP_USER_SEARCH_DIR);
+ locations = getDir(NS_APP_SEARCH_DIR_LIST, Ci.nsISimpleEnumerator);
+ while (locations.hasMoreElements()) {
+ let dir = locations.getNext().QueryInterface(Ci.nsIFile);
+ if ((!cache.engines || !dir.equals(userSearchDir)) &&
+ dir.directoryEntries.hasMoreElements())
+ otherDirs.push(dir);
+ }
+
+ function modifiedDir(aDir) {
+ return cacheOtherPaths.get(aDir.path) != aDir.lastModifiedTime;
+ }
+
+ function notInCacheVisibleEngines(aEngineName) {
+ return cache.visibleDefaultEngines.indexOf(aEngineName) == -1;
+ }
+
+ let buildID = Services.appinfo.platformBuildID;
+ let cacheOtherPaths = new Map();
+ if (cache.engines) {
+ for (let engine of cache.engines) {
+ if (engine._dirPath) {
+ cacheOtherPaths.set(engine._dirPath, engine._dirLastModifiedTime);
+ }
+ }
+ }
+
+ let rebuildCache = !cache.engines ||
+ cache.version != CACHE_VERSION ||
+ cache.locale != getLocale() ||
+ cache.buildID != buildID ||
+ cacheOtherPaths.size != otherDirs.length ||
+ otherDirs.some(d => !cacheOtherPaths.has(d.path)) ||
+ cache.visibleDefaultEngines.length != this._visibleDefaultEngines.length ||
+ this._visibleDefaultEngines.some(notInCacheVisibleEngines) ||
+ otherDirs.some(modifiedDir);
+
+ if (rebuildCache) {
+ LOG("_loadEngines: Absent or outdated cache. Loading engines from disk.");
+ distDirs.forEach(this._loadEnginesFromDir, this);
+
+ this._loadFromChromeURLs(chromeURIs);
+
+ LOG("_loadEngines: load user-installed engines from the obsolete cache");
+ this._loadEnginesFromCache(cache, true);
+
+ otherDirs.forEach(this._loadEnginesFromDir, this);
+
+ this._loadEnginesMetadataFromCache(cache);
+ this._buildCache();
+ return;
+ }
+
+ LOG("_loadEngines: loading from cache directories");
+ this._loadEnginesFromCache(cache);
+
+ LOG("_loadEngines: done");
+ },
+
+ /**
+ * Loads engines asynchronously.
+ *
+ * @returns {Promise} A promise, resolved successfully if loading data
+ * succeeds.
+ */
+ _asyncLoadEngines: Task.async(function* (cache) {
+ LOG("_asyncLoadEngines: start");
+ Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "find-jar-engines");
+ let chromeURIs =
+ yield checkForSyncCompletion(this._asyncFindJAREngines());
+
+ // Get the non-empty distribution directories into distDirs...
+ let distDirs = [];
+ let locations;
+ try {
+ locations = getDir(NS_APP_DISTRIBUTION_SEARCH_DIR_LIST,
+ Ci.nsISimpleEnumerator);
+ } catch (e) {
+ // NS_APP_DISTRIBUTION_SEARCH_DIR_LIST is defined by each app
+ // so this throws during unit tests (but not xpcshell tests).
+ locations = {hasMoreElements: () => false};
+ }
+ while (locations.hasMoreElements()) {
+ let dir = locations.getNext().QueryInterface(Ci.nsIFile);
+ let iterator = new OS.File.DirectoryIterator(dir.path,
+ { winPattern: "*.xml" });
+ try {
+ // Add dir to distDirs if it contains any files.
+ yield checkForSyncCompletion(iterator.next());
+ distDirs.push(dir);
+ } catch (ex) {
+ // Catch for StopIteration exception.
+ if (ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {
+ throw ex;
+ }
+ } finally {
+ iterator.close();
+ }
+ }
+
+ // Add the non-empty directories of NS_APP_SEARCH_DIR_LIST to
+ // otherDirs...
+ let otherDirs = [];
+ let userSearchDir = getDir(NS_APP_USER_SEARCH_DIR);
+ locations = getDir(NS_APP_SEARCH_DIR_LIST, Ci.nsISimpleEnumerator);
+ while (locations.hasMoreElements()) {
+ let dir = locations.getNext().QueryInterface(Ci.nsIFile);
+ if (cache.engines && dir.equals(userSearchDir))
+ continue;
+ let iterator = new OS.File.DirectoryIterator(dir.path,
+ { winPattern: "*.xml" });
+ try {
+ // Add dir to otherDirs if it contains any files.
+ yield checkForSyncCompletion(iterator.next());
+ otherDirs.push(dir);
+ } catch (ex) {
+ // Catch for StopIteration exception.
+ if (ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {
+ throw ex;
+ }
+ } finally {
+ iterator.close();
+ }
+ }
+
+ let hasModifiedDir = Task.async(function* (aList) {
+ let modifiedDir = false;
+
+ for (let dir of aList) {
+ let lastModifiedTime = cacheOtherPaths.get(dir.path);
+ if (!lastModifiedTime) {
+ continue;
+ }
+
+ let info = yield OS.File.stat(dir.path);
+ if (lastModifiedTime != info.lastModificationDate.getTime()) {
+ modifiedDir = true;
+ break;
+ }
+ }
+ return modifiedDir;
+ });
+
+ function notInCacheVisibleEngines(aEngineName) {
+ return cache.visibleDefaultEngines.indexOf(aEngineName) == -1;
+ }
+
+ let buildID = Services.appinfo.platformBuildID;
+ let cacheOtherPaths = new Map();
+ if (cache.engines) {
+ for (let engine of cache.engines) {
+ if (engine._dirPath) {
+ cacheOtherPaths.set(engine._dirPath, engine._dirLastModifiedTime);
+ }
+ }
+ }
+
+ let rebuildCache = !cache.engines ||
+ cache.version != CACHE_VERSION ||
+ cache.locale != getLocale() ||
+ cache.buildID != buildID ||
+ cacheOtherPaths.size != otherDirs.length ||
+ otherDirs.some(d => !cacheOtherPaths.has(d.path)) ||
+ cache.visibleDefaultEngines.length != this._visibleDefaultEngines.length ||
+ this._visibleDefaultEngines.some(notInCacheVisibleEngines) ||
+ (yield checkForSyncCompletion(hasModifiedDir(otherDirs)));
+
+ if (rebuildCache) {
+ LOG("_asyncLoadEngines: Absent or outdated cache. Loading engines from disk.");
+ for (let loadDir of distDirs) {
+ let enginesFromDir =
+ yield checkForSyncCompletion(this._asyncLoadEnginesFromDir(loadDir));
+ enginesFromDir.forEach(this._addEngineToStore, this);
+ }
+ let enginesFromURLs =
+ yield checkForSyncCompletion(this._asyncLoadFromChromeURLs(chromeURIs));
+ enginesFromURLs.forEach(this._addEngineToStore, this);
+
+ LOG("_asyncLoadEngines: loading user-installed engines from the obsolete cache");
+ this._loadEnginesFromCache(cache, true);
+
+ for (let loadDir of otherDirs) {
+ let enginesFromDir =
+ yield checkForSyncCompletion(this._asyncLoadEnginesFromDir(loadDir));
+ enginesFromDir.forEach(this._addEngineToStore, this);
+ }
+
+ this._loadEnginesMetadataFromCache(cache);
+ this._buildCache();
+ return;
+ }
+
+ LOG("_asyncLoadEngines: loading from cache directories");
+ this._loadEnginesFromCache(cache);
+
+ LOG("_asyncLoadEngines: done");
+ }),
+
+ _asyncReInit: function () {
+ LOG("_asyncReInit");
+ // Start by clearing the initialized state, so we don't abort early.
+ gInitialized = false;
+
+ Task.spawn(function* () {
+ try {
+ if (this._batchTask) {
+ LOG("finalizing batch task");
+ let task = this._batchTask;
+ this._batchTask = null;
+ yield task.finalize();
+ }
+
+ // Clear the engines, too, so we don't stick with the stale ones.
+ this._engines = {};
+ this.__sortedEngines = null;
+ this._currentEngine = null;
+ this._visibleDefaultEngines = [];
+ this._metaData = {};
+ this._cacheFileJSON = null;
+
+ // Tests that want to force a synchronous re-initialization need to
+ // be notified when we are done uninitializing.
+ Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC,
+ "uninit-complete");
+
+ let cache = {};
+ cache = yield this._asyncReadCacheFile();
+ if (!gInitialized && cache.metaData)
+ this._metaData = cache.metaData;
+
+ yield this._asyncLoadEngines(cache);
+
+ // Typically we'll re-init as a result of a pref observer,
+ // so signal to 'callers' that we're done.
+ Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "init-complete");
+ this._recordEngineTelemetry();
+ gInitialized = true;
+ } catch (err) {
+ LOG("Reinit failed: " + err);
+ Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "reinit-failed");
+ } finally {
+ Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "reinit-complete");
+ }
+ }.bind(this));
+ },
+
+ /**
+ * Read the cache file synchronously. This also imports data from the old
+ * search-metadata.json file if needed.
+ *
+ * @returns A JS object containing the cached data.
+ */
+ _readCacheFile: function SRCH_SVC__readCacheFile() {
+ if (this._cacheFileJSON) {
+ return this._cacheFileJSON;
+ }
+
+ let cacheFile = getDir(NS_APP_USER_PROFILE_50_DIR);
+ cacheFile.append(CACHE_FILENAME);
+
+ let stream;
+ try {
+ stream = Cc["@mozilla.org/network/file-input-stream;1"].
+ createInstance(Ci.nsIFileInputStream);
+ stream.init(cacheFile, MODE_RDONLY, FileUtils.PERMS_FILE, 0);
+
+ let bis = Cc["@mozilla.org/binaryinputstream;1"]
+ .createInstance(Ci.nsIBinaryInputStream);
+ bis.setInputStream(stream);
+
+ let count = stream.available();
+ let array = new Uint8Array(count);
+ bis.readArrayBuffer(count, array.buffer);
+
+ let bytes = Lz4.decompressFileContent(array);
+ let json = JSON.parse(new TextDecoder().decode(bytes));
+ if (!json.engines || !json.engines.length)
+ throw "no engine in the file";
+ return json;
+ } catch (ex) {
+ LOG("_readCacheFile: Error reading cache file: " + ex);
+ } finally {
+ stream.close();
+ }
+
+ try {
+ cacheFile.leafName = "search-metadata.json";
+ stream = Cc["@mozilla.org/network/file-input-stream;1"].
+ createInstance(Ci.nsIFileInputStream);
+ stream.init(cacheFile, MODE_RDONLY, FileUtils.PERMS_FILE, 0);
+ let metadata = parseJsonFromStream(stream);
+ let json = {};
+ if ("[global]" in metadata) {
+ LOG("_readCacheFile: migrating metadata from search-metadata.json");
+ let data = metadata["[global]"];
+ json.metaData = {};
+ let fields = ["searchDefault", "searchDefaultHash", "searchDefaultExpir",
+ "current", "hash",
+ "visibleDefaultEngines", "visibleDefaultEnginesHash"];
+ for (let field of fields) {
+ let name = field.toLowerCase();
+ if (name in data)
+ json.metaData[field] = data[name];
+ }
+ }
+ delete metadata["[global]"];
+ json._oldMetadata = metadata;
+
+ return json;
+ } catch (ex) {
+ LOG("_readCacheFile: failed to read old metadata: " + ex);
+ return {};
+ } finally {
+ stream.close();
+ }
+ },
+
+ /**
+ * Read the cache file asynchronously. This also imports data from the old
+ * search-metadata.json file if needed.
+ *
+ * @returns {Promise} A promise, resolved successfully if retrieveing data
+ * succeeds.
+ */
+ _asyncReadCacheFile: Task.async(function* () {
+ let json;
+ try {
+ let cacheFilePath = OS.Path.join(OS.Constants.Path.profileDir, CACHE_FILENAME);
+ let bytes = yield OS.File.read(cacheFilePath, {compression: "lz4"});
+ json = JSON.parse(new TextDecoder().decode(bytes));
+ if (!json.engines || !json.engines.length)
+ throw "no engine in the file";
+ this._cacheFileJSON = json;
+ } catch (ex) {
+ LOG("_asyncReadCacheFile: Error reading cache file: " + ex);
+ json = {};
+
+ let oldMetadata =
+ OS.Path.join(OS.Constants.Path.profileDir, "search-metadata.json");
+ try {
+ let bytes = yield OS.File.read(oldMetadata);
+ let metadata = JSON.parse(new TextDecoder().decode(bytes));
+ if ("[global]" in metadata) {
+ LOG("_asyncReadCacheFile: migrating metadata from search-metadata.json");
+ let data = metadata["[global]"];
+ json.metaData = {};
+ let fields = ["searchDefault", "searchDefaultHash", "searchDefaultExpir",
+ "current", "hash",
+ "visibleDefaultEngines", "visibleDefaultEnginesHash"];
+ for (let field of fields) {
+ let name = field.toLowerCase();
+ if (name in data)
+ json.metaData[field] = data[name];
+ }
+ }
+ delete metadata["[global]"];
+ json._oldMetadata = metadata;
+ } catch (ex) {}
+ }
+ return json;
+ }),
+
+ _batchTask: null,
+ get batchTask() {
+ if (!this._batchTask) {
+ let task = function taskCallback() {
+ LOG("batchTask: Invalidating engine cache");
+ this._buildCache();
+ }.bind(this);
+ this._batchTask = new DeferredTask(task, CACHE_INVALIDATION_DELAY);
+ }
+ return this._batchTask;
+ },
+
+ _addEngineToStore: function SRCH_SVC_addEngineToStore(aEngine) {
+ LOG("_addEngineToStore: Adding engine: \"" + aEngine.name + "\"");
+
+ // See if there is an existing engine with the same name. However, if this
+ // engine is updating another engine, it's allowed to have the same name.
+ var hasSameNameAsUpdate = (aEngine._engineToUpdate &&
+ aEngine.name == aEngine._engineToUpdate.name);
+ if (aEngine.name in this._engines && !hasSameNameAsUpdate) {
+ LOG("_addEngineToStore: Duplicate engine found, aborting!");
+ return;
+ }
+
+ if (aEngine._engineToUpdate) {
+ // We need to replace engineToUpdate with the engine that just loaded.
+ var oldEngine = aEngine._engineToUpdate;
+
+ // Remove the old engine from the hash, since it's keyed by name, and our
+ // name might change (the update might have a new name).
+ delete this._engines[oldEngine.name];
+
+ // Hack: we want to replace the old engine with the new one, but since
+ // people may be holding refs to the nsISearchEngine objects themselves,
+ // we'll just copy over all "private" properties (those without a getter
+ // or setter) from one object to the other.
+ for (var p in aEngine) {
+ if (!(aEngine.__lookupGetter__(p) || aEngine.__lookupSetter__(p)))
+ oldEngine[p] = aEngine[p];
+ }
+ aEngine = oldEngine;
+ aEngine._engineToUpdate = null;
+
+ // Add the engine back
+ this._engines[aEngine.name] = aEngine;
+ notifyAction(aEngine, SEARCH_ENGINE_CHANGED);
+ } else {
+ // Not an update, just add the new engine.
+ this._engines[aEngine.name] = aEngine;
+ // Only add the engine to the list of sorted engines if the initial list
+ // has already been built (i.e. if this.__sortedEngines is non-null). If
+ // it hasn't, we're loading engines from disk and the sorted engine list
+ // will be built once we need it.
+ if (this.__sortedEngines) {
+ this.__sortedEngines.push(aEngine);
+ this._saveSortedEngineList();
+ }
+ notifyAction(aEngine, SEARCH_ENGINE_ADDED);
+ }
+
+ if (aEngine._hasUpdates) {
+ // Schedule the engine's next update, if it isn't already.
+ if (!aEngine.getAttr("updateexpir"))
+ engineUpdateService.scheduleNextUpdate(aEngine);
+ }
+ },
+
+ _loadEnginesMetadataFromCache: function SRCH_SVC__loadEnginesMetadataFromCache(cache) {
+ if (cache._oldMetadata) {
+ // If we have old metadata in the cache, we had no valid cache
+ // file and read data from search-metadata.json.
+ for (let name in this._engines) {
+ let engine = this._engines[name];
+ if (engine._id && cache._oldMetadata[engine._id])
+ engine._metaData = cache._oldMetadata[engine._id];
+ }
+ return;
+ }
+
+ if (!cache.engines)
+ return;
+
+ for (let engine of cache.engines) {
+ let name = engine._name;
+ if (name in this._engines) {
+ LOG("_loadEnginesMetadataFromCache, transfering metadata for " + name);
+ this._engines[name]._metaData = engine._metaData;
+ }
+ }
+ },
+
+ _loadEnginesFromCache: function SRCH_SVC__loadEnginesFromCache(cache,
+ skipReadOnly) {
+ if (!cache.engines)
+ return;
+
+ LOG("_loadEnginesFromCache: Loading " +
+ cache.engines.length + " engines from cache");
+
+ let skippedEngines = 0;
+ for (let engine of cache.engines) {
+ if (skipReadOnly && engine._readOnly == undefined) {
+ ++skippedEngines;
+ continue;
+ }
+
+ this._loadEngineFromCache(engine);
+ }
+
+ if (skippedEngines) {
+ LOG("_loadEnginesFromCache: skipped " + skippedEngines + " read-only engines.");
+ }
+ },
+
+ _loadEngineFromCache: function SRCH_SVC__loadEngineFromCache(json) {
+ try {
+ let engine = new Engine(json._shortName, json._readOnly == undefined);
+ engine._initWithJSON(json);
+ this._addEngineToStore(engine);
+ } catch (ex) {
+ LOG("Failed to load " + json._name + " from cache: " + ex);
+ LOG("Engine JSON: " + json.toSource());
+ }
+ },
+
+ _loadEnginesFromDir: function SRCH_SVC__loadEnginesFromDir(aDir) {
+ LOG("_loadEnginesFromDir: Searching in " + aDir.path + " for search engines.");
+
+ // Check whether aDir is the user profile dir
+ var isInProfile = aDir.equals(getDir(NS_APP_USER_SEARCH_DIR));
+
+ var files = aDir.directoryEntries
+ .QueryInterface(Ci.nsIDirectoryEnumerator);
+
+ while (files.hasMoreElements()) {
+ var file = files.nextFile;
+
+ // Ignore hidden and empty files, and directories
+ if (!file.isFile() || file.fileSize == 0 || file.isHidden())
+ continue;
+
+ var fileURL = NetUtil.ioService.newFileURI(file).QueryInterface(Ci.nsIURL);
+ var fileExtension = fileURL.fileExtension.toLowerCase();
+
+ if (fileExtension != "xml") {
+ // Not an engine
+ continue;
+ }
+
+ var addedEngine = null;
+ try {
+ addedEngine = new Engine(file, !isInProfile);
+ addedEngine._initFromFile(file);
+ if (!isInProfile && !addedEngine._isDefault) {
+ addedEngine._dirPath = aDir.path;
+ addedEngine._dirLastModifiedTime = aDir.lastModifiedTime;
+ }
+ } catch (ex) {
+ LOG("_loadEnginesFromDir: Failed to load " + file.path + "!\n" + ex);
+ continue;
+ }
+
+ this._addEngineToStore(addedEngine);
+ }
+ },
+
+ /**
+ * Loads engines from a given directory asynchronously.
+ *
+ * @param aDir the directory.
+ *
+ * @returns {Promise} A promise, resolved successfully if retrieveing data
+ * succeeds.
+ */
+ _asyncLoadEnginesFromDir: Task.async(function* (aDir) {
+ LOG("_asyncLoadEnginesFromDir: Searching in " + aDir.path + " for search engines.");
+
+ // Check whether aDir is the user profile dir
+ let isInProfile = aDir.equals(getDir(NS_APP_USER_SEARCH_DIR));
+ let dirPath = aDir.path;
+ let iterator = new OS.File.DirectoryIterator(dirPath);
+
+ let osfiles = yield iterator.nextBatch();
+ iterator.close();
+
+ let engines = [];
+ for (let osfile of osfiles) {
+ if (osfile.isDir || osfile.isSymLink)
+ continue;
+
+ let fileInfo = yield OS.File.stat(osfile.path);
+ if (fileInfo.size == 0)
+ continue;
+
+ let parts = osfile.path.split(".");
+ if (parts.length <= 1 || (parts.pop()).toLowerCase() != "xml") {
+ // Not an engine
+ continue;
+ }
+
+ let addedEngine = null;
+ try {
+ let file = new FileUtils.File(osfile.path);
+ addedEngine = new Engine(file, !isInProfile);
+ yield checkForSyncCompletion(addedEngine._asyncInitFromFile(file));
+ if (!isInProfile && !addedEngine._isDefault) {
+ addedEngine._dirPath = dirPath;
+ let info = yield OS.File.stat(dirPath);
+ addedEngine._dirLastModifiedTime =
+ info.lastModificationDate.getTime();
+ }
+ engines.push(addedEngine);
+ } catch (ex) {
+ if (ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {
+ throw ex;
+ }
+ LOG("_asyncLoadEnginesFromDir: Failed to load " + osfile.path + "!\n" + ex);
+ }
+ }
+ return engines;
+ }),
+
+ _loadFromChromeURLs: function SRCH_SVC_loadFromChromeURLs(aURLs) {
+ aURLs.forEach(function (url) {
+ try {
+ LOG("_loadFromChromeURLs: loading engine from chrome url: " + url);
+
+ let uri = makeURI(url);
+ let engine = new Engine(uri, true);
+
+ engine._initFromURISync(uri);
+
+ this._addEngineToStore(engine);
+ } catch (ex) {
+ LOG("_loadFromChromeURLs: failed to load engine: " + ex);
+ }
+ }, this);
+ },
+
+ /**
+ * Loads engines from Chrome URLs asynchronously.
+ *
+ * @param aURLs a list of URLs.
+ *
+ * @returns {Promise} A promise, resolved successfully if loading data
+ * succeeds.
+ */
+ _asyncLoadFromChromeURLs: Task.async(function* (aURLs) {
+ let engines = [];
+ for (let url of aURLs) {
+ try {
+ LOG("_asyncLoadFromChromeURLs: loading engine from chrome url: " + url);
+ let uri = NetUtil.newURI(url);
+ let engine = new Engine(uri, true);
+ yield checkForSyncCompletion(engine._asyncInitFromURI(uri));
+ engines.push(engine);
+ } catch (ex) {
+ if (ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {
+ throw ex;
+ }
+ LOG("_asyncLoadFromChromeURLs: failed to load engine: " + ex);
+ }
+ }
+ return engines;
+ }),
+
+ _convertChannelToFile: function(chan) {
+ let fileURI = chan.URI;
+ while (fileURI instanceof Ci.nsIJARURI)
+ fileURI = fileURI.JARFile;
+ fileURI.QueryInterface(Ci.nsIFileURL);
+
+ return fileURI.file;
+ },
+
+ _findJAREngines: function SRCH_SVC_findJAREngines() {
+ LOG("_findJAREngines: looking for engines in JARs")
+
+ let chan = makeChannel(APP_SEARCH_PREFIX + "list.json");
+ if (!chan) {
+ LOG("_findJAREngines: " + APP_SEARCH_PREFIX + " isn't registered");
+ return [];
+ }
+
+ let uris = [];
+
+ let sis = Cc["@mozilla.org/scriptableinputstream;1"].
+ createInstance(Ci.nsIScriptableInputStream);
+ try {
+ sis.init(chan.open2());
+ this._parseListJSON(sis.read(sis.available()), uris);
+ // parseListJSON will catch its own errors, so we
+ // should only go into this catch if list.json
+ // doesn't exist
+ } catch (e) {
+ chan = makeChannel(APP_SEARCH_PREFIX + "list.txt");
+ sis.init(chan.open2());
+ this._parseListTxt(sis.read(sis.available()), uris);
+ }
+ return uris;
+ },
+
+ /**
+ * Loads jar engines asynchronously.
+ *
+ * @returns {Promise} A promise, resolved successfully if finding jar engines
+ * succeeds.
+ */
+ _asyncFindJAREngines: Task.async(function* () {
+ LOG("_asyncFindJAREngines: looking for engines in JARs")
+
+ let listURL = APP_SEARCH_PREFIX + "list.json";
+ let chan = makeChannel(listURL);
+ if (!chan) {
+ LOG("_asyncFindJAREngines: " + APP_SEARCH_PREFIX + " isn't registered");
+ return [];
+ }
+
+ let uris = [];
+
+ // Read list.json to find the engines we need to load.
+ let deferred = Promise.defer();
+ let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
+ createInstance(Ci.nsIXMLHttpRequest);
+ request.overrideMimeType("text/plain");
+ request.onload = function(aEvent) {
+ deferred.resolve(aEvent.target.responseText);
+ };
+ request.onerror = function(aEvent) {
+ LOG("_asyncFindJAREngines: failed to read " + listURL);
+ // Couldn't find list.json, try list.txt
+ request.onerror = function(aEvent) {
+ LOG("_asyncFindJAREngines: failed to read " + APP_SEARCH_PREFIX + "list.txt");
+ deferred.resolve("");
+ }
+ request.open("GET", NetUtil.newURI(APP_SEARCH_PREFIX + "list.txt").spec, true);
+ request.send();
+ };
+ request.open("GET", NetUtil.newURI(listURL).spec, true);
+ request.send();
+ let list = yield deferred.promise;
+
+ if (request.responseURL.endsWith(".txt")) {
+ this._parseListTxt(list, uris);
+ } else {
+ this._parseListJSON(list, uris);
+ }
+ return uris;
+ }),
+
+ _parseListJSON: function SRCH_SVC_parseListJSON(list, uris) {
+ let searchSettings;
+ try {
+ searchSettings = JSON.parse(list);
+ } catch (e) {
+ LOG("failing to parse list.json: " + e);
+ return;
+ }
+
+ let jarNames = new Set();
+ for (let region in searchSettings) {
+ // Artifact builds use the full list.json which parses
+ // slightly differently
+ if (!("visibleDefaultEngines" in searchSettings[region])) {
+ continue;
+ }
+ for (let engine of searchSettings[region]["visibleDefaultEngines"]) {
+ jarNames.add(engine);
+ }
+ }
+
+ // Check if we have a useable country specific list of visible default engines.
+ let engineNames;
+ let visibleDefaultEngines = this.getVerifiedGlobalAttr("visibleDefaultEngines");
+ if (visibleDefaultEngines) {
+ engineNames = visibleDefaultEngines.split(",");
+ for (let engineName of engineNames) {
+ // If all engineName values are part of jarNames,
+ // then we can use the country specific list, otherwise ignore it.
+ // The visibleDefaultEngines string containing the name of an engine we
+ // don't ship indicates the server is misconfigured to answer requests
+ // from the specific Firefox version we are running, so ignoring the
+ // value altogether is safer.
+ if (!jarNames.has(engineName)) {
+ LOG("_parseListJSON: ignoring visibleDefaultEngines value because " +
+ engineName + " is not in the jar engines we have found");
+ engineNames = null;
+ break;
+ }
+ }
+ }
+
+ // Fallback to building a list based on the regions in the JSON
+ if (!engineNames || !engineNames.length) {
+ engineNames = searchSettings["default"]["visibleDefaultEngines"];
+ }
+
+ for (let name of engineNames) {
+ uris.push(APP_SEARCH_PREFIX + name + ".xml");
+ }
+
+ // Store this so that it can be used while writing the cache file.
+ this._visibleDefaultEngines = engineNames;
+ },
+
+ _parseListTxt: function SRCH_SVC_parseListTxt(list, uris) {
+ let names = list.split("\n").filter(n => !!n);
+ // This maps the names of our built-in engines to a boolean
+ // indicating whether it should be hidden by default.
+ let jarNames = new Map();
+ for (let name of names) {
+ if (name.endsWith(":hidden")) {
+ name = name.split(":")[0];
+ jarNames.set(name, true);
+ } else {
+ jarNames.set(name, false);
+ }
+ }
+
+ // Check if we have a useable country specific list of visible default engines.
+ let engineNames;
+ let visibleDefaultEngines = this.getVerifiedGlobalAttr("visibleDefaultEngines");
+ if (visibleDefaultEngines) {
+ engineNames = visibleDefaultEngines.split(",");
+
+ for (let engineName of engineNames) {
+ // If all engineName values are part of jarNames,
+ // then we can use the country specific list, otherwise ignore it.
+ // The visibleDefaultEngines string containing the name of an engine we
+ // don't ship indicates the server is misconfigured to answer requests
+ // from the specific Firefox version we are running, so ignoring the
+ // value altogether is safer.
+ if (!jarNames.has(engineName)) {
+ LOG("_parseListTxt: ignoring visibleDefaultEngines value because " +
+ engineName + " is not in the jar engines we have found");
+ engineNames = null;
+ break;
+ }
+ }
+ }
+
+ // Fallback to building a list based on the :hidden suffixes found in list.txt.
+ if (!engineNames) {
+ engineNames = [];
+ for (let [name, hidden] of jarNames) {
+ if (!hidden)
+ engineNames.push(name);
+ }
+ }
+
+ for (let name of engineNames) {
+ uris.push(APP_SEARCH_PREFIX + name + ".xml");
+ }
+
+ // Store this so that it can be used while writing the cache file.
+ this._visibleDefaultEngines = engineNames;
+ },
+
+
+ _saveSortedEngineList: function SRCH_SVC_saveSortedEngineList() {
+ LOG("SRCH_SVC_saveSortedEngineList: starting");
+
+ // Set the useDB pref to indicate that from now on we should use the order
+ // information stored in the database.
+ Services.prefs.setBoolPref(BROWSER_SEARCH_PREF + "useDBForOrder", true);
+
+ var engines = this._getSortedEngines(true);
+
+ for (var i = 0; i < engines.length; ++i) {
+ engines[i].setAttr("order", i + 1);
+ }
+
+ LOG("SRCH_SVC_saveSortedEngineList: done");
+ },
+
+ _buildSortedEngineList: function SRCH_SVC_buildSortedEngineList() {
+ LOG("_buildSortedEngineList: building list");
+ var addedEngines = { };
+ this.__sortedEngines = [];
+ var engine;
+
+ // If the user has specified a custom engine order, read the order
+ // information from the metadata instead of the default prefs.
+ if (Services.prefs.getBoolPref(BROWSER_SEARCH_PREF + "useDBForOrder", false)) {
+ LOG("_buildSortedEngineList: using db for order");
+
+ // Flag to keep track of whether or not we need to call _saveSortedEngineList.
+ let needToSaveEngineList = false;
+
+ for (let name in this._engines) {
+ let engine = this._engines[name];
+ var orderNumber = engine.getAttr("order");
+
+ // Since the DB isn't regularly cleared, and engine files may disappear
+ // without us knowing, we may already have an engine in this slot. If
+ // that happens, we just skip it - it will be added later on as an
+ // unsorted engine.
+ if (orderNumber && !this.__sortedEngines[orderNumber-1]) {
+ this.__sortedEngines[orderNumber-1] = engine;
+ addedEngines[engine.name] = engine;
+ } else {
+ // We need to call _saveSortedEngineList so this gets sorted out.
+ needToSaveEngineList = true;
+ }
+ }
+
+ // Filter out any nulls for engines that may have been removed
+ var filteredEngines = this.__sortedEngines.filter(function(a) { return !!a; });
+ if (this.__sortedEngines.length != filteredEngines.length)
+ needToSaveEngineList = true;
+ this.__sortedEngines = filteredEngines;
+
+ if (needToSaveEngineList)
+ this._saveSortedEngineList();
+ } else {
+ // The DB isn't being used, so just read the engine order from the prefs
+ var i = 0;
+ var engineName;
+ var prefName;
+
+ try {
+ var extras =
+ Services.prefs.getChildList(BROWSER_SEARCH_PREF + "order.extra.");
+
+ for (prefName of extras) {
+ engineName = Services.prefs.getCharPref(prefName);
+
+ engine = this._engines[engineName];
+ if (!engine || engine.name in addedEngines)
+ continue;
+
+ this.__sortedEngines.push(engine);
+ addedEngines[engine.name] = engine;
+ }
+ }
+ catch (e) { }
+
+ while (true) {
+ engineName = getLocalizedPref(BROWSER_SEARCH_PREF + "order." + (++i));
+ if (!engineName)
+ break;
+
+ engine = this._engines[engineName];
+ if (!engine || engine.name in addedEngines)
+ continue;
+
+ this.__sortedEngines.push(engine);
+ addedEngines[engine.name] = engine;
+ }
+ }
+
+ // Array for the remaining engines, alphabetically sorted.
+ let alphaEngines = [];
+
+ for (let name in this._engines) {
+ let engine = this._engines[name];
+ if (!(engine.name in addedEngines))
+ alphaEngines.push(this._engines[engine.name]);
+ }
+
+ let locale = Cc["@mozilla.org/intl/nslocaleservice;1"]
+ .getService(Ci.nsILocaleService)
+ .newLocale(getLocale());
+ let collation = Cc["@mozilla.org/intl/collation-factory;1"]
+ .createInstance(Ci.nsICollationFactory)
+ .CreateCollation(locale);
+ const strength = Ci.nsICollation.kCollationCaseInsensitiveAscii;
+ let comparator = (a, b) => collation.compareString(strength, a.name, b.name);
+ alphaEngines.sort(comparator);
+ return this.__sortedEngines = this.__sortedEngines.concat(alphaEngines);
+ },
+
+ /**
+ * Get a sorted array of engines.
+ * @param aWithHidden
+ * True if hidden plugins should be included in the result.
+ */
+ _getSortedEngines: function SRCH_SVC_getSorted(aWithHidden) {
+ if (aWithHidden)
+ return this._sortedEngines;
+
+ return this._sortedEngines.filter(function (engine) {
+ return !engine.hidden;
+ });
+ },
+
+ // nsIBrowserSearchService
+ init: function SRCH_SVC_init(observer) {
+ LOG("SearchService.init");
+ let self = this;
+ if (!this._initStarted) {
+ this._initStarted = true;
+ Task.spawn(function* task() {
+ try {
+ // Complete initialization by calling asynchronous initializer.
+ yield self._asyncInit();
+ } catch (ex) {
+ if (ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {
+ // No need to pursue asynchronous because synchronous fallback was
+ // called and has finished.
+ } else {
+ self._initObservers.reject(ex);
+ }
+ }
+ });
+ }
+ if (observer) {
+ this._initObservers.promise.then(
+ function onSuccess() {
+ try {
+ observer.onInitComplete(self._initRV);
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ },
+ function onError(aReason) {
+ Cu.reportError("Internal error while initializing SearchService: " + aReason);
+ observer.onInitComplete(Components.results.NS_ERROR_UNEXPECTED);
+ }
+ );
+ }
+ },
+
+ get isInitialized() {
+ return gInitialized;
+ },
+
+ getEngines: function SRCH_SVC_getEngines(aCount) {
+ this._ensureInitialized();
+ LOG("getEngines: getting all engines");
+ var engines = this._getSortedEngines(true);
+ aCount.value = engines.length;
+ return engines;
+ },
+
+ getVisibleEngines: function SRCH_SVC_getVisible(aCount) {
+ this._ensureInitialized();
+ LOG("getVisibleEngines: getting all visible engines");
+ var engines = this._getSortedEngines(false);
+ aCount.value = engines.length;
+ return engines;
+ },
+
+ getDefaultEngines: function SRCH_SVC_getDefault(aCount) {
+ this._ensureInitialized();
+ function isDefault(engine) {
+ return engine._isDefault;
+ }
+ var engines = this._sortedEngines.filter(isDefault);
+ var engineOrder = {};
+ var engineName;
+ var i = 1;
+
+ // Build a list of engines which we have ordering information for.
+ // We're rebuilding the list here because _sortedEngines contain the
+ // current order, but we want the original order.
+
+ // First, look at the "browser.search.order.extra" branch.
+ try {
+ var extras = Services.prefs.getChildList(BROWSER_SEARCH_PREF + "order.extra.");
+
+ for (var prefName of extras) {
+ engineName = Services.prefs.getCharPref(prefName);
+
+ if (!(engineName in engineOrder))
+ engineOrder[engineName] = i++;
+ }
+ } catch (e) {
+ LOG("Getting extra order prefs failed: " + e);
+ }
+
+ // Now look through the "browser.search.order" branch.
+ for (var j = 1; ; j++) {
+ engineName = getLocalizedPref(BROWSER_SEARCH_PREF + "order." + j);
+ if (!engineName)
+ break;
+
+ if (!(engineName in engineOrder))
+ engineOrder[engineName] = i++;
+ }
+
+ LOG("getDefaultEngines: engineOrder: " + engineOrder.toSource());
+
+ function compareEngines (a, b) {
+ var aIdx = engineOrder[a.name];
+ var bIdx = engineOrder[b.name];
+
+ if (aIdx && bIdx)
+ return aIdx - bIdx;
+ if (aIdx)
+ return -1;
+ if (bIdx)
+ return 1;
+
+ return a.name.localeCompare(b.name);
+ }
+ engines.sort(compareEngines);
+
+ aCount.value = engines.length;
+ return engines;
+ },
+
+ getEngineByName: function SRCH_SVC_getEngineByName(aEngineName) {
+ this._ensureInitialized();
+ return this._engines[aEngineName] || null;
+ },
+
+ getEngineByAlias: function SRCH_SVC_getEngineByAlias(aAlias) {
+ this._ensureInitialized();
+ for (var engineName in this._engines) {
+ var engine = this._engines[engineName];
+ if (engine && engine.alias == aAlias)
+ return engine;
+ }
+ return null;
+ },
+
+ addEngineWithDetails: function SRCH_SVC_addEWD(aName, aIconURL, aAlias,
+ aDescription, aMethod,
+ aTemplate, aExtensionID) {
+ this._ensureInitialized();
+ if (!aName)
+ FAIL("Invalid name passed to addEngineWithDetails!");
+ if (!aMethod)
+ FAIL("Invalid method passed to addEngineWithDetails!");
+ if (!aTemplate)
+ FAIL("Invalid template passed to addEngineWithDetails!");
+ if (this._engines[aName])
+ FAIL("An engine with that name already exists!", Cr.NS_ERROR_FILE_ALREADY_EXISTS);
+
+ var engine = new Engine(sanitizeName(aName), false);
+ engine._initFromMetadata(aName, aIconURL, aAlias, aDescription,
+ aMethod, aTemplate, aExtensionID);
+ engine._loadPath = "[other]addEngineWithDetails";
+ this._addEngineToStore(engine);
+ },
+
+ addEngine: function SRCH_SVC_addEngine(aEngineURL, aDataType, aIconURL,
+ aConfirm, aCallback) {
+ LOG("addEngine: Adding \"" + aEngineURL + "\".");
+ this._ensureInitialized();
+ try {
+ var uri = makeURI(aEngineURL);
+ var engine = new Engine(uri, false);
+ if (aCallback) {
+ engine._installCallback = function (errorCode) {
+ try {
+ if (errorCode == null)
+ aCallback.onSuccess(engine);
+ else
+ aCallback.onError(errorCode);
+ } catch (ex) {
+ Cu.reportError("Error invoking addEngine install callback: " + ex);
+ }
+ // Clear the reference to the callback now that it's been invoked.
+ engine._installCallback = null;
+ };
+ }
+ engine._initFromURIAndLoad(uri);
+ } catch (ex) {
+ // Drop the reference to the callback, if set
+ if (engine)
+ engine._installCallback = null;
+ FAIL("addEngine: Error adding engine:\n" + ex, Cr.NS_ERROR_FAILURE);
+ }
+ engine._setIcon(aIconURL, false);
+ engine._confirm = aConfirm;
+ },
+
+ removeEngine: function SRCH_SVC_removeEngine(aEngine) {
+ this._ensureInitialized();
+ if (!aEngine)
+ FAIL("no engine passed to removeEngine!");
+
+ var engineToRemove = null;
+ for (var e in this._engines) {
+ if (aEngine.wrappedJSObject == this._engines[e])
+ engineToRemove = this._engines[e];
+ }
+
+ if (!engineToRemove)
+ FAIL("removeEngine: Can't find engine to remove!", Cr.NS_ERROR_FILE_NOT_FOUND);
+
+ if (engineToRemove == this.currentEngine) {
+ this._currentEngine = null;
+ }
+
+ if (engineToRemove._readOnly) {
+ // Just hide it (the "hidden" setter will notify) and remove its alias to
+ // avoid future conflicts with other engines.
+ engineToRemove.hidden = true;
+ engineToRemove.alias = null;
+ } else {
+ // Remove the engine file from disk if we had a legacy file in the profile.
+ if (engineToRemove._filePath) {
+ let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+ file.persistentDescriptor = engineToRemove._filePath;
+ if (file.exists()) {
+ file.remove(false);
+ }
+ engineToRemove._filePath = null;
+ }
+
+ // Remove the engine from _sortedEngines
+ var index = this._sortedEngines.indexOf(engineToRemove);
+ if (index == -1)
+ FAIL("Can't find engine to remove in _sortedEngines!", Cr.NS_ERROR_FAILURE);
+ this.__sortedEngines.splice(index, 1);
+
+ // Remove the engine from the internal store
+ delete this._engines[engineToRemove.name];
+
+ // Since we removed an engine, we need to update the preferences.
+ this._saveSortedEngineList();
+ }
+ notifyAction(engineToRemove, SEARCH_ENGINE_REMOVED);
+ },
+
+ moveEngine: function SRCH_SVC_moveEngine(aEngine, aNewIndex) {
+ this._ensureInitialized();
+ if ((aNewIndex > this._sortedEngines.length) || (aNewIndex < 0))
+ FAIL("SRCH_SVC_moveEngine: Index out of bounds!");
+ if (!(aEngine instanceof Ci.nsISearchEngine))
+ FAIL("SRCH_SVC_moveEngine: Invalid engine passed to moveEngine!");
+ if (aEngine.hidden)
+ FAIL("moveEngine: Can't move a hidden engine!", Cr.NS_ERROR_FAILURE);
+
+ var engine = aEngine.wrappedJSObject;
+
+ var currentIndex = this._sortedEngines.indexOf(engine);
+ if (currentIndex == -1)
+ FAIL("moveEngine: Can't find engine to move!", Cr.NS_ERROR_UNEXPECTED);
+
+ // Our callers only take into account non-hidden engines when calculating
+ // aNewIndex, but we need to move it in the array of all engines, so we
+ // need to adjust aNewIndex accordingly. To do this, we count the number
+ // of hidden engines in the list before the engine that we're taking the
+ // place of. We do this by first finding newIndexEngine (the engine that
+ // we were supposed to replace) and then iterating through the complete
+ // engine list until we reach it, increasing aNewIndex for each hidden
+ // engine we find on our way there.
+ //
+ // This could be further simplified by having our caller pass in
+ // newIndexEngine directly instead of aNewIndex.
+ var newIndexEngine = this._getSortedEngines(false)[aNewIndex];
+ if (!newIndexEngine)
+ FAIL("moveEngine: Can't find engine to replace!", Cr.NS_ERROR_UNEXPECTED);
+
+ for (var i = 0; i < this._sortedEngines.length; ++i) {
+ if (newIndexEngine == this._sortedEngines[i])
+ break;
+ if (this._sortedEngines[i].hidden)
+ aNewIndex++;
+ }
+
+ if (currentIndex == aNewIndex)
+ return; // nothing to do!
+
+ // Move the engine
+ var movedEngine = this.__sortedEngines.splice(currentIndex, 1)[0];
+ this.__sortedEngines.splice(aNewIndex, 0, movedEngine);
+
+ notifyAction(engine, SEARCH_ENGINE_CHANGED);
+
+ // Since we moved an engine, we need to update the preferences.
+ this._saveSortedEngineList();
+ },
+
+ restoreDefaultEngines: function SRCH_SVC_resetDefaultEngines() {
+ this._ensureInitialized();
+ for (let name in this._engines) {
+ let e = this._engines[name];
+ // Unhide all default engines
+ if (e.hidden && e._isDefault)
+ e.hidden = false;
+ }
+ },
+
+ get defaultEngine() { return this.currentEngine; },
+
+ set defaultEngine(val) {
+ this.currentEngine = val;
+ },
+
+ get currentEngine() {
+ this._ensureInitialized();
+ if (!this._currentEngine) {
+ let name = this.getGlobalAttr("current");
+ let engine = this.getEngineByName(name);
+ if (engine && (this.getGlobalAttr("hash") == getVerificationHash(name) ||
+ engine._isDefault)) {
+ // If the current engine is a default one, we can relax the
+ // verification hash check to reduce the annoyance for users who
+ // backup/sync their profile in custom ways.
+ this._currentEngine = engine;
+ }
+ if (!name)
+ this._currentEngine = this.originalDefaultEngine;
+ }
+
+ // If the current engine is not set or hidden, we fallback...
+ if (!this._currentEngine || this._currentEngine.hidden) {
+ // first to the original default engine
+ let originalDefault = this.originalDefaultEngine;
+ if (!originalDefault || originalDefault.hidden) {
+ // then to the first visible engine
+ let firstVisible = this._getSortedEngines(false)[0];
+ if (firstVisible && !firstVisible.hidden) {
+ this.currentEngine = firstVisible;
+ return firstVisible;
+ }
+ // and finally as a last resort we unhide the original default engine.
+ if (originalDefault)
+ originalDefault.hidden = false;
+ }
+ if (!originalDefault)
+ return null;
+
+ // If the current engine wasn't set or was hidden, we used a fallback
+ // to pick a new current engine. As soon as we return it, this new
+ // current engine will become user-visible, so we should persist it.
+ // by calling the setter.
+ this.currentEngine = originalDefault;
+ }
+
+ return this._currentEngine;
+ },
+
+ set currentEngine(val) {
+ this._ensureInitialized();
+ // Sometimes we get wrapped nsISearchEngine objects (external XPCOM callers),
+ // and sometimes we get raw Engine JS objects (callers in this file), so
+ // handle both.
+ if (!(val instanceof Ci.nsISearchEngine) && !(val instanceof Engine))
+ FAIL("Invalid argument passed to currentEngine setter");
+
+ var newCurrentEngine = this.getEngineByName(val.name);
+ if (!newCurrentEngine)
+ FAIL("Can't find engine in store!", Cr.NS_ERROR_UNEXPECTED);
+
+ if (!newCurrentEngine._isDefault) {
+ // If a non default engine is being set as the current engine, ensure
+ // its loadPath has a verification hash.
+ if (!newCurrentEngine._loadPath)
+ newCurrentEngine._loadPath = "[other]unknown";
+ let loadPathHash = getVerificationHash(newCurrentEngine._loadPath);
+ let currentHash = newCurrentEngine.getAttr("loadPathHash");
+ if (!currentHash || currentHash != loadPathHash) {
+ newCurrentEngine.setAttr("loadPathHash", loadPathHash);
+ notifyAction(newCurrentEngine, SEARCH_ENGINE_CHANGED);
+ }
+ }
+
+ if (newCurrentEngine == this._currentEngine)
+ return;
+
+ this._currentEngine = newCurrentEngine;
+
+ // If we change the default engine in the future, that change should impact
+ // users who have switched away from and then back to the build's "default"
+ // engine. So clear the user pref when the currentEngine is set to the
+ // build's default engine, so that the currentEngine getter falls back to
+ // whatever the default is.
+ let newName = this._currentEngine.name;
+ if (this._currentEngine == this.originalDefaultEngine) {
+ newName = "";
+ }
+
+ this.setGlobalAttr("current", newName);
+ this.setGlobalAttr("hash", getVerificationHash(newName));
+
+ notifyAction(this._currentEngine, SEARCH_ENGINE_DEFAULT);
+ notifyAction(this._currentEngine, SEARCH_ENGINE_CURRENT);
+ },
+
+ getDefaultEngineInfo() {
+ let result = {};
+
+ let engine;
+ try {
+ engine = this.defaultEngine;
+ } catch (e) {
+ // The defaultEngine getter will throw if there's no engine at all,
+ // which shouldn't happen unless an add-on or a test deleted all of them.
+ // Our preferences UI doesn't let users do that.
+ Cu.reportError("getDefaultEngineInfo: No default engine");
+ }
+
+ if (!engine) {
+ result.name = "NONE";
+ } else {
+ if (engine.name)
+ result.name = engine.name;
+
+ result.loadPath = engine._loadPath;
+
+ let origin;
+ if (engine._isDefault)
+ origin = "default";
+ else {
+ let currentHash = engine.getAttr("loadPathHash");
+ if (!currentHash)
+ origin = "unverified";
+ else {
+ let loadPathHash = getVerificationHash(engine._loadPath);
+ origin = currentHash == loadPathHash ? "verified" : "invalid";
+ }
+ }
+ result.origin = origin;
+
+ // For privacy, we only collect the submission URL for default engines...
+ let sendSubmissionURL = engine._isDefault;
+
+ // ... or engines sorted by default near the top of the list.
+ if (!sendSubmissionURL) {
+ let extras =
+ Services.prefs.getChildList(BROWSER_SEARCH_PREF + "order.extra.");
+
+ for (let prefName of extras) {
+ try {
+ if (result.name == Services.prefs.getCharPref(prefName)) {
+ sendSubmissionURL = true;
+ break;
+ }
+ } catch (e) {}
+ }
+
+ let i = 0;
+ while (!sendSubmissionURL) {
+ let engineName = getLocalizedPref(BROWSER_SEARCH_PREF + "order." + (++i));
+ if (!engineName)
+ break;
+ if (result.name == engineName) {
+ sendSubmissionURL = true;
+ break;
+ }
+ }
+ }
+
+ if (sendSubmissionURL) {
+ let uri = engine._getURLOfType("text/html")
+ .getSubmission("", engine, "searchbar").uri;
+ uri.userPass = ""; // Avoid reporting a username or password.
+ result.submissionURL = uri.spec;
+ }
+ }
+
+ return result;
+ },
+
+ _recordEngineTelemetry: function() {
+ Services.telemetry.getHistogramById("SEARCH_SERVICE_ENGINE_COUNT")
+ .add(Object.keys(this._engines).length);
+ let hasUpdates = false;
+ let hasIconUpdates = false;
+ for (let name in this._engines) {
+ let engine = this._engines[name];
+ if (engine._hasUpdates) {
+ hasUpdates = true;
+ if (engine._iconUpdateURL) {
+ hasIconUpdates = true;
+ break;
+ }
+ }
+ }
+ Services.telemetry.getHistogramById("SEARCH_SERVICE_HAS_UPDATES").add(hasUpdates);
+ Services.telemetry.getHistogramById("SEARCH_SERVICE_HAS_ICON_UPDATES").add(hasIconUpdates);
+ },
+
+ /**
+ * This map is built lazily after the available search engines change. It
+ * allows quick parsing of an URL representing a search submission into the
+ * search engine name and original terms.
+ *
+ * The keys are strings containing the domain name and lowercase path of the
+ * engine submission, for example "www.google.com/search".
+ *
+ * The values are objects with these properties:
+ * {
+ * engine: The associated nsISearchEngine.
+ * termsParameterName: Name of the URL parameter containing the search
+ * terms, for example "q".
+ * }
+ */
+ _parseSubmissionMap: null,
+
+ _buildParseSubmissionMap: function SRCH_SVC__buildParseSubmissionMap() {
+ LOG("_buildParseSubmissionMap");
+ this._parseSubmissionMap = new Map();
+
+ // Used only while building the map, indicates which entries do not refer to
+ // the main domain of the engine but to an alternate domain, for example
+ // "www.google.fr" for the "www.google.com" search engine.
+ let keysOfAlternates = new Set();
+
+ for (let engine of this._sortedEngines) {
+ LOG("Processing engine: " + engine.name);
+
+ if (engine.hidden) {
+ LOG("Engine is hidden.");
+ continue;
+ }
+
+ let urlParsingInfo = engine.getURLParsingInfo();
+ if (!urlParsingInfo) {
+ LOG("Engine does not support URL parsing.");
+ continue;
+ }
+
+ // Store the same object on each matching map key, as an optimization.
+ let mapValueForEngine = {
+ engine: engine,
+ termsParameterName: urlParsingInfo.termsParameterName,
+ };
+
+ let processDomain = (domain, isAlternate) => {
+ let key = domain + urlParsingInfo.path;
+
+ // Apply the logic for which main domains take priority over alternate
+ // domains, even if they are found later in the ordered engine list.
+ let existingEntry = this._parseSubmissionMap.get(key);
+ if (!existingEntry) {
+ LOG("Adding new entry: " + key);
+ if (isAlternate) {
+ keysOfAlternates.add(key);
+ }
+ } else if (!isAlternate && keysOfAlternates.has(key)) {
+ LOG("Overriding alternate entry: " + key +
+ " (" + existingEntry.engine.name + ")");
+ keysOfAlternates.delete(key);
+ } else {
+ LOG("Keeping existing entry: " + key +
+ " (" + existingEntry.engine.name + ")");
+ return;
+ }
+
+ this._parseSubmissionMap.set(key, mapValueForEngine);
+ };
+
+ processDomain(urlParsingInfo.mainDomain, false);
+ SearchStaticData.getAlternateDomains(urlParsingInfo.mainDomain)
+ .forEach(d => processDomain(d, true));
+ }
+ },
+
+ /**
+ * Checks to see if any engine has an EngineURL of type URLTYPE_SEARCH_HTML
+ * for this request-method, template URL, and query params.
+ */
+ hasEngineWithURL: function(method, template, formData) {
+ this._ensureInitialized();
+
+ // Quick helper method to ensure formData filtered/sorted for compares.
+ let getSortedFormData = data => {
+ return data.filter(a => a.name && a.value).sort((a, b) => {
+ if (a.name > b.name) {
+ return 1;
+ } else if (b.name > a.name) {
+ return -1;
+ } else if (a.value > b.value) {
+ return 1;
+ }
+ return (b.value > a.value) ? -1 : 0;
+ });
+ };
+
+ // Sanitize method, ensure formData is pre-sorted.
+ let methodUpper = method.toUpperCase();
+ let sortedFormData = getSortedFormData(formData);
+ let sortedFormLength = sortedFormData.length;
+
+ return this._getSortedEngines(false).some(engine => {
+ return engine._urls.some(url => {
+ // Not an engineURL match if type, method, url, #params don't match.
+ if (url.type != URLTYPE_SEARCH_HTML ||
+ url.method != methodUpper ||
+ url.template != template ||
+ url.params.length != sortedFormLength) {
+ return false;
+ }
+
+ // Ensure engineURL formData is pre-sorted. Then, we're
+ // not an engineURL match if any queryParam doesn't compare.
+ let sortedParams = getSortedFormData(url.params);
+ for (let i = 0; i < sortedFormLength; i++) {
+ let formData = sortedFormData[i];
+ let param = sortedParams[i];
+ if (param.name != formData.name ||
+ param.value != formData.value ||
+ param.purpose != formData.purpose) {
+ return false;
+ }
+ }
+ // Else we're a match.
+ return true;
+ });
+ });
+ },
+
+ parseSubmissionURL: function SRCH_SVC_parseSubmissionURL(aURL) {
+ this._ensureInitialized();
+ LOG("parseSubmissionURL: Parsing \"" + aURL + "\".");
+
+ if (!this._parseSubmissionMap) {
+ this._buildParseSubmissionMap();
+ }
+
+ // Extract the elements of the provided URL first.
+ let soughtKey, soughtQuery;
+ try {
+ let soughtUrl = NetUtil.newURI(aURL).QueryInterface(Ci.nsIURL);
+
+ // Exclude any URL that is not HTTP or HTTPS from the beginning.
+ if (soughtUrl.scheme != "http" && soughtUrl.scheme != "https") {
+ LOG("The URL scheme is not HTTP or HTTPS.");
+ return gEmptyParseSubmissionResult;
+ }
+
+ // Reading these URL properties may fail and raise an exception.
+ soughtKey = soughtUrl.host + soughtUrl.filePath.toLowerCase();
+ soughtQuery = soughtUrl.query;
+ } catch (ex) {
+ // Errors while parsing the URL or accessing the properties are not fatal.
+ LOG("The value does not look like a structured URL.");
+ return gEmptyParseSubmissionResult;
+ }
+
+ // Look up the domain and path in the map to identify the search engine.
+ let mapEntry = this._parseSubmissionMap.get(soughtKey);
+ if (!mapEntry) {
+ LOG("No engine associated with domain and path: " + soughtKey);
+ return gEmptyParseSubmissionResult;
+ }
+
+ // Extract the search terms from the parameter, for example "caff%C3%A8"
+ // from the URL "https://www.google.com/search?q=caff%C3%A8&client=firefox".
+ let encodedTerms = null;
+ for (let param of soughtQuery.split("&")) {
+ let equalPos = param.indexOf("=");
+ if (equalPos != -1 &&
+ param.substr(0, equalPos) == mapEntry.termsParameterName) {
+ // This is the parameter we are looking for.
+ encodedTerms = param.substr(equalPos + 1);
+ break;
+ }
+ }
+ if (encodedTerms === null) {
+ LOG("Missing terms parameter: " + mapEntry.termsParameterName);
+ return gEmptyParseSubmissionResult;
+ }
+
+ let length = 0;
+ let offset = aURL.indexOf("?") + 1;
+ let query = aURL.slice(offset);
+ // Iterate a second time over the original input string to determine the
+ // correct search term offset and length in the original encoding.
+ for (let param of query.split("&")) {
+ let equalPos = param.indexOf("=");
+ if (equalPos != -1 &&
+ param.substr(0, equalPos) == mapEntry.termsParameterName) {
+ // This is the parameter we are looking for.
+ offset += equalPos + 1;
+ length = param.length - equalPos - 1;
+ break;
+ }
+ offset += param.length + 1;
+ }
+
+ // Decode the terms using the charset defined in the search engine.
+ let terms;
+ try {
+ terms = gTextToSubURI.UnEscapeAndConvert(
+ mapEntry.engine.queryCharset,
+ encodedTerms.replace(/\+/g, " "));
+ } catch (ex) {
+ // Decoding errors will cause this match to be ignored.
+ LOG("Parameter decoding failed. Charset: " +
+ mapEntry.engine.queryCharset);
+ return gEmptyParseSubmissionResult;
+ }
+
+ LOG("Match found. Terms: " + terms);
+ return new ParseSubmissionResult(mapEntry.engine, terms, offset, length);
+ },
+
+ // nsIObserver
+ observe: function SRCH_SVC_observe(aEngine, aTopic, aVerb) {
+ switch (aTopic) {
+ case SEARCH_ENGINE_TOPIC:
+ switch (aVerb) {
+ case SEARCH_ENGINE_LOADED:
+ var engine = aEngine.QueryInterface(Ci.nsISearchEngine);
+ LOG("nsSearchService::observe: Done installation of " + engine.name
+ + ".");
+ this._addEngineToStore(engine.wrappedJSObject);
+ if (engine.wrappedJSObject._useNow) {
+ LOG("nsSearchService::observe: setting current");
+ this.currentEngine = aEngine;
+ }
+ // The addition of the engine to the store always triggers an ADDED
+ // or a CHANGED notification, that will trigger the task below.
+ break;
+ case SEARCH_ENGINE_ADDED:
+ case SEARCH_ENGINE_CHANGED:
+ case SEARCH_ENGINE_REMOVED:
+ this.batchTask.disarm();
+ this.batchTask.arm();
+ // Invalidate the map used to parse URLs to search engines.
+ this._parseSubmissionMap = null;
+ break;
+ }
+ break;
+
+ case QUIT_APPLICATION_TOPIC:
+ this._removeObservers();
+ break;
+
+ case "nsPref:changed":
+ if (aVerb == LOCALE_PREF) {
+ // Locale changed. Re-init. We rely on observers, because we can't
+ // return this promise to anyone.
+ this._asyncReInit();
+ break;
+ }
+ }
+ },
+
+ // nsITimerCallback
+ notify: function SRCH_SVC_notify(aTimer) {
+ LOG("_notify: checking for updates");
+
+ if (!Services.prefs.getBoolPref(BROWSER_SEARCH_PREF + "update", true))
+ return;
+
+ // Our timer has expired, but unfortunately, we can't get any data from it.
+ // Therefore, we need to walk our engine-list, looking for expired engines
+ var currentTime = Date.now();
+ LOG("currentTime: " + currentTime);
+ for (let name in this._engines) {
+ let engine = this._engines[name].wrappedJSObject;
+ if (!engine._hasUpdates)
+ continue;
+
+ LOG("checking " + engine.name);
+
+ var expirTime = engine.getAttr("updateexpir");
+ LOG("expirTime: " + expirTime + "\nupdateURL: " + engine._updateURL +
+ "\niconUpdateURL: " + engine._iconUpdateURL);
+
+ var engineExpired = expirTime <= currentTime;
+
+ if (!expirTime || !engineExpired) {
+ LOG("skipping engine");
+ continue;
+ }
+
+ LOG(engine.name + " has expired");
+
+ engineUpdateService.update(engine);
+
+ // Schedule the next update
+ engineUpdateService.scheduleNextUpdate(engine);
+
+ } // end engine iteration
+ },
+
+ _addObservers: function SRCH_SVC_addObservers() {
+ if (this._observersAdded) {
+ // There might be a race between synchronous and asynchronous
+ // initialization for which we try to register the observers twice.
+ return;
+ }
+ this._observersAdded = true;
+
+ Services.obs.addObserver(this, SEARCH_ENGINE_TOPIC, false);
+ Services.obs.addObserver(this, QUIT_APPLICATION_TOPIC, false);
+
+ // The current stage of shutdown. Used to help analyze crash
+ // signatures in case of shutdown timeout.
+ let shutdownState = {
+ step: "Not started",
+ latestError: {
+ message: undefined,
+ stack: undefined
+ }
+ };
+ OS.File.profileBeforeChange.addBlocker(
+ "Search service: shutting down",
+ () => Task.spawn(function* () {
+ if (this._batchTask) {
+ shutdownState.step = "Finalizing batched task";
+ try {
+ yield this._batchTask.finalize();
+ shutdownState.step = "Batched task finalized";
+ } catch (ex) {
+ shutdownState.step = "Batched task failed to finalize";
+
+ shutdownState.latestError.message = "" + ex;
+ if (ex && typeof ex == "object") {
+ shutdownState.latestError.stack = ex.stack || undefined;
+ }
+
+ // Ensure that error is reported and that it causes tests
+ // to fail.
+ Promise.reject(ex);
+ }
+ }
+ }.bind(this)),
+
+ () => shutdownState
+ );
+ },
+ _observersAdded: false,
+
+ _removeObservers: function SRCH_SVC_removeObservers() {
+ Services.obs.removeObserver(this, SEARCH_ENGINE_TOPIC);
+ Services.obs.removeObserver(this, QUIT_APPLICATION_TOPIC);
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([
+ Ci.nsIBrowserSearchService,
+ Ci.nsIObserver,
+ Ci.nsITimerCallback
+ ])
+};
+
+
+const SEARCH_UPDATE_LOG_PREFIX = "*** Search update: ";
+
+/**
+ * Outputs aText to the JavaScript console as well as to stdout, if the search
+ * logging pref (browser.search.update.log) is set to true.
+ */
+function ULOG(aText) {
+ if (Services.prefs.getBoolPref(BROWSER_SEARCH_PREF + "update.log", false)) {
+ dump(SEARCH_UPDATE_LOG_PREFIX + aText + "\n");
+ Services.console.logStringMessage(aText);
+ }
+}
+
+var engineUpdateService = {
+ scheduleNextUpdate: function eus_scheduleNextUpdate(aEngine) {
+ var interval = aEngine._updateInterval || SEARCH_DEFAULT_UPDATE_INTERVAL;
+ var milliseconds = interval * 86400000; // |interval| is in days
+ aEngine.setAttr("updateexpir", Date.now() + milliseconds);
+ },
+
+ update: function eus_Update(aEngine) {
+ let engine = aEngine.wrappedJSObject;
+ ULOG("update called for " + aEngine._name);
+ if (!Services.prefs.getBoolPref(BROWSER_SEARCH_PREF + "update", true) || !engine._hasUpdates)
+ return;
+
+ let testEngine = null;
+ let updateURL = engine._getURLOfType(URLTYPE_OPENSEARCH);
+ let updateURI = (updateURL && updateURL._hasRelation("self")) ?
+ updateURL.getSubmission("", engine).uri :
+ makeURI(engine._updateURL);
+ if (updateURI) {
+ if (engine._isDefault && !updateURI.schemeIs("https")) {
+ ULOG("Invalid scheme for default engine update");
+ return;
+ }
+
+ ULOG("updating " + engine.name + " from " + updateURI.spec);
+ testEngine = new Engine(updateURI, false);
+ testEngine._engineToUpdate = engine;
+ testEngine._initFromURIAndLoad(updateURI);
+ } else
+ ULOG("invalid updateURI");
+
+ if (engine._iconUpdateURL) {
+ // If we're updating the engine too, use the new engine object,
+ // otherwise use the existing engine object.
+ (testEngine || engine)._setIcon(engine._iconUpdateURL, true);
+ }
+ }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SearchService]);
diff --git a/application/basilisk/components/search/service/nsSearchSuggestions.js b/application/basilisk/components/search/service/nsSearchSuggestions.js
new file mode 100644
index 000000000..a05d8b4b4
--- /dev/null
+++ b/application/basilisk/components/search/service/nsSearchSuggestions.js
@@ -0,0 +1,197 @@
+/* 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/. */
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/nsFormAutoCompleteResult.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "SearchSuggestionController",
+ "resource://gre/modules/SearchSuggestionController.jsm");
+
+/**
+ * SuggestAutoComplete is a base class that implements nsIAutoCompleteSearch
+ * and can collect results for a given search by using this._suggestionController.
+ * We do it this way since the AutoCompleteController in Mozilla requires a
+ * unique XPCOM Service for every search provider, even if the logic for two
+ * providers is identical.
+ * @constructor
+ */
+function SuggestAutoComplete() {
+ this._init();
+}
+SuggestAutoComplete.prototype = {
+
+ _init: function() {
+ this._suggestionController = new SearchSuggestionController(obj => this.onResultsReturned(obj));
+ this._suggestionController.maxLocalResults = this._historyLimit;
+ },
+
+ get _suggestionLabel() {
+ let bundle = Services.strings.createBundle("chrome://global/locale/search/search.properties");
+ let label = bundle.GetStringFromName("suggestion_label");
+ Object.defineProperty(SuggestAutoComplete.prototype, "_suggestionLabel", {value: label});
+ return label;
+ },
+
+ /**
+ * The object implementing nsIAutoCompleteObserver that we notify when
+ * we have found results
+ * @private
+ */
+ _listener: null,
+
+ /**
+ * Maximum number of history items displayed. This is capped at 7
+ * because the primary consumer (Firefox search bar) displays 10 rows
+ * by default, and so we want to leave some space for suggestions
+ * to be visible.
+ */
+ _historyLimit: 7,
+
+ /**
+ * Callback for handling results from SearchSuggestionController.jsm
+ * @private
+ */
+ onResultsReturned: function(results) {
+ let finalResults = [];
+ let finalComments = [];
+
+ // If form history has results, add them to the list.
+ for (let i = 0; i < results.local.length; ++i) {
+ finalResults.push(results.local[i]);
+ finalComments.push("");
+ }
+
+ // If there are remote matches, add them.
+ if (results.remote.length) {
+ // "comments" column values for suggestions starts as empty strings
+ let comments = new Array(results.remote.length).fill("", 1);
+ comments[0] = this._suggestionLabel;
+ // now put the history results above the suggestions
+ finalResults = finalResults.concat(results.remote);
+ finalComments = finalComments.concat(comments);
+ }
+
+ // Notify the FE of our new results
+ this.onResultsReady(results.term, finalResults, finalComments, results.formHistoryResult);
+ },
+
+ /**
+ * Notifies the front end of new results.
+ * @param searchString the user's query string
+ * @param results an array of results to the search
+ * @param comments an array of metadata corresponding to the results
+ * @private
+ */
+ onResultsReady: function(searchString, results, comments, formHistoryResult) {
+ if (this._listener) {
+ // Create a copy of the results array to use as labels, since
+ // FormAutoCompleteResult doesn't like being passed the same array
+ // for both.
+ let labels = results.slice();
+ let result = new FormAutoCompleteResult(
+ searchString,
+ Ci.nsIAutoCompleteResult.RESULT_SUCCESS,
+ 0,
+ "",
+ results,
+ labels,
+ comments,
+ formHistoryResult);
+
+ this._listener.onSearchResult(this, result);
+
+ // Null out listener to make sure we don't notify it twice
+ this._listener = null;
+ }
+ },
+
+ /**
+ * Initiates the search result gathering process. Part of
+ * nsIAutoCompleteSearch implementation.
+ *
+ * @param searchString the user's query string
+ * @param searchParam unused, "an extra parameter"; even though
+ * this parameter and the next are unused, pass
+ * them through in case the form history
+ * service wants them
+ * @param previousResult unused, a client-cached store of the previous
+ * generated resultset for faster searching.
+ * @param listener object implementing nsIAutoCompleteObserver which
+ * we notify when results are ready.
+ */
+ startSearch: function(searchString, searchParam, previousResult, listener) {
+ // Don't reuse a previous form history result when it no longer applies.
+ if (!previousResult)
+ this._formHistoryResult = null;
+
+ var formHistorySearchParam = searchParam.split("|")[0];
+
+ // Receive the information about the privacy mode of the window to which
+ // this search box belongs. The front-end's search.xml bindings passes this
+ // information in the searchParam parameter. The alternative would have
+ // been to modify nsIAutoCompleteSearch to add an argument to startSearch
+ // and patch all of autocomplete to be aware of this, but the searchParam
+ // argument is already an opaque argument, so this solution is hopefully
+ // less hackish (although still gross.)
+ var privacyMode = (searchParam.split("|")[1] == "private");
+
+ // Start search immediately if possible, otherwise once the search
+ // service is initialized
+ if (Services.search.isInitialized) {
+ this._triggerSearch(searchString, formHistorySearchParam, listener, privacyMode);
+ return;
+ }
+
+ Services.search.init((function startSearch_cb(aResult) {
+ if (!Components.isSuccessCode(aResult)) {
+ Cu.reportError("Could not initialize search service, bailing out: " + aResult);
+ return;
+ }
+ this._triggerSearch(searchString, formHistorySearchParam, listener, privacyMode);
+ }).bind(this));
+ },
+
+ /**
+ * Actual implementation of search.
+ */
+ _triggerSearch: function(searchString, searchParam, listener, privacyMode) {
+ this._listener = listener;
+ this._suggestionController.fetch(searchString,
+ privacyMode,
+ Services.search.currentEngine);
+ },
+
+ /**
+ * Ends the search result gathering process. Part of nsIAutoCompleteSearch
+ * implementation.
+ */
+ stopSearch: function() {
+ this._suggestionController.stop();
+ },
+
+ // nsISupports
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteSearch,
+ Ci.nsIAutoCompleteObserver])
+};
+
+/**
+ * SearchSuggestAutoComplete is a service implementation that handles suggest
+ * results specific to web searches.
+ * @constructor
+ */
+function SearchSuggestAutoComplete() {
+ // This calls _init() in the parent class (SuggestAutoComplete) via the
+ // prototype, below.
+ this._init();
+}
+SearchSuggestAutoComplete.prototype = {
+ classID: Components.ID("{aa892eb4-ffbf-477d-9f9a-06c995ae9f27}"),
+ __proto__: SuggestAutoComplete.prototype,
+ serviceURL: ""
+};
+
+var component = [SearchSuggestAutoComplete];
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory(component);
diff --git a/application/basilisk/components/search/service/nsSidebar.js b/application/basilisk/components/search/service/nsSidebar.js
new file mode 100644
index 000000000..63976cba7
--- /dev/null
+++ b/application/basilisk/components/search/service/nsSidebar.js
@@ -0,0 +1,66 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
+/* 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/. */
+
+const { interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+// File extension for Sherlock search plugin description files
+const SHERLOCK_FILE_EXT_REGEXP = /\.src$/i;
+
+function nsSidebar() {
+}
+
+nsSidebar.prototype = {
+ init: function(window) {
+ this.window = window;
+ try {
+ this.mm = window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDocShell)
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIContentFrameMessageManager);
+ } catch (e) {
+ Cu.reportError(e);
+ }
+ },
+
+ // Deprecated, only left here to avoid breaking old browser-detection scripts.
+ addSearchEngine: function(engineURL, iconURL, suggestedTitle, suggestedCategory) {
+ if (SHERLOCK_FILE_EXT_REGEXP.test(engineURL)) {
+ Cu.reportError("Installing Sherlock search plugins is no longer supported.");
+ return;
+ }
+
+ this.AddSearchProvider(engineURL);
+ },
+
+ // This function implements window.external.AddSearchProvider().
+ // The capitalization, although nonstandard here, is to match other browsers'
+ // APIs and is therefore important.
+ AddSearchProvider: function(engineURL) {
+ if (!this.mm) {
+ Cu.reportError(`Installing a search provider from this context is not currently supported: ${Error().stack}.`);
+ return;
+ }
+
+ this.mm.sendAsyncMessage("Search:AddEngine", {
+ pageURL: this.window.document.documentURIObject.spec,
+ engineURL
+ });
+ },
+
+ // This function exists to implement window.external.IsSearchProviderInstalled(),
+ // for compatibility with other browsers. The function has been deprecated
+ // and so will not be implemented.
+ IsSearchProviderInstalled: function(engineURL) {
+ return 0;
+ },
+
+ classID: Components.ID("{22117140-9c6e-11d3-aaf1-00805f8a4905}"),
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+ Ci.nsIDOMGlobalPropertyInitializer])
+}
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsSidebar]);
diff --git a/application/basilisk/components/search/service/toolkitsearch.manifest b/application/basilisk/components/search/service/toolkitsearch.manifest
new file mode 100644
index 000000000..b7c55da0e
--- /dev/null
+++ b/application/basilisk/components/search/service/toolkitsearch.manifest
@@ -0,0 +1,10 @@
+component {7319788a-fe93-4db3-9f39-818cf08f4256} nsSearchService.js process=main
+contract @mozilla.org/browser/search-service;1 {7319788a-fe93-4db3-9f39-818cf08f4256} process=main
+# 21600 == 6 hours
+category update-timer nsSearchService @mozilla.org/browser/search-service;1,getService,search-engine-update-timer,browser.search.update.interval,21600
+component {aa892eb4-ffbf-477d-9f9a-06c995ae9f27} nsSearchSuggestions.js
+contract @mozilla.org/autocomplete/search;1?name=search-autocomplete {aa892eb4-ffbf-477d-9f9a-06c995ae9f27}
+#ifdef HAVE_SIDEBAR
+component {22117140-9c6e-11d3-aaf1-00805f8a4905} nsSidebar.js
+contract @mozilla.org/sidebar;1 {22117140-9c6e-11d3-aaf1-00805f8a4905}
+#endif
diff --git a/application/basilisk/components/sessionstore/ContentRestore.jsm b/application/basilisk/components/sessionstore/ContentRestore.jsm
index d4972bcaf..8b3867624 100644
--- a/application/basilisk/components/sessionstore/ContentRestore.jsm
+++ b/application/basilisk/components/sessionstore/ContentRestore.jsm
@@ -208,10 +208,6 @@ ContentRestoreInternal.prototype = {
? Utils.deserializePrincipal(loadArguments.triggeringPrincipal)
: null;
- if (loadArguments.userContextId) {
- webNavigation.setOriginAttributesBeforeLoading({ userContextId: loadArguments.userContextId });
- }
-
webNavigation.loadURIWithOptions(loadArguments.uri, loadArguments.flags,
referrer, referrerPolicy, postData,
null, null, triggeringPrincipal);
diff --git a/application/basilisk/components/sessionstore/SessionHistory.jsm b/application/basilisk/components/sessionstore/SessionHistory.jsm
index 3d28d87db..907a60839 100644
--- a/application/basilisk/components/sessionstore/SessionHistory.jsm
+++ b/application/basilisk/components/sessionstore/SessionHistory.jsm
@@ -64,11 +64,10 @@ var SessionHistoryInternal = {
* The docShell that owns the session history.
*/
collect: function (docShell) {
- let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
let history = webNavigation.sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
- let data = {entries: [], userContextId: loadContext.originAttributes.userContextId };
+ let data = {entries: []};
if (history && history.count > 0) {
// Loop over the transaction linked list directly so we can get the
diff --git a/application/basilisk/components/sessionstore/SessionStore.jsm b/application/basilisk/components/sessionstore/SessionStore.jsm
index b599bc162..086bb914a 100644
--- a/application/basilisk/components/sessionstore/SessionStore.jsm
+++ b/application/basilisk/components/sessionstore/SessionStore.jsm
@@ -2204,10 +2204,9 @@ var SessionStoreInternal = {
}
// Create a new tab.
- let userContextId = aTab.getAttribute("usercontextid");
let newTab = aTab == aWindow.gBrowser.selectedTab ?
- aWindow.gBrowser.addTab(null, {relatedToCurrent: true, ownerTab: aTab, userContextId}) :
- aWindow.gBrowser.addTab(null, {userContextId});
+ aWindow.gBrowser.addTab(null, {relatedToCurrent: true, ownerTab: aTab}) :
+ aWindow.gBrowser.addTab();
// Set tab title to "Connecting..." and start the throbber to pretend we're
// doing something while actually waiting for data from the frame script.
@@ -2296,7 +2295,7 @@ var SessionStoreInternal = {
// create a new tab
let tabbrowser = aWindow.gBrowser;
- let tab = tabbrowser.selectedTab = tabbrowser.addTab(null, state);
+ let tab = tabbrowser.selectedTab = tabbrowser.addTab();
// restore tab content
this.restoreTab(tab, state);
@@ -3100,31 +3099,13 @@ var SessionStoreInternal = {
let numVisibleTabs = 0;
for (var t = 0; t < newTabCount; t++) {
- // When trying to restore into existing tab, we also take the userContextId
- // into account if present.
- let userContextId = winData.tabs[t].userContextId;
- let reuseExisting = t < openTabCount &&
- (tabbrowser.tabs[t].getAttribute("usercontextid") == (userContextId || ""));
- // If the tab is pinned, then we'll be loading it right away, and
- // there's no need to cause a remoteness flip by loading it initially
- // non-remote.
- let forceNotRemote = !winData.tabs[t].pinned;
- let tab = reuseExisting ? tabbrowser.tabs[t] :
- tabbrowser.addTab("about:blank",
- {skipAnimation: true,
- forceNotRemote,
- userContextId,
- skipBackgroundNotify: true});
-
- // If we inserted a new tab because the userContextId didn't match with the
- // open tab, even though `t < openTabCount`, we need to remove that open tab
- // and put the newly added tab in its place.
- if (!reuseExisting && t < openTabCount) {
- tabbrowser.removeTab(tabbrowser.tabs[t]);
- tabbrowser.moveTabTo(tab, t);
- }
-
- tabs.push(tab);
+ tabs.push(t < openTabCount ?
+ tabbrowser.tabs[t] :
+ tabbrowser.addTab("about:blank", {
+ skipAnimation: true,
+ forceNotRemote: true,
+ skipBackgroundNotify: true
+ }));
if (winData.tabs[t].pinned)
tabbrowser.pinTab(tabs[t]);
@@ -3531,9 +3512,6 @@ var SessionStoreInternal = {
let uri = activePageData ? activePageData.url || null : null;
if (aLoadArguments) {
uri = aLoadArguments.uri;
- if (aLoadArguments.userContextId) {
- browser.setAttribute("usercontextid", aLoadArguments.userContextId);
- }
}
// We have to mark this tab as restoring first, otherwise
diff --git a/application/basilisk/components/sessionstore/TabState.jsm b/application/basilisk/components/sessionstore/TabState.jsm
index f22c52fe3..ac846031b 100644
--- a/application/basilisk/components/sessionstore/TabState.jsm
+++ b/application/basilisk/components/sessionstore/TabState.jsm
@@ -181,10 +181,6 @@ var TabStateInternal = {
if (key === "history") {
tabData.entries = value.entries;
- if (value.hasOwnProperty("userContextId")) {
- tabData.userContextId = value.userContextId;
- }
-
if (value.hasOwnProperty("index")) {
tabData.index = value.index;
}
diff --git a/application/basilisk/base/content/sync/aboutSyncTabs-bindings.xml b/application/basilisk/components/sync/aboutSyncTabs-bindings.xml
index e6108209a..e6108209a 100644
--- a/application/basilisk/base/content/sync/aboutSyncTabs-bindings.xml
+++ b/application/basilisk/components/sync/aboutSyncTabs-bindings.xml
diff --git a/application/basilisk/base/content/sync/aboutSyncTabs.css b/application/basilisk/components/sync/aboutSyncTabs.css
index 5a353175b..5a353175b 100644
--- a/application/basilisk/base/content/sync/aboutSyncTabs.css
+++ b/application/basilisk/components/sync/aboutSyncTabs.css
diff --git a/application/basilisk/base/content/sync/aboutSyncTabs.js b/application/basilisk/components/sync/aboutSyncTabs.js
index f4bb607ea..4808c052f 100644
--- a/application/basilisk/base/content/sync/aboutSyncTabs.js
+++ b/application/basilisk/components/sync/aboutSyncTabs.js
@@ -11,14 +11,6 @@ Cu.import("resource://gre/modules/PlacesUtils.jsm", this);
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
- "resource://gre/modules/Promise.jsm");
-
-#ifdef MOZ_SERVICES_CLOUDSYNC
-XPCOMUtils.defineLazyModuleGetter(this, "CloudSync",
- "resource://gre/modules/CloudSync.jsm");
-#endif
-
var RemoteTabViewer = {
_tabsList: null,
@@ -26,8 +18,6 @@ var RemoteTabViewer = {
Services.obs.addObserver(this, "weave:service:login:finish", false);
Services.obs.addObserver(this, "weave:engine:sync:finish", false);
- Services.obs.addObserver(this, "cloudsync:tabs:update", false);
-
this._tabsList = document.getElementById("tabsList");
this.buildList(true);
@@ -36,14 +26,12 @@ var RemoteTabViewer = {
uninit: function () {
Services.obs.removeObserver(this, "weave:service:login:finish");
Services.obs.removeObserver(this, "weave:engine:sync:finish");
-
- Services.obs.removeObserver(this, "cloudsync:tabs:update");
},
- createItem: function (attrs) {
+ createItem: function(attrs) {
let item = document.createElement("richlistitem");
- // Copy the attributes from the argument into the item.
+ // Copy the attributes from the argument into the item
for (let attr in attrs) {
item.setAttribute(attr, attrs[attr]);
}
@@ -55,7 +43,7 @@ var RemoteTabViewer = {
return item;
},
- filterTabs: function (event) {
+ filterTabs: function(event) {
let val = event.target.value.toLowerCase();
let numTabs = this._tabsList.getRowCount();
let clientTabs = 0;
@@ -65,7 +53,7 @@ var RemoteTabViewer = {
let item = this._tabsList.getItemAtIndex(i);
let hide = false;
if (item.getAttribute("type") == "tab") {
- if (!item.getAttribute("url").toLowerCase().includes(val) &&
+ if (!item.getAttribute("url").toLowerCase().includes(val) &&
!item.getAttribute("title").toLowerCase().includes(val)) {
hide = true;
} else {
@@ -88,10 +76,10 @@ var RemoteTabViewer = {
}
},
- openSelected: function () {
+ openSelected: function() {
let items = this._tabsList.selectedItems;
let urls = [];
- for (let i = 0; i < items.length; i++) {
+ for (let i = 0;i < items.length;i++) {
if (items[i].getAttribute("type") == "tab") {
urls.push(items[i].getAttribute("url"));
let index = this._tabsList.getIndexOfItem(items[i]);
@@ -104,7 +92,7 @@ var RemoteTabViewer = {
}
},
- bookmarkSingleTab: function () {
+ bookmarkSingleTab: function() {
let item = this._tabsList.selectedItems[0];
let uri = Weave.Utils.makeURI(item.getAttribute("url"));
let title = item.getAttribute("title");
@@ -119,10 +107,10 @@ var RemoteTabViewer = {
}, window.top);
},
- bookmarkSelectedTabs: function () {
+ bookmarkSelectedTabs: function() {
let items = this._tabsList.selectedItems;
let URIs = [];
- for (let i = 0; i < items.length; i++) {
+ for (let i = 0;i < items.length;i++) {
if (items[i].getAttribute("type") == "tab") {
let uri = Weave.Utils.makeURI(items[i].getAttribute("url"));
if (!uri) {
@@ -157,7 +145,7 @@ var RemoteTabViewer = {
_buildListRequested: false,
- buildList: function (forceSync) {
+ buildList: function (force) {
if (this._waitingForBuildList) {
this._buildListRequested = true;
return;
@@ -168,37 +156,27 @@ var RemoteTabViewer = {
this._clearTabList();
- if (Weave.Service.isLoggedIn) {
- this._refetchTabs(forceSync);
+ if (Weave.Service.isLoggedIn && this._refetchTabs(force)) {
this._generateWeaveTabList();
} else {
- // XXXzpao We should say something about not being logged in & not having data
+ //XXXzpao We should say something about not being logged in & not having data
// or tell the appropriate condition. (bug 583344)
}
- let complete = () => {
+ function complete() {
this._waitingForBuildList = false;
if (this._buildListRequested) {
CommonUtils.nextTick(this.buildList, this);
}
}
-#ifdef MOZ_SERVICES_CLOUDSYNC
- if (CloudSync && CloudSync.ready && CloudSync().tabsReady && CloudSync().tabs.hasRemoteTabs()) {
- this._generateCloudSyncTabList()
- .then(complete, complete);
- } else {
- complete();
- }
-#else
complete();
-#endif
},
_clearTabList: function () {
let list = this._tabsList;
- // Clear out existing richlistitems.
+ // Clear out existing richlistitems
let count = list.getRowCount();
if (count > 0) {
for (let i = count - 1; i >= 0; i--) {
@@ -214,7 +192,7 @@ var RemoteTabViewer = {
let seenURLs = new Set();
let localURLs = engine.getOpenURLs();
- for (let [, client] of Object.entries(engine.getAllClients())) {
+ for (let [guid, client] in Iterator(engine.getAllClients())) {
// Create the client node, but don't add it in-case we don't show any tabs
let appendClient = true;
@@ -248,37 +226,7 @@ var RemoteTabViewer = {
}
},
- _generateCloudSyncTabList: function () {
- let updateTabList = function (remoteTabs) {
- let list = this._tabsList;
-
- for (let client of remoteTabs) {
- let clientAttrs = {
- type: "client",
- clientName: client.name,
- };
-
- let clientEnt = this.createItem(clientAttrs);
- list.appendChild(clientEnt);
-
- for (let tab of client.tabs) {
- let tabAttrs = {
- type: "tab",
- title: tab.title,
- url: tab.url,
- icon: this.getIcon(tab.icon),
- };
- let tabEnt = this.createItem(tabAttrs);
- list.appendChild(tabEnt);
- }
- }
- }.bind(this);
-
- return CloudSync().tabs.getRemoteTabs()
- .then(updateTabList, Promise.reject.bind(Promise));
- },
-
- adjustContextMenu: function (event) {
+ adjustContextMenu: function(event) {
let mode = "all";
switch (this._tabsList.selectedItems.length) {
case 0:
@@ -303,16 +251,10 @@ var RemoteTabViewer = {
}
},
- _refetchTabs: function (force) {
+ _refetchTabs: function(force) {
if (!force) {
// Don't bother refetching tabs if we already did so recently
- let lastFetch = 0;
- try {
- lastFetch = Services.prefs.getIntPref("services.sync.lastTabFetch");
- }
- catch (e) {
- /* Just use the default value of 0 */
- }
+ lastFetch = Services.prefs.getIntPref("services.sync.lastTabFetch", 0);
let now = Math.floor(Date.now() / 1000);
if (now - lastFetch < 30) {
@@ -320,40 +262,40 @@ var RemoteTabViewer = {
}
}
- // Ask Sync to just do the tabs engine if it can.
- Weave.Service.sync(["tabs"]);
+ // if Clients hasn't synced yet this session, we need to sync it as well.
+ if (Weave.Service.clientsEngine.lastSync == 0) {
+ Weave.Service.clientsEngine.sync();
+ }
+
+ // Force a sync only for the tabs engine
+ let engine = Weave.Service.engineManager.get("tabs");
+ engine.lastModified = null;
+ engine.sync();
Services.prefs.setIntPref("services.sync.lastTabFetch",
Math.floor(Date.now() / 1000));
return true;
},
- observe: function (subject, topic, data) {
+ observe: function(subject, topic, data) {
switch (topic) {
case "weave:service:login:finish":
- // A login has finished, which means that a Sync is about to start and
- // we will eventually get to the "tabs" engine - but try and force the
- // tab engine to sync first by passing |true| for the forceSync param.
this.buildList(true);
break;
case "weave:engine:sync:finish":
- if (data == "tabs") {
- // The tabs engine just finished, so re-build the list without
- // forcing a new sync of the tabs engine.
+ if (subject == "tabs") {
this.buildList(false);
}
break;
- case "cloudsync:tabs:update":
- this.buildList(false);
- break;
}
},
- handleClick: function (event) {
+ handleClick: function(event) {
if (event.target.getAttribute("type") != "tab") {
return;
}
+
if (event.button == 1) {
let url = event.target.getAttribute("url");
openUILink(url, event);
@@ -362,3 +304,4 @@ var RemoteTabViewer = {
}
}
}
+
diff --git a/application/basilisk/base/content/sync/aboutSyncTabs.xul b/application/basilisk/components/sync/aboutSyncTabs.xul
index a4aa0032f..a4aa0032f 100644
--- a/application/basilisk/base/content/sync/aboutSyncTabs.xul
+++ b/application/basilisk/components/sync/aboutSyncTabs.xul
diff --git a/application/basilisk/base/content/sync/addDevice.js b/application/basilisk/components/sync/addDevice.js
index 0390d4397..0390d4397 100644
--- a/application/basilisk/base/content/sync/addDevice.js
+++ b/application/basilisk/components/sync/addDevice.js
diff --git a/application/basilisk/base/content/sync/addDevice.xul b/application/basilisk/components/sync/addDevice.xul
index 83c3b7b3c..f2371aad0 100644
--- a/application/basilisk/base/content/sync/addDevice.xul
+++ b/application/basilisk/components/sync/addDevice.xul
@@ -43,7 +43,7 @@
&pairDevice.dialog.description.label;
<label class="text-link"
value="&addDevice.showMeHow.label;"
- href="https://services.mozilla.com/sync/help/add-device"/>
+ href="http://www.palemoon.org/sync/help/easy-setup.shtml"/>
</description>
<separator class="groove-thin"/>
<description>
diff --git a/application/basilisk/base/content/sync/genericChange.js b/application/basilisk/components/sync/genericChange.js
index 51a74f1b1..df6639178 100644
--- a/application/basilisk/base/content/sync/genericChange.js
+++ b/application/basilisk/components/sync/genericChange.js
@@ -32,6 +32,7 @@ var Change = {
onLoad: function Change_onLoad() {
/* Load labels */
let introText = document.getElementById("introText");
+ let introText2 = document.getElementById("introText2");
let warningText = document.getElementById("warningText");
// load some other elements & info from the window
@@ -69,7 +70,6 @@ var Change = {
else {
document.getElementById("generatePassphraseButton").hidden = false;
document.getElementById("passphraseBackupButtons").hidden = false;
- this._passphraseBox.setAttribute("readonly", "true");
let pp = Weave.Service.identity.syncKey;
if (Weave.Utils.isPassphrase(pp))
pp = Weave.Utils.hyphenatePassphrase(pp);
@@ -120,7 +120,7 @@ var Change = {
_updateStatus: function Change__updateStatus(str, state) {
this._updateStatusWithString(this._str(str), state);
},
-
+
_updateStatusWithString: function Change__updateStatusWithString(string, state) {
this._statusRow.hidden = false;
this._status.value = string;
@@ -141,10 +141,11 @@ var Change = {
case "UpdatePassphrase":
case "ResetPassphrase":
return this.doChangePassphrase();
+ break;
case "ChangePassword":
return this.doChangePassword();
+ break;
}
- return undefined;
},
doGeneratePassphrase: function () {
@@ -212,10 +213,10 @@ var Change = {
[valid, errorString] = gSyncUtils.validatePassword(this._firstBox, this._secondBox);
}
else {
- if (!this._updatingPassphrase)
- return;
-
- valid = this._passphraseBox.value != "";
+ //Pale Moon: Enforce minimum length of 8 for allowed custom passphrase
+ //and don't restrict it to "out of sync" situations only. People who
+ //go to this page generally know what they are doing ;)
+ valid = this._passphraseBox.value.length >= 8;
}
if (errorString == "")
diff --git a/application/basilisk/base/content/sync/genericChange.xul b/application/basilisk/components/sync/genericChange.xul
index db74a1b31..3c0b2cd6c 100644
--- a/application/basilisk/base/content/sync/genericChange.xul
+++ b/application/basilisk/components/sync/genericChange.xul
@@ -67,7 +67,7 @@
<label id="generatePassphraseButton"
hidden="true"
value="&syncGenerateNewKey.label;"
- class="text-link"
+ class="text-link inline-link"
onclick="event.stopPropagation();
Change.doGeneratePassphrase();"/>
</hbox>
@@ -105,7 +105,7 @@
<description>
&existingRecoveryKey.description;
<label class="text-link"
- href="https://services.mozilla.com/sync/help/manual-setup">
+ href="http://www.palemoon.org/sync/help/recoverykey.shtml">
&addDevice.showMeHow.label;
</label>
</description>
diff --git a/application/basilisk/components/sync/jar.mn b/application/basilisk/components/sync/jar.mn
new file mode 100644
index 000000000..3782038cd
--- /dev/null
+++ b/application/basilisk/components/sync/jar.mn
@@ -0,0 +1,22 @@
+# 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/sync/aboutSyncTabs.xul
+ content/browser/sync/aboutSyncTabs.js
+ content/browser/sync/aboutSyncTabs.css
+ content/browser/sync/aboutSyncTabs-bindings.xml
+ content/browser/sync/setup.xul
+ content/browser/sync/addDevice.js
+ content/browser/sync/addDevice.xul
+ content/browser/sync/setup.js
+ content/browser/sync/genericChange.xul
+ content/browser/sync/genericChange.js
+ content/browser/sync/key.xhtml
+ content/browser/sync/notification.xml
+ content/browser/sync/quota.xul
+ content/browser/sync/quota.js
+ content/browser/sync/utils.js
+ content/browser/sync/progress.js
+ content/browser/sync/progress.xhtml \ No newline at end of file
diff --git a/application/basilisk/base/content/sync/key.xhtml b/application/basilisk/components/sync/key.xhtml
index 1363132e7..92abf0ee6 100644
--- a/application/basilisk/base/content/sync/key.xhtml
+++ b/application/basilisk/components/sync/key.xhtml
@@ -44,7 +44,7 @@
<p><em>&syncKey.keepItSafe1.description;</em>&syncKey.keepItSafe2.description;<em>&syncKey.keepItSafe3.description;</em>&syncKey.keepItSafe4a.description;</p>
</div>
-<p>&syncKey.findOutMore1.label;<a href="https://services.mozilla.com">https://services.mozilla.com</a>&syncKey.findOutMore2.label;</p>
+<p>&syncKey.findOutMore1.label;<a href="http://www.palemoon.org/sync/">http://www.palemoon.org/sync/</a>&syncKey.findOutMore2.label;</p>
<footer>
&syncKey.footer1.label;<a id="tosLink" href="termsURL">termsURL</a>&syncKey.footer2.label;<a id="ppLink" href="privacyURL">privacyURL</a>&syncKey.footer3.label;
diff --git a/application/basilisk/components/contextualidentity/moz.build b/application/basilisk/components/sync/moz.build
index aac3a838c..2d64d506c 100644
--- a/application/basilisk/components/contextualidentity/moz.build
+++ b/application/basilisk/components/sync/moz.build
@@ -1,7 +1,8 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# -*- Mode: python; c-basic-offset: 4; 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']
+
diff --git a/application/basilisk/components/sync/notification.xml b/application/basilisk/components/sync/notification.xml
new file mode 100644
index 000000000..8ac881e08
--- /dev/null
+++ b/application/basilisk/components/sync/notification.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0"?>
+
+<!-- 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 bindings [
+<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
+%notificationDTD;
+]>
+
+<bindings id="notificationBindings"
+ xmlns="http://www.mozilla.org/xbl"
+ xmlns:xbl="http://www.mozilla.org/xbl"
+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <binding id="notificationbox" extends="chrome://global/content/bindings/notification.xml#notificationbox">
+ <content>
+ <xul:vbox xbl:inherits="hidden=notificationshidden">
+ <xul:spacer/>
+ <children includes="notification"/>
+ </xul:vbox>
+ <children/>
+ </content>
+
+ <implementation>
+ <constructor><![CDATA[
+ let temp = {};
+ Cu.import("resource://services-common/observers.js", temp);
+ temp.Observers.add("weave:notification:added", this.onNotificationAdded, this);
+ temp.Observers.add("weave:notification:removed", this.onNotificationRemoved, this);
+
+ for each (var notification in Weave.Notifications.notifications)
+ this._appendNotification(notification);
+ ]]></constructor>
+
+ <destructor><![CDATA[
+ let temp = {};
+ Cu.import("resource://services-common/observers.js", temp);
+ temp.Observers.remove("weave:notification:added", this.onNotificationAdded, this);
+ temp.Observers.remove("weave:notification:removed", this.onNotificationRemoved, this);
+ ]]></destructor>
+
+ <method name="onNotificationAdded">
+ <parameter name="subject"/>
+ <parameter name="data"/>
+ <body><![CDATA[
+ this._appendNotification(subject);
+ ]]></body>
+ </method>
+
+ <method name="onNotificationRemoved">
+ <parameter name="subject"/>
+ <parameter name="data"/>
+ <body><![CDATA[
+ // If the view of the notification hasn't been removed yet, remove it.
+ var notifications = this.allNotifications;
+ for each (var notification in notifications) {
+ if (notification.notification == subject) {
+ notification.close();
+ break;
+ }
+ }
+ ]]></body>
+ </method>
+
+ <method name="_appendNotification">
+ <parameter name="notification"/>
+ <body><![CDATA[
+ var node = this.appendNotification(notification.description,
+ notification.title,
+ notification.iconURL,
+ notification.priority,
+ notification.buttons);
+ node.notification = notification;
+ ]]></body>
+ </method>
+
+ </implementation>
+ </binding>
+
+ <binding id="notification" extends="chrome://global/content/bindings/notification.xml#notification">
+ <content>
+ <xul:hbox class="notification-inner outset" flex="1" xbl:inherits="type">
+ <xul:toolbarbutton ondblclick="event.stopPropagation();"
+ class="messageCloseButton close-icon tabbable"
+ xbl:inherits="hidden=hideclose"
+ tooltiptext="&closeNotification.tooltip;"
+ oncommand="document.getBindingParent(this).close()"/>
+ <xul:hbox anonid="details" align="center" flex="1">
+ <xul:image anonid="messageImage" class="messageImage" xbl:inherits="src=image,type"/>
+ <xul:description anonid="messageText" class="messageText" xbl:inherits="xbl:text=label"/>
+
+ <!-- The children are the buttons defined by the notification. -->
+ <xul:hbox oncommand="document.getBindingParent(this)._doButtonCommand(event);">
+ <children/>
+ </xul:hbox>
+ </xul:hbox>
+ </xul:hbox>
+ </content>
+ <implementation>
+ <!-- Note: this used to be a field, but for some reason it kept getting
+ - reset to its default value for TabNotification elements.
+ - As a property, that doesn't happen, even though the property stores
+ - its value in a JS property |_notification| that is not defined
+ - in XBL as a field or property. Maybe this is wrong, but it works.
+ -->
+ <property name="notification"
+ onget="return this._notification"
+ onset="this._notification = val; return val;"/>
+ <method name="close">
+ <body><![CDATA[
+ Weave.Notifications.remove(this.notification);
+
+ // We should be able to call the base class's close method here
+ // to remove the notification element from the notification box,
+ // but we can't because of bug 373652, so instead we copied its code
+ // and execute it below.
+ var control = this.control;
+ if (control)
+ control.removeNotification(this);
+ else
+ this.hidden = true;
+ ]]></body>
+ </method>
+ </implementation>
+ </binding>
+
+</bindings>
diff --git a/application/basilisk/components/sync/progress.js b/application/basilisk/components/sync/progress.js
new file mode 100644
index 000000000..101160fa8
--- /dev/null
+++ b/application/basilisk/components/sync/progress.js
@@ -0,0 +1,71 @@
+/* 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/. */
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://services-sync/main.js");
+
+var gProgressBar;
+var gCounter = 0;
+
+function onLoad(event) {
+ Services.obs.addObserver(onEngineSync, "weave:engine:sync:finish", false);
+ Services.obs.addObserver(onEngineSync, "weave:engine:sync:error", false);
+ Services.obs.addObserver(onServiceSync, "weave:service:sync:finish", false);
+ Services.obs.addObserver(onServiceSync, "weave:service:sync:error", false);
+
+ gProgressBar = document.getElementById('uploadProgressBar');
+
+ if (Services.prefs.getPrefType("services.sync.firstSync") != Ci.nsIPrefBranch.PREF_INVALID) {
+ gProgressBar.hidden = false;
+ }
+ else {
+ gProgressBar.hidden = true;
+ }
+}
+
+function onUnload(event) {
+ cleanUpObservers();
+}
+
+function cleanUpObservers() {
+ try {
+ Services.obs.removeObserver(onEngineSync, "weave:engine:sync:finish");
+ Services.obs.removeObserver(onEngineSync, "weave:engine:sync:error");
+ Services.obs.removeObserver(onServiceSync, "weave:service:sync:finish");
+ Services.obs.removeObserver(onServiceSync, "weave:service:sync:error");
+ }
+ catch (e) {
+ // may be double called by unload & exit. Ignore.
+ }
+}
+
+function onEngineSync(subject, topic, data) {
+ // The Clients engine syncs first. At this point we don't necessarily know
+ // yet how many engines will be enabled, so we'll ignore the Clients engine
+ // and evaluate how many engines are enabled when the first "real" engine
+ // syncs.
+ if (data == "clients") {
+ return;
+ }
+
+ if (!gCounter &&
+ Services.prefs.getPrefType("services.sync.firstSync") != Ci.nsIPrefBranch.PREF_INVALID) {
+ gProgressBar.max = Weave.Service.engineManager.getEnabled().length;
+ }
+
+ gCounter += 1;
+ gProgressBar.setAttribute("value", gCounter);
+}
+
+function onServiceSync(subject, topic, data) {
+ // To address the case where 0 engines are synced, we will fill the
+ // progress bar so the user knows that the sync has finished.
+ gProgressBar.setAttribute("value", gProgressBar.max);
+ cleanUpObservers();
+}
+
+function closeTab() {
+ window.close();
+}
diff --git a/application/basilisk/components/sync/progress.xhtml b/application/basilisk/components/sync/progress.xhtml
new file mode 100644
index 000000000..d403cb20d
--- /dev/null
+++ b/application/basilisk/components/sync/progress.xhtml
@@ -0,0 +1,55 @@
+<?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 [
+ <!ENTITY % htmlDTD
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "DTD/xhtml1-strict.dtd">
+ %htmlDTD;
+ <!ENTITY % syncProgressDTD
+ SYSTEM "chrome://browser/locale/syncProgress.dtd">
+ %syncProgressDTD;
+ <!ENTITY % syncSetupDTD
+ SYSTEM "chrome://browser/locale/syncSetup.dtd">
+ %syncSetupDTD;
+ <!ENTITY % globalDTD
+ SYSTEM "chrome://global/locale/global.dtd">
+ %globalDTD;
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>&syncProgress.pageTitle;</title>
+
+ <link rel="stylesheet" type="text/css" media="all"
+ href="chrome://browser/skin/syncProgress.css"/>
+
+ <link rel="icon" type="image/png" id="favicon"
+ href="chrome://browser/skin/sync-16.png"/>
+
+ <script type="text/javascript;version=1.8"
+ src="chrome://browser/content/sync/progress.js"/>
+ </head>
+ <body onload="onLoad(event)" onunload="onUnload(event)" dir="&locale.dir;">
+ <title>&setup.successPage.title;</title>
+ <div id="floatingBox" class="main-content">
+ <div id="title">
+ <h1>&setup.successPage.title;</h1>
+ </div>
+ <div id="successLogo">
+ <img id="brandSyncLogo" src="chrome://browser/skin/sync-128.png" alt="&syncProgress.logoAltText;" />
+ </div>
+ <div id="loadingText">
+ <p id="blurb">&syncProgress.textBlurb; </p>
+ </div>
+ <div id="progressBar">
+ <progress id="uploadProgressBar" value="0"/>
+ </div>
+ <div id="bottomRow">
+ <button id="closeButton" onclick="closeTab()">&syncProgress.closeButton; </button>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/application/basilisk/base/content/sync/quota.js b/application/basilisk/components/sync/quota.js
index b416a44cc..b416a44cc 100644
--- a/application/basilisk/base/content/sync/quota.js
+++ b/application/basilisk/components/sync/quota.js
diff --git a/application/basilisk/base/content/sync/quota.xul b/application/basilisk/components/sync/quota.xul
index 99e6ed78b..99e6ed78b 100644
--- a/application/basilisk/base/content/sync/quota.xul
+++ b/application/basilisk/components/sync/quota.xul
diff --git a/application/basilisk/base/content/sync/setup.js b/application/basilisk/components/sync/setup.js
index f9dae1bd4..e8d67a5f6 100644
--- a/application/basilisk/base/content/sync/setup.js
+++ b/application/basilisk/components/sync/setup.js
@@ -1,4 +1,3 @@
-// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* 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/. */
@@ -51,9 +50,7 @@ var gSyncSetup = {
server: false
},
- get _remoteSites() {
- return [Weave.Service.serverURL, RECAPTCHA_DOMAIN];
- },
+ get _remoteSites() [Weave.Service.serverURL, RECAPTCHA_DOMAIN],
get _usingMainServers() {
if (this._settingUpNew)
@@ -72,7 +69,7 @@ var gSyncSetup = {
let self = this;
let addRem = function(add) {
obs.forEach(function([topic, func]) {
- // XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
+ //XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
// of `this`. Fix in a followup. (bug 583347)
if (add)
Weave.Svc.Obs.add(topic, self[func], self);
@@ -81,7 +78,7 @@ var gSyncSetup = {
});
};
addRem(true);
- window.addEventListener("unload", () => addRem(false), false);
+ window.addEventListener("unload", function() addRem(false), false);
window.setTimeout(function () {
// Force Service to be loaded so that engines are registered.
@@ -123,14 +120,14 @@ var gSyncSetup = {
startNewAccountSetup: function () {
if (!Weave.Utils.ensureMPUnlocked())
- return;
+ return false;
this._settingUpNew = true;
this.wizard.pageIndex = NEW_ACCOUNT_START_PAGE;
},
useExistingAccount: function () {
if (!Weave.Utils.ensureMPUnlocked())
- return;
+ return false;
this._settingUpNew = false;
if (this.wizardType == "pair") {
// We're already pairing, so there's no point in pairing again.
@@ -512,6 +509,7 @@ var gSyncSetup = {
onWizardBack: function () {
switch (this.wizard.pageIndex) {
case NEW_ACCOUNT_START_PAGE:
+ case EXISTING_ACCOUNT_LOGIN_PAGE:
this.wizard.pageIndex = INTRO_PAGE;
return false;
case EXISTING_ACCOUNT_CONNECT_PAGE:
@@ -552,12 +550,19 @@ var gSyncSetup = {
for (let i = 0;i < prefs.length;i++) {
Weave.Svc.Prefs.set(prefs[i], isChecked(prefs[i]));
}
+
+ // XXX: Addons syncing is currently not operational;
+ // Make doubly-sure to always disable addons syncing pref
+ Weave.Svc.Prefs.set("engine.addons", false);
+
this._handleNoScript(false);
if (Weave.Svc.Prefs.get("firstSync", "") == "notReady")
Weave.Svc.Prefs.reset("firstSync");
Weave.Service.persistLogin();
Weave.Svc.Obs.notify("weave:service:setup-complete");
+
+ gSyncUtils.openFirstSyncProgressPage();
}
Weave.Utils.nextTick(Weave.Service.sync, Weave.Service);
window.close();
@@ -797,6 +802,7 @@ var gSyncSetup = {
let el = document.getElementById("server");
let valid = false;
let feedback = document.getElementById("serverFeedbackRow");
+ let str = "";
if (el.value) {
valid = this._validateServer(el);
let str = valid ? "" : "serverInvalid.label";
@@ -932,7 +938,12 @@ var gSyncSetup = {
let addonsEngine = Weave.Service.engineManager.get("addons");
if (addonsEngine.enabled) {
let ids = addonsEngine._store.getAllIDs();
- let blessedcount = Object.keys(ids).filter(id => ids[id]).length;
+ let blessedcount = 0;
+ for each (let i in ids) {
+ if (i) {
+ blessedcount++;
+ }
+ }
// bug 600141 does not apply, as this does not have to support existing strings
document.getElementById("addonCount").value =
PluralForm.get(blessedcount,
@@ -956,7 +967,7 @@ var gSyncSetup = {
box.appendChild(node);
}
- for (let name of Weave.Service.clientsEngine.stats.names) {
+ for each (let name in Weave.Service.clientsEngine.stats.names) {
// Don't list the current client
if (name == Weave.Service.clientsEngine.localName)
continue;
@@ -998,7 +1009,7 @@ var gSyncSetup = {
if (string) {
try {
str = this._stringBundle.GetStringFromName(string);
- } catch (e) {}
+ } catch(e) {}
if (!str)
str = Weave.Utils.getErrorString(string);
@@ -1027,7 +1038,7 @@ var gSyncSetup = {
// If we didn't find a captcha, assume it's not needed and don't show it.
let responseStatus = request.QueryInterface(Ci.nsIHttpChannel).responseStatus;
setVisibility(this.captchaBrowser, responseStatus != 404);
- // XXX TODO we should really log any responseStatus other than 200
+ //XXX TODO we should really log any responseStatus other than 200
},
onProgressChange: function() {},
onStatusChange: function() {},
diff --git a/application/basilisk/base/content/sync/setup.xul b/application/basilisk/components/sync/setup.xul
index 11c085931..cf2cc77e4 100644
--- a/application/basilisk/base/content/sync/setup.xul
+++ b/application/basilisk/components/sync/setup.xul
@@ -43,7 +43,7 @@
&pairDevice.dialog.description.label;
<label class="text-link"
value="&addDevice.showMeHow.label;"
- href="https://services.mozilla.com/sync/help/add-device"/>
+ href="http://www.palemoon.org/sync/help/easy-setup.shtml"/>
</description>
<separator class="groove-thin"/>
<description>
@@ -183,12 +183,12 @@
onclick="document.getElementById('tos').focus();
document.getElementById('tos').click()">
&setup.tosAgree1.label;
- <label class="text-link"
+ <label class="text-link inline-link"
onclick="event.stopPropagation();gSyncUtils.openToS();">
&setup.tosLink.label;
</label>
&setup.tosAgree2.label;
- <label class="text-link"
+ <label class="text-link inline-link"
onclick="event.stopPropagation();gSyncUtils.openPrivacyPolicy();">
&setup.ppLink.label;
</label>
@@ -221,7 +221,7 @@
&pairDevice.setup.description.label;
<label class="text-link"
value="&addDevice.showMeHow.label;"
- href="https://services.mozilla.com/sync/help/easy-setup"/>
+ href="http://www.palemoon.org/sync/help/easy-setup.shtml"/>
</description>
<label value="&addDevice.setup.enterCode.label;"
control="easySetupPIN1"/>
@@ -340,7 +340,7 @@
<description>
&existingRecoveryKey.description;
<label class="text-link"
- href="https://services.mozilla.com/sync/help/manual-setup">
+ href="http://www.palemoon.org/sync/help/recoverykey.shtml">
&addDevice.showMeHow.label;
</label>
<spacer id="passphraseHelpSpacer"/>
@@ -359,7 +359,7 @@
<grid>
<columns>
<column/>
- <column flex="1" style="margin-inline-end: 2px"/>
+ <column flex="1" style="-moz-margin-end: 2px"/>
</columns>
<rows>
<row align="center">
@@ -375,7 +375,8 @@
<checkbox label="&engine.addons.label;"
accesskey="&engine.addons.accesskey;"
id="engine.addons"
- checked="true"/>
+ checked="false"
+ hidden="true"/>
<checkbox label="&engine.bookmarks.label;"
accesskey="&engine.bookmarks.accesskey;"
id="engine.bookmarks"
diff --git a/application/basilisk/base/content/sync/utils.js b/application/basilisk/components/sync/utils.js
index 92981f7b4..d41ecf18a 100644
--- a/application/basilisk/base/content/sync/utils.js
+++ b/application/basilisk/components/sync/utils.js
@@ -14,13 +14,6 @@ var gSyncUtils = {
return this.bundle = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
},
- get fxAccountsEnabled() {
- let service = Components.classes["@mozilla.org/weave/service;1"]
- .getService(Components.interfaces.nsISupports)
- .wrappedJSObject;
- return service.fxAccountsEnabled;
- },
-
// opens in a new window if we're in a modal prefwindow world, in a new tab otherwise
_openLink: function (url) {
let thisDocEl = document.documentElement,
@@ -77,22 +70,16 @@ var gSyncUtils = {
this._openLink(Weave.Service.pwResetURL);
},
- get tosURL() {
- let root = this.fxAccountsEnabled ? "fxa." : "";
- return Weave.Svc.Prefs.get(root + "termsURL");
- },
-
openToS: function () {
- this._openLink(this.tosURL);
+ this._openLink(Weave.Svc.Prefs.get("termsURL"));
},
- get privacyPolicyURL() {
- let root = this.fxAccountsEnabled ? "fxa." : "";
- return Weave.Svc.Prefs.get(root + "privacyURL");
+ openPrivacyPolicy: function () {
+ this._openLink(Weave.Svc.Prefs.get("privacyURL"));
},
- openPrivacyPolicy: function () {
- this._openLink(this.privacyPolicyURL);
+ openFirstSyncProgressPage: function () {
+ this._openLink("about:sync-progress");
},
/**
@@ -134,7 +121,7 @@ var gSyncUtils = {
/**
* Print passphrase backup document.
- *
+ *
* @param elid : ID of the form element containing the passphrase.
*/
passphrasePrint: function(elid) {
@@ -162,7 +149,7 @@ var gSyncUtils = {
/**
* Save passphrase backup document to disk as HTML file.
- *
+ *
* @param elid : ID of the form element containing the passphrase.
*/
passphraseSave: function(elid) {
@@ -200,7 +187,7 @@ var gSyncUtils = {
*
* @param el1 : the first textbox element in the form
* @param el2 : the second textbox element, if omitted it's an update form
- *
+ *
* returns [valid, errorString]
*/
validatePassword: function (el1, el2) {
diff --git a/application/basilisk/components/syncedtabs/EventEmitter.jsm b/application/basilisk/components/syncedtabs/EventEmitter.jsm
deleted file mode 100644
index ec3225f0f..000000000
--- a/application/basilisk/components/syncedtabs/EventEmitter.jsm
+++ /dev/null
@@ -1,45 +0,0 @@
-/* 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-this.EXPORTED_SYMBOLS = [
- "EventEmitter"
-];
-
-// Simple event emitter abstraction for storage objects to use.
-function EventEmitter () {
- this._events = new Map();
-}
-
-EventEmitter.prototype = {
- on(event, listener) {
- if (this._events.has(event)) {
- this._events.get(event).add(listener);
- } else {
- this._events.set(event, new Set([listener]));
- }
- },
- off(event, listener) {
- if (!this._events.has(event)) {
- return;
- }
- this._events.get(event).delete(listener);
- },
- emit(event, ...args) {
- if (!this._events.has(event)) {
- return;
- }
- for (let listener of this._events.get(event).values()) {
- try {
- listener.apply(this, args);
- } catch (e) {
- Cu.reportError(e);
- }
- }
- },
-};
-
diff --git a/application/basilisk/components/syncedtabs/SyncedTabsDeckComponent.js b/application/basilisk/components/syncedtabs/SyncedTabsDeckComponent.js
deleted file mode 100644
index c35277795..000000000
--- a/application/basilisk/components/syncedtabs/SyncedTabsDeckComponent.js
+++ /dev/null
@@ -1,169 +0,0 @@
-/* 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-Cu.import("resource:///modules/syncedtabs/SyncedTabsDeckStore.js");
-Cu.import("resource:///modules/syncedtabs/SyncedTabsDeckView.js");
-Cu.import("resource:///modules/syncedtabs/SyncedTabsListStore.js");
-Cu.import("resource:///modules/syncedtabs/TabListComponent.js");
-Cu.import("resource:///modules/syncedtabs/TabListView.js");
-let { getChromeWindow } = Cu.import("resource:///modules/syncedtabs/util.js", {});
-
-XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
- return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {});
-});
-
-let log = Cu.import("resource://gre/modules/Log.jsm", {})
- .Log.repository.getLogger("Sync.RemoteTabs");
-
-this.EXPORTED_SYMBOLS = [
- "SyncedTabsDeckComponent"
-];
-
-/* SyncedTabsDeckComponent
- * This component instantiates views and storage objects as well as defines
- * behaviors that will be passed down to the views. This helps keep the views
- * isolated and easier to test.
- */
-
-function SyncedTabsDeckComponent({
- window, SyncedTabs, fxAccounts, deckStore, listStore, listComponent, DeckView, getChromeWindowMock,
-}) {
- this._window = window;
- this._SyncedTabs = SyncedTabs;
- this._fxAccounts = fxAccounts;
- this._DeckView = DeckView || SyncedTabsDeckView;
- // used to stub during tests
- this._getChromeWindow = getChromeWindowMock || getChromeWindow;
-
- this._deckStore = deckStore || new SyncedTabsDeckStore();
- this._syncedTabsListStore = listStore || new SyncedTabsListStore(SyncedTabs);
- this.tabListComponent = listComponent || new TabListComponent({
- window: this._window,
- store: this._syncedTabsListStore,
- View: TabListView,
- SyncedTabs: SyncedTabs,
- clipboardHelper: Cc["@mozilla.org/widget/clipboardhelper;1"]
- .getService(Ci.nsIClipboardHelper),
- getChromeWindow: this._getChromeWindow,
- });
-}
-
-SyncedTabsDeckComponent.prototype = {
- PANELS: {
- TABS_CONTAINER: "tabs-container",
- TABS_FETCHING: "tabs-fetching",
- NOT_AUTHED_INFO: "notAuthedInfo",
- SINGLE_DEVICE_INFO: "singleDeviceInfo",
- TABS_DISABLED: "tabs-disabled",
- },
-
- get container() {
- return this._deckView ? this._deckView.container : null;
- },
-
- init() {
- Services.obs.addObserver(this, this._SyncedTabs.TOPIC_TABS_CHANGED, false);
- Services.obs.addObserver(this, FxAccountsCommon.ONLOGIN_NOTIFICATION, false);
-
- // Go ahead and trigger sync
- this._SyncedTabs.syncTabs()
- .catch(Cu.reportError);
-
- this._deckView = new this._DeckView(this._window, this.tabListComponent, {
- onAndroidClick: event => this.openAndroidLink(event),
- oniOSClick: event => this.openiOSLink(event),
- onSyncPrefClick: event => this.openSyncPrefs(event)
- });
-
- this._deckStore.on("change", state => this._deckView.render(state));
- // Trigger the initial rendering of the deck view
- // Object.values only in nightly
- this._deckStore.setPanels(Object.keys(this.PANELS).map(k => this.PANELS[k]));
- // Set the initial panel to display
- this.updatePanel();
- },
-
- uninit() {
- Services.obs.removeObserver(this, this._SyncedTabs.TOPIC_TABS_CHANGED);
- Services.obs.removeObserver(this, FxAccountsCommon.ONLOGIN_NOTIFICATION);
- this._deckView.destroy();
- },
-
- observe(subject, topic, data) {
- switch (topic) {
- case this._SyncedTabs.TOPIC_TABS_CHANGED:
- this._syncedTabsListStore.getData();
- this.updatePanel();
- break;
- case FxAccountsCommon.ONLOGIN_NOTIFICATION:
- this.updatePanel();
- break;
- default:
- break;
- }
- },
-
- // There's no good way to mock fxAccounts in browser tests where it's already
- // been instantiated, so we have this method for stubbing.
- _accountStatus() {
- return this._fxAccounts.accountStatus();
- },
-
- getPanelStatus() {
- return this._accountStatus().then(exists => {
- if (!exists) {
- return this.PANELS.NOT_AUTHED_INFO;
- }
- if (!this._SyncedTabs.isConfiguredToSyncTabs) {
- return this.PANELS.TABS_DISABLED;
- }
- if (!this._SyncedTabs.hasSyncedThisSession) {
- return this.PANELS.TABS_FETCHING;
- }
- return this._SyncedTabs.getTabClients().then(clients => {
- if (clients.length) {
- return this.PANELS.TABS_CONTAINER;
- }
- return this.PANELS.SINGLE_DEVICE_INFO;
- });
- })
- .catch(err => {
- Cu.reportError(err);
- return this.PANELS.NOT_AUTHED_INFO;
- });
- },
-
- updatePanel() {
- // return promise for tests
- return this.getPanelStatus()
- .then(panelId => this._deckStore.selectPanel(panelId))
- .catch(Cu.reportError);
- },
-
- openAndroidLink(event) {
- let href = Services.prefs.getCharPref("identity.mobilepromo.android") + "synced-tabs-sidebar";
- this._openUrl(href, event);
- },
-
- openiOSLink(event) {
- let href = Services.prefs.getCharPref("identity.mobilepromo.ios") + "synced-tabs-sidebar";
- this._openUrl(href, event);
- },
-
- _openUrl(url, event) {
- this._window.openUILink(url, event);
- },
-
- openSyncPrefs() {
- this._getChromeWindow(this._window).gSyncUI.openSetup(null, "tabs-sidebar");
- }
-};
-
diff --git a/application/basilisk/components/syncedtabs/SyncedTabsDeckStore.js b/application/basilisk/components/syncedtabs/SyncedTabsDeckStore.js
deleted file mode 100644
index ede6914c8..000000000
--- a/application/basilisk/components/syncedtabs/SyncedTabsDeckStore.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/* 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-let { EventEmitter } = Cu.import("resource:///modules/syncedtabs/EventEmitter.jsm", {});
-
-this.EXPORTED_SYMBOLS = [
- "SyncedTabsDeckStore"
-];
-
-/**
- * SyncedTabsDeckStore
- *
- * This store keeps track of the deck view state, including the panels and which
- * one is selected. The view listens for change events on the store, which are
- * triggered whenever the state changes. If it's a small change, the state
- * will have `isUpdatable` set to true so the view can skip rerendering the whole
- * DOM.
- */
-function SyncedTabsDeckStore() {
- EventEmitter.call(this);
- this._panels = [];
-}
-
-Object.assign(SyncedTabsDeckStore.prototype, EventEmitter.prototype, {
- _change(isUpdatable = false) {
- let panels = this._panels.map(panel => {
- return {id: panel, selected: panel === this._selectedPanel};
- });
- this.emit("change", {panels, isUpdatable: isUpdatable});
- },
-
- /**
- * Sets the selected panelId and triggers a change event.
- * @param {String} panelId - ID of the panel to select.
- */
- selectPanel(panelId) {
- if (this._panels.indexOf(panelId) === -1 || this._selectedPanel === panelId) {
- return;
- }
- this._selectedPanel = panelId;
- this._change(true);
- },
-
- /**
- * Update the set of panels in the deck and trigger a change event.
- * @param {Array} panels - an array of IDs for each panel in the deck.
- */
- setPanels(panels) {
- if (panels === this._panels) {
- return;
- }
- this._panels = panels || [];
- this._change();
- }
-});
diff --git a/application/basilisk/components/syncedtabs/SyncedTabsDeckView.js b/application/basilisk/components/syncedtabs/SyncedTabsDeckView.js
deleted file mode 100644
index e9efff323..000000000
--- a/application/basilisk/components/syncedtabs/SyncedTabsDeckView.js
+++ /dev/null
@@ -1,116 +0,0 @@
-/* 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-let { getChromeWindow } = Cu.import("resource:///modules/syncedtabs/util.js", {});
-
-let log = Cu.import("resource://gre/modules/Log.jsm", {})
- .Log.repository.getLogger("Sync.RemoteTabs");
-
-this.EXPORTED_SYMBOLS = [
- "SyncedTabsDeckView"
-];
-
-/**
- * SyncedTabsDeckView
- *
- * Instances of SyncedTabsDeckView render DOM nodes from a given state.
- * No state is kept internaly and the DOM will completely
- * rerender unless the state flags `isUpdatable`, which helps
- * make small changes without the overhead of a full rerender.
- */
-const SyncedTabsDeckView = function (window, tabListComponent, props) {
- this.props = props;
-
- this._window = window;
- this._doc = window.document;
-
- this._tabListComponent = tabListComponent;
- this._deckTemplate = this._doc.getElementById("deck-template");
- this.container = this._doc.createElement("div");
-};
-
-SyncedTabsDeckView.prototype = {
- render(state) {
- if (state.isUpdatable) {
- this.update(state);
- } else {
- this.create(state);
- }
- },
-
- create(state) {
- let deck = this._doc.importNode(this._deckTemplate.content, true).firstElementChild;
- this._clearChilden();
-
- let tabListWrapper = this._doc.createElement("div");
- tabListWrapper.className = "tabs-container sync-state";
- this._tabListComponent.init();
- tabListWrapper.appendChild(this._tabListComponent.container);
- deck.appendChild(tabListWrapper);
- this.container.appendChild(deck);
-
- this._generateDevicePromo();
-
- this._attachListeners();
- this.update(state);
- },
-
- _getBrowserBundle() {
- return getChromeWindow(this._window).document.getElementById("bundle_browser");
- },
-
- _generateDevicePromo() {
- let bundle = this._getBrowserBundle();
- let formatArgs = ["android", "ios"].map(os => {
- let link = this._doc.createElement("a");
- link.textContent = bundle.getString(`appMenuRemoteTabs.mobilePromo.${os}`);
- link.className = `${os}-link text-link`;
- link.setAttribute("href", "#");
- return link.outerHTML;
- });
- // Put it all together...
- let contents = bundle.getFormattedString("appMenuRemoteTabs.mobilePromo.text2", formatArgs);
- this.container.querySelector(".device-promo").innerHTML = contents;
- },
-
- destroy() {
- this._tabListComponent.uninit();
- this.container.remove();
- },
-
- update(state) {
- // Note that we may also want to update elements that are outside of the
- // deck, so use the document to find the class names rather than our
- // container.
- for (let panel of state.panels) {
- if (panel.selected) {
- Array.prototype.map.call(this._doc.getElementsByClassName(panel.id),
- item => item.classList.add("selected"));
- } else {
- Array.prototype.map.call(this._doc.getElementsByClassName(panel.id),
- item => item.classList.remove("selected"));
- }
- }
- },
-
- _clearChilden() {
- while (this.container.firstChild) {
- this.container.removeChild(this.container.firstChild);
- }
- },
-
- _attachListeners() {
- this.container.querySelector(".android-link").addEventListener("click", this.props.onAndroidClick);
- this.container.querySelector(".ios-link").addEventListener("click", this.props.oniOSClick);
- let syncPrefLinks = this.container.querySelectorAll(".sync-prefs");
- for (let link of syncPrefLinks) {
- link.addEventListener("click", this.props.onSyncPrefClick);
- }
- },
-};
-
diff --git a/application/basilisk/components/syncedtabs/SyncedTabsListStore.js b/application/basilisk/components/syncedtabs/SyncedTabsListStore.js
deleted file mode 100644
index 8f03d9a89..000000000
--- a/application/basilisk/components/syncedtabs/SyncedTabsListStore.js
+++ /dev/null
@@ -1,235 +0,0 @@
-/* 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-let { EventEmitter } = Cu.import("resource:///modules/syncedtabs/EventEmitter.jsm", {});
-
-this.EXPORTED_SYMBOLS = [
- "SyncedTabsListStore"
-];
-
-/**
- * SyncedTabsListStore
- *
- * Instances of this store encapsulate all of the state associated with a synced tabs list view.
- * The state includes the clients, their tabs, the row that is currently selected,
- * and the filtered query.
- */
-function SyncedTabsListStore(SyncedTabs) {
- EventEmitter.call(this);
- this._SyncedTabs = SyncedTabs;
- this.data = [];
- this._closedClients = {};
- this._selectedRow = [-1, -1];
- this.filter = "";
- this.inputFocused = false;
-}
-
-Object.assign(SyncedTabsListStore.prototype, EventEmitter.prototype, {
- // This internal method triggers the "change" event that views
- // listen for. It denormalizes the state so that it's easier for
- // the view to deal with. updateType hints to the view what
- // actually needs to be rerendered or just updated, and can be
- // empty (to (re)render everything), "searchbox" (to rerender just the tab list),
- // or "all" (to skip rendering and just update all attributes of existing nodes).
- _change(updateType) {
- let selectedParent = this._selectedRow[0];
- let selectedChild = this._selectedRow[1];
- let rowSelected = false;
- // clone the data so that consumers can't mutate internal storage
- let data = Cu.cloneInto(this.data, {});
- let tabCount = 0;
-
- data.forEach((client, index) => {
- client.closed = !!this._closedClients[client.id];
-
- if (rowSelected || selectedParent < 0) {
- return;
- }
- if (this.filter) {
- if (selectedParent < tabCount + client.tabs.length) {
- client.tabs[selectedParent - tabCount].selected = true;
- client.tabs[selectedParent - tabCount].focused = !this.inputFocused;
- rowSelected = true;
- } else {
- tabCount += client.tabs.length;
- }
- return;
- }
- if (selectedParent === index && selectedChild === -1) {
- client.selected = true;
- client.focused = !this.inputFocused;
- rowSelected = true;
- } else if (selectedParent === index) {
- client.tabs[selectedChild].selected = true;
- client.tabs[selectedChild].focused = !this.inputFocused;
- rowSelected = true;
- }
- });
-
- // If this were React the view would be smart enough
- // to not re-render the whole list unless necessary. But it's
- // not, so updateType is a hint to the view of what actually
- // needs to be rerendered.
- this.emit("change", {
- clients: data,
- canUpdateAll: updateType === "all",
- canUpdateInput: updateType === "searchbox",
- filter: this.filter,
- inputFocused: this.inputFocused
- });
- },
-
- /**
- * Moves the row selection from a child to its parent,
- * which occurs when the parent of a selected row closes.
- */
- _selectParentRow() {
- this._selectedRow[1] = -1;
- },
-
- _toggleBranch(id, closed) {
- this._closedClients[id] = closed;
- if (this._closedClients[id]) {
- this._selectParentRow();
- }
- this._change("all");
- },
-
- _isOpen(client) {
- return !this._closedClients[client.id];
- },
-
- moveSelectionDown() {
- let branchRow = this._selectedRow[0];
- let childRow = this._selectedRow[1];
- let branch = this.data[branchRow];
-
- if (this.filter) {
- this.selectRow(branchRow + 1);
- return;
- }
-
- if (branchRow < 0) {
- this.selectRow(0, -1);
- } else if ((!branch.tabs.length || childRow >= branch.tabs.length - 1 || !this._isOpen(branch)) && branchRow < this.data.length) {
- this.selectRow(branchRow + 1, -1);
- } else if (childRow < branch.tabs.length) {
- this.selectRow(branchRow, childRow + 1);
- }
- },
-
- moveSelectionUp() {
- let branchRow = this._selectedRow[0];
- let childRow = this._selectedRow[1];
-
- if (this.filter) {
- this.selectRow(branchRow - 1);
- return;
- }
-
- if (branchRow < 0) {
- this.selectRow(0, -1);
- } else if (childRow < 0 && branchRow > 0) {
- let prevBranch = this.data[branchRow - 1];
- let newChildRow = this._isOpen(prevBranch) ? prevBranch.tabs.length - 1 : -1;
- this.selectRow(branchRow - 1, newChildRow);
- } else if (childRow >= 0) {
- this.selectRow(branchRow, childRow - 1);
- }
- },
-
- // Selects a row and makes sure the selection is within bounds
- selectRow(parent, child) {
- let maxParentRow = this.filter ? this._tabCount() : this.data.length;
- let parentRow = parent;
- if (parent <= -1) {
- parentRow = 0;
- } else if (parent >= maxParentRow) {
- return;
- }
-
- let childRow = child;
- if (parentRow === -1 || this.filter || typeof child === "undefined" || child < -1) {
- childRow = -1;
- } else if (child >= this.data[parentRow].tabs.length) {
- childRow = this.data[parentRow].tabs.length - 1;
- }
-
- if (this._selectedRow[0] === parentRow && this._selectedRow[1] === childRow) {
- return;
- }
-
- this._selectedRow = [parentRow, childRow];
- this.inputFocused = false;
- this._change("all");
- },
-
- _tabCount() {
- return this.data.reduce((prev, curr) => curr.tabs.length + prev, 0);
- },
-
- toggleBranch(id) {
- this._toggleBranch(id, !this._closedClients[id]);
- },
-
- closeBranch(id) {
- this._toggleBranch(id, true);
- },
-
- openBranch(id) {
- this._toggleBranch(id, false);
- },
-
- focusInput() {
- this.inputFocused = true;
- // A change type of "all" updates rather than rebuilds, which is what we
- // want here - only the selection/focus has changed.
- this._change("all");
- },
-
- blurInput() {
- this.inputFocused = false;
- // A change type of "all" updates rather than rebuilds, which is what we
- // want here - only the selection/focus has changed.
- this._change("all");
- },
-
- clearFilter() {
- this.filter = "";
- this._selectedRow = [-1, -1];
- return this.getData();
- },
-
- // Fetches data from the SyncedTabs module and triggers
- // and update
- getData(filter) {
- let updateType;
- let hasFilter = typeof filter !== "undefined";
- if (hasFilter) {
- this.filter = filter;
- this._selectedRow = [-1, -1];
-
- // When a filter is specified we tell the view that only the list
- // needs to be rerendered so that it doesn't disrupt the input
- // field's focus.
- updateType = "searchbox";
- }
-
- // return promise for tests
- return this._SyncedTabs.getTabClients(this.filter)
- .then(result => {
- if (!hasFilter) {
- // Only sort clients and tabs if we're rendering the whole list.
- this._SyncedTabs.sortTabClientsByLastUsed(result);
- }
- this.data = result;
- this._change(updateType);
- })
- .catch(Cu.reportError);
- }
-});
diff --git a/application/basilisk/components/syncedtabs/TabListComponent.js b/application/basilisk/components/syncedtabs/TabListComponent.js
deleted file mode 100644
index aa60e4769..000000000
--- a/application/basilisk/components/syncedtabs/TabListComponent.js
+++ /dev/null
@@ -1,138 +0,0 @@
-/* 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-let log = Cu.import("resource://gre/modules/Log.jsm", {})
- .Log.repository.getLogger("Sync.RemoteTabs");
-
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUIUtils",
- "resource:///modules/PlacesUIUtils.jsm");
-
-this.EXPORTED_SYMBOLS = [
- "TabListComponent"
-];
-
-/**
- * TabListComponent
- *
- * The purpose of this component is to compose the view, state, and actions.
- * It defines high level actions that act on the state and passes them to the
- * view for it to trigger during user interaction. It also subscribes the view
- * to state changes so it can rerender.
- */
-
-function TabListComponent({window, store, View, SyncedTabs, clipboardHelper,
- getChromeWindow}) {
- this._window = window;
- this._store = store;
- this._View = View;
- this._clipboardHelper = clipboardHelper;
- this._getChromeWindow = getChromeWindow;
- // used to trigger Sync from context menu
- this._SyncedTabs = SyncedTabs;
-}
-
-TabListComponent.prototype = {
- get container() {
- return this._view.container;
- },
-
- init() {
- log.debug("Initializing TabListComponent");
-
- this._view = new this._View(this._window, {
- onSelectRow: (...args) => this.onSelectRow(...args),
- onOpenTab: (...args) => this.onOpenTab(...args),
- onOpenTabs: (...args) => this.onOpenTabs(...args),
- onMoveSelectionDown: (...args) => this.onMoveSelectionDown(...args),
- onMoveSelectionUp: (...args) => this.onMoveSelectionUp(...args),
- onToggleBranch: (...args) => this.onToggleBranch(...args),
- onBookmarkTab: (...args) => this.onBookmarkTab(...args),
- onCopyTabLocation: (...args) => this.onCopyTabLocation(...args),
- onSyncRefresh: (...args) => this.onSyncRefresh(...args),
- onFilter: (...args) => this.onFilter(...args),
- onClearFilter: (...args) => this.onClearFilter(...args),
- onFilterFocus: (...args) => this.onFilterFocus(...args),
- onFilterBlur: (...args) => this.onFilterBlur(...args)
- });
-
- this._store.on("change", state => this._view.render(state));
- this._view.render({clients: []});
- // get what's already available...
- this._store.getData();
- this._store.focusInput();
- },
-
- uninit() {
- this._view.destroy();
- },
-
- onFilter(query) {
- this._store.getData(query);
- },
-
- onClearFilter() {
- this._store.clearFilter();
- },
-
- onFilterFocus() {
- this._store.focusInput();
- },
-
- onFilterBlur() {
- this._store.blurInput();
- },
-
- onSelectRow(position) {
- this._store.selectRow(position[0], position[1]);
- },
-
- onMoveSelectionDown() {
- this._store.moveSelectionDown();
- },
-
- onMoveSelectionUp() {
- this._store.moveSelectionUp();
- },
-
- onToggleBranch(id) {
- this._store.toggleBranch(id);
- },
-
- onBookmarkTab(uri, title) {
- this._window.top.PlacesCommandHook
- .bookmarkLink(this._window.top.PlacesUtils.bookmarksMenuFolderId, uri, title)
- .catch(Cu.reportError);
- },
-
- onOpenTab(url, where, params) {
- this._window.openUILinkIn(url, where, params);
- },
-
- onOpenTabs(urls, where) {
- if (!PlacesUIUtils.confirmOpenInTabs(urls.length, this._window)) {
- return;
- }
- if (where == "window") {
- this._window.openDialog(this._window.getBrowserURL(), "_blank",
- "chrome,dialog=no,all", urls.join("|"));
- } else {
- let loadInBackground = where == "tabshifted" ? true : false;
- this._getChromeWindow(this._window).gBrowser.loadTabs(urls, loadInBackground, false);
- }
- },
-
- onCopyTabLocation(url) {
- this._clipboardHelper.copyString(url);
- },
-
- onSyncRefresh() {
- this._SyncedTabs.syncTabs(true);
- }
-};
diff --git a/application/basilisk/components/syncedtabs/TabListView.js b/application/basilisk/components/syncedtabs/TabListView.js
deleted file mode 100644
index dab15101b..000000000
--- a/application/basilisk/components/syncedtabs/TabListView.js
+++ /dev/null
@@ -1,568 +0,0 @@
-/* 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-
-let { getChromeWindow } = Cu.import("resource:///modules/syncedtabs/util.js", {});
-
-let log = Cu.import("resource://gre/modules/Log.jsm", {})
- .Log.repository.getLogger("Sync.RemoteTabs");
-
-this.EXPORTED_SYMBOLS = [
- "TabListView"
-];
-
-function getContextMenu(window) {
- return getChromeWindow(window).document.getElementById("SyncedTabsSidebarContext");
-}
-
-function getTabsFilterContextMenu(window) {
- return getChromeWindow(window).document.getElementById("SyncedTabsSidebarTabsFilterContext");
-}
-
-/*
- * TabListView
- *
- * Given a state, this object will render the corresponding DOM.
- * It maintains no state of it's own. It listens for DOM events
- * and triggers actions that may cause the state to change and
- * ultimately the view to rerender.
- */
-function TabListView(window, props) {
- this.props = props;
-
- this._window = window;
- this._doc = this._window.document;
-
- this._tabsContainerTemplate = this._doc.getElementById("tabs-container-template");
- this._clientTemplate = this._doc.getElementById("client-template");
- this._emptyClientTemplate = this._doc.getElementById("empty-client-template");
- this._tabTemplate = this._doc.getElementById("tab-template");
- this.tabsFilter = this._doc.querySelector(".tabsFilter");
- this.clearFilter = this._doc.querySelector(".textbox-search-clear");
- this.searchBox = this._doc.querySelector(".search-box");
- this.searchIcon = this._doc.querySelector(".textbox-search-icon");
-
- this.container = this._doc.createElement("div");
-
- this._attachFixedListeners();
-
- this._setupContextMenu();
-}
-
-TabListView.prototype = {
- render(state) {
- // Don't rerender anything; just update attributes, e.g. selection
- if (state.canUpdateAll) {
- this._update(state);
- return;
- }
- // Rerender the tab list
- if (state.canUpdateInput) {
- this._updateSearchBox(state);
- this._createList(state);
- return;
- }
- // Create the world anew
- this._create(state);
- },
-
- // Create the initial DOM from templates
- _create(state) {
- let wrapper = this._doc.importNode(this._tabsContainerTemplate.content, true).firstElementChild;
- this._clearChilden();
- this.container.appendChild(wrapper);
-
- this.list = this.container.querySelector(".list");
-
- this._createList(state);
- this._updateSearchBox(state);
-
- this._attachListListeners();
- },
-
- _createList(state) {
- this._clearChilden(this.list);
- for (let client of state.clients) {
- if (state.filter) {
- this._renderFilteredClient(client);
- } else {
- this._renderClient(client);
- }
- }
- if (this.list.firstChild) {
- const firstTab = this.list.firstChild.querySelector(".item.tab:first-child .item-title");
- if (firstTab) {
- firstTab.setAttribute("tabindex", 2);
- }
- }
- },
-
- destroy() {
- this._teardownContextMenu();
- this.container.remove();
- },
-
- _update(state) {
- this._updateSearchBox(state);
- for (let client of state.clients) {
- let clientNode = this._doc.getElementById("item-" + client.id);
- if (clientNode) {
- this._updateClient(client, clientNode);
- }
-
- client.tabs.forEach((tab, index) => {
- let tabNode = this._doc.getElementById('tab-' + client.id + '-' + index);
- this._updateTab(tab, tabNode, index);
- });
- }
- },
-
- // Client rows are hidden when the list is filtered
- _renderFilteredClient(client, filter) {
- client.tabs.forEach((tab, index) => {
- let node = this._renderTab(client, tab, index);
- this.list.appendChild(node);
- });
- },
-
- _renderClient(client) {
- let itemNode = client.tabs.length ?
- this._createClient(client) :
- this._createEmptyClient(client);
-
- this._updateClient(client, itemNode);
-
- let tabsList = itemNode.querySelector(".item-tabs-list");
- client.tabs.forEach((tab, index) => {
- let node = this._renderTab(client, tab, index);
- tabsList.appendChild(node);
- });
-
- this.list.appendChild(itemNode);
- return itemNode;
- },
-
- _renderTab(client, tab, index) {
- let itemNode = this._createTab(tab);
- this._updateTab(tab, itemNode, index);
- return itemNode;
- },
-
- _createClient(item) {
- return this._doc.importNode(this._clientTemplate.content, true).firstElementChild;
- },
-
- _createEmptyClient(item) {
- return this._doc.importNode(this._emptyClientTemplate.content, true).firstElementChild;
- },
-
- _createTab(item) {
- return this._doc.importNode(this._tabTemplate.content, true).firstElementChild;
- },
-
- _clearChilden(node) {
- let parent = node || this.container;
- while (parent.firstChild) {
- parent.removeChild(parent.firstChild);
- }
- },
-
- // These listeners are attached only once, when we initialize the view
- _attachFixedListeners() {
- this.tabsFilter.addEventListener("input", this.onFilter.bind(this));
- this.tabsFilter.addEventListener("focus", this.onFilterFocus.bind(this));
- this.tabsFilter.addEventListener("blur", this.onFilterBlur.bind(this));
- this.clearFilter.addEventListener("click", this.onClearFilter.bind(this));
- this.searchIcon.addEventListener("click", this.onFilterFocus.bind(this));
- },
-
- // These listeners have to be re-created every time since we re-create the list
- _attachListListeners() {
- this.list.addEventListener("click", this.onClick.bind(this));
- this.list.addEventListener("mouseup", this.onMouseUp.bind(this));
- this.list.addEventListener("keydown", this.onKeyDown.bind(this));
- },
-
- _updateSearchBox(state) {
- if (state.filter) {
- this.searchBox.classList.add("filtered");
- } else {
- this.searchBox.classList.remove("filtered");
- }
- this.tabsFilter.value = state.filter;
- if (state.inputFocused) {
- this.searchBox.setAttribute("focused", true);
- this.tabsFilter.focus();
- } else {
- this.searchBox.removeAttribute("focused");
- }
- },
-
- /**
- * Update the element representing an item, ensuring it's in sync with the
- * underlying data.
- * @param {client} item - Item to use as a source.
- * @param {Element} itemNode - Element to update.
- */
- _updateClient(item, itemNode) {
- itemNode.setAttribute("id", "item-" + item.id);
- let lastSync = new Date(item.lastModified);
- let lastSyncTitle = getChromeWindow(this._window).gSyncUI.formatLastSyncDate(lastSync);
- itemNode.setAttribute("title", lastSyncTitle);
- if (item.closed) {
- itemNode.classList.add("closed");
- } else {
- itemNode.classList.remove("closed");
- }
- if (item.selected) {
- itemNode.classList.add("selected");
- } else {
- itemNode.classList.remove("selected");
- }
- if (item.isMobile) {
- itemNode.classList.add("device-image-mobile");
- } else {
- itemNode.classList.add("device-image-desktop");
- }
- if (item.focused) {
- itemNode.focus();
- }
- itemNode.dataset.id = item.id;
- itemNode.querySelector(".item-title").textContent = item.name;
- },
-
- /**
- * Update the element representing a tab, ensuring it's in sync with the
- * underlying data.
- * @param {tab} item - Item to use as a source.
- * @param {Element} itemNode - Element to update.
- */
- _updateTab(item, itemNode, index) {
- itemNode.setAttribute("title", `${item.title}\n${item.url}`);
- itemNode.setAttribute("id", "tab-" + item.client + '-' + index);
- if (item.selected) {
- itemNode.classList.add("selected");
- } else {
- itemNode.classList.remove("selected");
- }
- if (item.focused) {
- itemNode.focus();
- }
- itemNode.dataset.url = item.url;
-
- itemNode.querySelector(".item-title").textContent = item.title;
-
- if (item.icon) {
- let icon = itemNode.querySelector(".item-icon-container");
- icon.style.backgroundImage = "url(" + item.icon + ")";
- }
- },
-
- onMouseUp(event) {
- if (event.which == 2) { // Middle click
- this.onClick(event);
- }
- },
-
- onClick(event) {
- let itemNode = this._findParentItemNode(event.target);
- if (!itemNode) {
- return;
- }
-
- if (itemNode.classList.contains("tab")) {
- let url = itemNode.dataset.url;
- if (url) {
- this.onOpenSelected(url, event);
- }
- }
-
- // Middle click on a client
- if (itemNode.classList.contains("client")) {
- let where = getChromeWindow(this._window).whereToOpenLink(event);
- if (where != "current") {
- const tabs = itemNode.querySelector(".item-tabs-list").childNodes;
- const urls = [...tabs].map(tab => tab.dataset.url);
- this.props.onOpenTabs(urls, where);
- }
- }
-
- if (event.target.classList.contains("item-twisty-container")
- && event.which != 2) {
- this.props.onToggleBranch(itemNode.dataset.id);
- return;
- }
-
- let position = this._getSelectionPosition(itemNode);
- this.props.onSelectRow(position);
- },
-
- /**
- * Handle a keydown event on the list box.
- * @param {Event} event - Triggering event.
- */
- onKeyDown(event) {
- if (event.keyCode == this._window.KeyEvent.DOM_VK_DOWN) {
- event.preventDefault();
- this.props.onMoveSelectionDown();
- } else if (event.keyCode == this._window.KeyEvent.DOM_VK_UP) {
- event.preventDefault();
- this.props.onMoveSelectionUp();
- } else if (event.keyCode == this._window.KeyEvent.DOM_VK_RETURN) {
- let selectedNode = this.container.querySelector('.item.selected');
- if (selectedNode.dataset.url) {
- this.onOpenSelected(selectedNode.dataset.url, event);
- } else if (selectedNode) {
- this.props.onToggleBranch(selectedNode.dataset.id);
- }
- }
- },
-
- onBookmarkTab() {
- let item = this._getSelectedTabNode();
- if (item) {
- let title = item.querySelector(".item-title").textContent;
- this.props.onBookmarkTab(item.dataset.url, title);
- }
- },
-
- onCopyTabLocation() {
- let item = this._getSelectedTabNode();
- if (item) {
- this.props.onCopyTabLocation(item.dataset.url);
- }
- },
-
- onOpenSelected(url, event) {
- let where = getChromeWindow(this._window).whereToOpenLink(event);
- this.props.onOpenTab(url, where, {});
- },
-
- onOpenSelectedFromContextMenu(event) {
- let item = this._getSelectedTabNode();
- if (item) {
- let where = event.target.getAttribute("where");
- let params = {
- private: event.target.hasAttribute("private"),
- };
- this.props.onOpenTab(item.dataset.url, where, params);
- }
- },
-
- onFilter(event) {
- let query = event.target.value;
- if (query) {
- this.props.onFilter(query);
- } else {
- this.props.onClearFilter();
- }
- },
-
- onClearFilter() {
- this.props.onClearFilter();
- },
-
- onFilterFocus() {
- this.props.onFilterFocus();
- },
- onFilterBlur() {
- this.props.onFilterBlur();
- },
-
- _getSelectedTabNode() {
- let item = this.container.querySelector('.item.selected');
- if (this._isTab(item) && item.dataset.url) {
- return item;
- }
- return null;
- },
-
- // Set up the custom context menu
- _setupContextMenu() {
- Services.els.addSystemEventListener(this._window, "contextmenu", this, false);
- for (let getMenu of [getContextMenu, getTabsFilterContextMenu]) {
- let menu = getMenu(this._window);
- menu.addEventListener("popupshowing", this, true);
- menu.addEventListener("command", this, true);
- }
- },
-
- _teardownContextMenu() {
- // Tear down context menu
- Services.els.removeSystemEventListener(this._window, "contextmenu", this, false);
- for (let getMenu of [getContextMenu, getTabsFilterContextMenu]) {
- let menu = getMenu(this._window);
- menu.removeEventListener("popupshowing", this, true);
- menu.removeEventListener("command", this, true);
- }
- },
-
- handleEvent(event) {
- switch (event.type) {
- case "contextmenu":
- this.handleContextMenu(event);
- break;
-
- case "popupshowing": {
- if (event.target.getAttribute("id") == "SyncedTabsSidebarTabsFilterContext") {
- this.handleTabsFilterContextMenuShown(event);
- }
- break;
- }
-
- case "command": {
- let menu = event.target.closest("menupopup");
- switch (menu.getAttribute("id")) {
- case "SyncedTabsSidebarContext":
- this.handleContentContextMenuCommand(event);
- break;
-
- case "SyncedTabsSidebarTabsFilterContext":
- this.handleTabsFilterContextMenuCommand(event);
- break;
- }
- break;
- }
- }
- },
-
- handleTabsFilterContextMenuShown(event) {
- let document = event.target.ownerDocument;
- let focusedElement = document.commandDispatcher.focusedElement;
- if (focusedElement != this.tabsFilter) {
- this.tabsFilter.focus();
- }
- for (let item of event.target.children) {
- if (!item.hasAttribute("cmd")) {
- continue;
- }
- let command = item.getAttribute("cmd");
- let controller = document.commandDispatcher.getControllerForCommand(command);
- if (controller.isCommandEnabled(command)) {
- item.removeAttribute("disabled");
- } else {
- item.setAttribute("disabled", "true");
- }
- }
- },
-
- handleContentContextMenuCommand(event) {
- let id = event.target.getAttribute("id");
- switch (id) {
- case "syncedTabsOpenSelected":
- case "syncedTabsOpenSelectedInTab":
- case "syncedTabsOpenSelectedInWindow":
- case "syncedTabsOpenSelectedInPrivateWindow":
- this.onOpenSelectedFromContextMenu(event);
- break;
- case "syncedTabsBookmarkSelected":
- this.onBookmarkTab();
- break;
- case "syncedTabsCopySelected":
- this.onCopyTabLocation();
- break;
- case "syncedTabsRefresh":
- case "syncedTabsRefreshFilter":
- this.props.onSyncRefresh();
- break;
- }
- },
-
- handleTabsFilterContextMenuCommand(event) {
- let command = event.target.getAttribute("cmd");
- let dispatcher = getChromeWindow(this._window).document.commandDispatcher;
- let controller = dispatcher.focusedElement.controllers.getControllerForCommand(command);
- controller.doCommand(command);
- },
-
- handleContextMenu(event) {
- let menu;
-
- if (event.target == this.tabsFilter) {
- menu = getTabsFilterContextMenu(this._window);
- } else {
- let itemNode = this._findParentItemNode(event.target);
- if (itemNode) {
- let position = this._getSelectionPosition(itemNode);
- this.props.onSelectRow(position);
- }
- menu = getContextMenu(this._window);
- this.adjustContextMenu(menu);
- }
-
- menu.openPopupAtScreen(event.screenX, event.screenY, true, event);
- },
-
- adjustContextMenu(menu) {
- let item = this.container.querySelector('.item.selected');
- let showTabOptions = this._isTab(item);
-
- let el = menu.firstChild;
-
- while (el) {
- if (showTabOptions || el.getAttribute("id") === "syncedTabsRefresh") {
- el.hidden = false;
- } else {
- el.hidden = true;
- }
-
- el = el.nextSibling;
- }
- },
-
- /**
- * Find the parent item element, from a given child element.
- * @param {Element} node - Child element.
- * @return {Element} Element for the item, or null if not found.
- */
- _findParentItemNode(node) {
- while (node && node !== this.list && node !== this._doc.documentElement &&
- !node.classList.contains("item")) {
- node = node.parentNode;
- }
-
- if (node !== this.list && node !== this._doc.documentElement) {
- return node;
- }
-
- return null;
- },
-
- _findParentBranchNode(node) {
- while (node && !node.classList.contains("list") && node !== this._doc.documentElement &&
- !node.parentNode.classList.contains("list")) {
- node = node.parentNode;
- }
-
- if (node !== this.list && node !== this._doc.documentElement) {
- return node;
- }
-
- return null;
- },
-
- _getSelectionPosition(itemNode) {
- let parent = this._findParentBranchNode(itemNode);
- let parentPosition = this._indexOfNode(parent.parentNode, parent);
- let childPosition = -1;
- // if the node is not a client, find its position within the parent
- if (parent !== itemNode) {
- childPosition = this._indexOfNode(itemNode.parentNode, itemNode);
- }
- return [parentPosition, childPosition];
- },
-
- _indexOfNode(parent, child) {
- return Array.prototype.indexOf.call(parent.childNodes, child);
- },
-
- _isTab(item) {
- return item && item.classList.contains("tab");
- }
-};
diff --git a/application/basilisk/components/syncedtabs/jar.mn b/application/basilisk/components/syncedtabs/jar.mn
deleted file mode 100644
index ba2b105a1..000000000
--- a/application/basilisk/components/syncedtabs/jar.mn
+++ /dev/null
@@ -1,7 +0,0 @@
-# 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/syncedtabs/sidebar.xhtml
- content/browser/syncedtabs/sidebar.js
diff --git a/application/basilisk/components/syncedtabs/moz.build b/application/basilisk/components/syncedtabs/moz.build
deleted file mode 100644
index a6515d6a1..000000000
--- a/application/basilisk/components/syncedtabs/moz.build
+++ /dev/null
@@ -1,17 +0,0 @@
-# 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']
-
-EXTRA_JS_MODULES.syncedtabs += [
- 'EventEmitter.jsm',
- 'SyncedTabsDeckComponent.js',
- 'SyncedTabsDeckStore.js',
- 'SyncedTabsDeckView.js',
- 'SyncedTabsListStore.js',
- 'TabListComponent.js',
- 'TabListView.js',
- 'util.js',
-]
-
diff --git a/application/basilisk/components/syncedtabs/sidebar.js b/application/basilisk/components/syncedtabs/sidebar.js
deleted file mode 100644
index 84df95e9d..000000000
--- a/application/basilisk/components/syncedtabs/sidebar.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://services-sync/SyncedTabs.jsm");
-Cu.import("resource:///modules/syncedtabs/SyncedTabsDeckComponent.js");
-
-XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
- "resource://gre/modules/FxAccounts.jsm");
-
-this.syncedTabsDeckComponent = new SyncedTabsDeckComponent({window, SyncedTabs, fxAccounts});
-
-let onLoaded = () => {
- syncedTabsDeckComponent.init();
- document.getElementById("template-container").appendChild(syncedTabsDeckComponent.container);
-};
-
-let onUnloaded = () => {
- removeEventListener("DOMContentLoaded", onLoaded);
- removeEventListener("unload", onUnloaded);
- syncedTabsDeckComponent.uninit();
-};
-
-addEventListener("DOMContentLoaded", onLoaded);
-addEventListener("unload", onUnloaded);
diff --git a/application/basilisk/components/syncedtabs/sidebar.xhtml b/application/basilisk/components/syncedtabs/sidebar.xhtml
deleted file mode 100644
index 3efcbea0e..000000000
--- a/application/basilisk/components/syncedtabs/sidebar.xhtml
+++ /dev/null
@@ -1,114 +0,0 @@
-<?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 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" [
- <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
- %browserDTD;
- <!ENTITY % globalDTD
- SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
- <!ENTITY % syncBrandDTD
- SYSTEM "chrome://browser/locale/syncBrand.dtd">
- %syncBrandDTD;
-]>
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
- <head>
- <script src="chrome://browser/content/syncedtabs/sidebar.js" type="application/javascript;version=1.8"></script>
- <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
-
- <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/skin/syncedtabs/sidebar.css"/>
- <link rel="stylesheet" type="text/css" media="all" href="chrome://global/skin/"/>
- <link rel="stylesheet" type="text/css" media="all" href="chrome://global/skin/textbox.css"/>
- <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/content/browser.css"/>
- <title>&syncedTabs.sidebar.label;</title>
- </head>
-
- <body dir="&locale.dir;" role="application">
- <template id="client-template">
- <div class="item client" role="option" tabindex="-1">
- <div class="item-title-container">
- <div class="item-twisty-container"></div>
- <div class="item-icon-container"></div>
- <p class="item-title"></p>
- </div>
- <div class="item-tabs-list"></div>
- </div>
- </template>
- <template id="empty-client-template">
- <div class="item empty client" role="option" tabindex="-1">
- <div class="item-title-container">
- <div class="item-twisty-container"></div>
- <div class="item-icon-container"></div>
- <p class="item-title"></p>
- </div>
- <div class="item-tabs-list">
- <div class="item empty" role="option" tabindex="-1">
- <div class="item-title-container">
- <div class="item-icon-container"></div>
- <p class="item-title">&syncedTabs.sidebar.notabs.label;</p>
- </div>
- </div>
- </div>
- </div>
- </template>
- <template id="tab-template">
- <div class="item tab" role="option" tabindex="-1">
- <div class="item-title-container">
- <div class="item-icon-container"></div>
- <p class="item-title"></p>
- </div>
- </div>
- </template>
-
- <template id="tabs-container-template">
- <div class="tabs-container">
- <div class="list" role="listbox"></div>
- </div>
- </template>
-
- <template id="deck-template">
- <div class="deck">
- <div class="tabs-fetching sync-state">
- <!-- Show intentionally blank panel, see bug 1239845 -->
- </div>
- <div class="notAuthedInfo sync-state">
- <p>&syncedTabs.sidebar.notsignedin.label;</p>
- <p><a href="#" class="sync-prefs text-link">&fxaSignIn.label;</a></p>
- </div>
- <div class="singleDeviceInfo sync-state">
- <p>&syncedTabs.sidebar.noclients.title;</p>
- <p>&syncedTabs.sidebar.noclients.subtitle;</p>
- <p class="device-promo" fxAccountsBrand="&syncBrand.fxAccount.label;"></p>
- </div>
- <div class="tabs-disabled sync-state">
- <p>&syncedTabs.sidebar.tabsnotsyncing.label;</p>
- <p><a href="#" class="sync-prefs text-link">&syncedTabs.sidebar.openprefs.label;</a></p>
- </div>
- </div>
- </template>
-
- <div class="content-container">
- <!-- the non-scrollable header -->
- <div class="content-header">
- <div class="sidebar-search-container tabs-container sync-state">
- <div class="search-box compact">
- <div class="textbox-input-box">
- <input type="text" class="tabsFilter textbox-input" tabindex="1"/>
- <div class="textbox-search-icons">
- <a class="textbox-search-clear"></a>
- <a class="textbox-search-icon"></a>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- the scrollable content area where our templates are inserted -->
- <div id="template-container" class="content-scrollable" tabindex="-1">
- </div>
- </div>
- </body>
-</html>
diff --git a/application/basilisk/components/syncedtabs/util.js b/application/basilisk/components/syncedtabs/util.js
deleted file mode 100644
index e09a1a528..000000000
--- a/application/basilisk/components/syncedtabs/util.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-this.EXPORTED_SYMBOLS = [
- "getChromeWindow"
-];
-
-// Get the chrome (ie, browser) window hosting this content.
-function getChromeWindow(window) {
- return window
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem)
- .rootTreeItem
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow)
- .wrappedJSObject;
-}
diff --git a/application/basilisk/configure.in b/application/basilisk/configure.in
index 4e7a06390..13f2ad54d 100644
--- a/application/basilisk/configure.in
+++ b/application/basilisk/configure.in
@@ -16,3 +16,10 @@ AC_SUBST(MC_BASILISK)
dnl Optional parts of the build.
+dnl ========================================================
+dnl = Disable Sync
+dnl ========================================================
+MOZ_ARG_DISABLE_BOOL(sync,
+[ --disable-sync Disable Sync],
+ MOZ_SERVICES_SYNC=,
+ MOZ_SERVICES_SYNC=1) \ No newline at end of file
diff --git a/application/basilisk/extensions/pdfjs/content/PdfJs.jsm b/application/basilisk/extensions/pdfjs/content/PdfJs.jsm
index b3d85436e..7dc01c398 100644
--- a/application/basilisk/extensions/pdfjs/content/PdfJs.jsm
+++ b/application/basilisk/extensions/pdfjs/content/PdfJs.jsm
@@ -52,23 +52,6 @@ XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsChromeUtils',
'resource://pdf.js/PdfjsChromeUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsContentUtils',
'resource://pdf.js/PdfjsContentUtils.jsm');
-
-function getBoolPref(aPref, aDefaultValue) {
- try {
- return Services.prefs.getBoolPref(aPref);
- } catch (ex) {
- return aDefaultValue;
- }
-}
-
-function getIntPref(aPref, aDefaultValue) {
- try {
- return Services.prefs.getIntPref(aPref);
- } catch (ex) {
- return aDefaultValue;
- }
-}
-
function isDefaultHandler() {
if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
return PdfjsContentUtils.isDefaultHandlerApp();
@@ -172,7 +155,7 @@ var PdfJs = {
}
this._initialized = true;
- if (!getBoolPref(PREF_DISABLED, true)) {
+ if (!Services.prefs.getBoolPref(PREF_DISABLED, true)) {
this._migrate();
}
@@ -209,7 +192,7 @@ var PdfJs = {
_migrate: function migrate() {
const VERSION = 2;
- var currentVersion = getIntPref(PREF_MIGRATION_VERSION, 0);
+ var currentVersion = Services.prefs.getIntPref(PREF_MIGRATION_VERSION, 0);
if (currentVersion >= VERSION) {
return;
}
@@ -284,7 +267,7 @@ var PdfJs = {
* @return {boolean} Whether or not it's enabled.
*/
get enabled() {
- var disabled = getBoolPref(PREF_DISABLED, true);
+ var disabled = Services.prefs.getBoolPref(PREF_DISABLED, true);
if (disabled) {
return false;
}
diff --git a/application/basilisk/extensions/pdfjs/content/PdfStreamConverter.jsm b/application/basilisk/extensions/pdfjs/content/PdfStreamConverter.jsm
index 5e337bbc5..b5b21f214 100644
--- a/application/basilisk/extensions/pdfjs/content/PdfStreamConverter.jsm
+++ b/application/basilisk/extensions/pdfjs/content/PdfStreamConverter.jsm
@@ -78,22 +78,6 @@ function getFindBar(domWindow) {
}
}
-function getBoolPref(pref, def) {
- try {
- return Services.prefs.getBoolPref(pref);
- } catch (ex) {
- return def;
- }
-}
-
-function getIntPref(pref, def) {
- try {
- return Services.prefs.getIntPref(pref);
- } catch (ex) {
- return def;
- }
-}
-
function getStringPref(pref, def) {
try {
return Services.prefs.getComplexValue(pref, Ci.nsISupportsString).data;
@@ -103,7 +87,7 @@ function getStringPref(pref, def) {
}
function log(aMsg) {
- if (!getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false)) {
+ if (!Services.prefs.getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false)) {
return;
}
var msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
@@ -359,17 +343,17 @@ ChromeActions.prototype = {
return !!findBar && ('updateControlState' in findBar);
},
supportsDocumentFonts: function() {
- var prefBrowser = getIntPref('browser.display.use_document_fonts', 1);
- var prefGfx = getBoolPref('gfx.downloadable_fonts.enabled', true);
+ var prefBrowser = Services.prefs.getIntPref('browser.display.use_document_fonts', 1);
+ var prefGfx = Services.prefs.getBoolPref('gfx.downloadable_fonts.enabled', true);
return (!!prefBrowser && prefGfx);
},
supportsDocumentColors: function() {
- return getIntPref('browser.display.document_color_use', 0) !== 2;
+ return Services.prefs.getIntPref('browser.display.document_color_use', 0) !== 2;
},
supportedMouseWheelZoomModifierKeys: function() {
return {
- ctrlKey: getIntPref('mousewheel.with_control.action', 3) === 3,
- metaKey: getIntPref('mousewheel.with_meta.action', 1) === 3,
+ ctrlKey: Services.prefs.getIntPref('mousewheel.with_control.action', 3) === 3,
+ metaKey: Services.prefs.getIntPref('mousewheel.with_meta.action', 1) === 3,
};
},
reportTelemetry: function (data) {
@@ -531,10 +515,10 @@ ChromeActions.prototype = {
prefName = (PREF_PREFIX + '.' + key);
switch (typeof prefValue) {
case 'boolean':
- currentPrefs[key] = getBoolPref(prefName, prefValue);
+ currentPrefs[key] = Services.prefs.getBoolPref(prefName, prefValue);
break;
case 'number':
- currentPrefs[key] = getIntPref(prefName, prefValue);
+ currentPrefs[key] = Services.prefs.getIntPref(prefName, prefValue);
break;
case 'string':
currentPrefs[key] = getStringPref(prefName, prefValue);
@@ -921,16 +905,16 @@ PdfStreamConverter.prototype = {
} catch (e) {}
var hash = aRequest.URI.ref;
- var isPDFBugEnabled = getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false);
+ var isPDFBugEnabled = Services.prefs.getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false);
rangeRequest = contentEncoding === 'identity' &&
acceptRanges === 'bytes' &&
aRequest.contentLength >= 0 &&
- !getBoolPref(PREF_PREFIX + '.disableRange', false) &&
+ !Services.prefs.getBoolPref(PREF_PREFIX + '.disableRange', false) &&
(!isPDFBugEnabled ||
hash.toLowerCase().indexOf('disablerange=true') < 0);
streamRequest = contentEncoding === 'identity' &&
aRequest.contentLength >= 0 &&
- !getBoolPref(PREF_PREFIX + '.disableStream', false) &&
+ !Services.prefs.getBoolPref(PREF_PREFIX + '.disableStream', false) &&
(!isPDFBugEnabled ||
hash.toLowerCase().indexOf('disablestream=true') < 0);
}
diff --git a/application/basilisk/fonts/TwemojiMozilla.ttf b/application/basilisk/fonts/TwemojiMozilla.ttf
index 1933891d9..c47cbbf11 100644
--- a/application/basilisk/fonts/TwemojiMozilla.ttf
+++ b/application/basilisk/fonts/TwemojiMozilla.ttf
Binary files differ
diff --git a/application/basilisk/installer/allowed-dupes.mn b/application/basilisk/installer/allowed-dupes.mn
index 7baa6ebed..a3780bf5a 100644
--- a/application/basilisk/installer/allowed-dupes.mn
+++ b/application/basilisk/installer/allowed-dupes.mn
@@ -211,13 +211,11 @@ chrome/toolkit/skin/classic/mozapps/update/buttons.png
chrome/toolkit/skin/classic/mozapps/update/downloadButtons.png
chrome/toolkit/skin/classic/mozapps/xpinstall/xpinstallItemGeneric.png
-components/FxAccountsPush.js
crashreporter.app/Contents/Resources/English.lproj/MainMenu.nib/classes.nib
crashreporter.app/Contents/Resources/English.lproj/MainMenuRTL.nib/classes.nib
# firefox/firefox-bin is bug 658850
@MOZ_APP_NAME@
@MOZ_APP_NAME@-bin
-modules/FxAccountsPush.js
modules/commonjs/index.js
modules/commonjs/sdk/ui/button/view/events.js
modules/commonjs/sdk/ui/state/events.js
diff --git a/application/basilisk/installer/package-manifest.in b/application/basilisk/installer/package-manifest.in
index 7e12e3af2..22655bc33 100644
--- a/application/basilisk/installer/package-manifest.in
+++ b/application/basilisk/installer/package-manifest.in
@@ -479,8 +479,6 @@
#endif
@RESPATH@/components/SyncComponents.manifest
@RESPATH@/components/Weave.js
-@RESPATH@/components/FxAccountsComponents.manifest
-@RESPATH@/components/FxAccountsPush.js
@RESPATH@/components/CaptivePortalDetectComponents.manifest
@RESPATH@/components/captivedetect.js
@RESPATH@/components/servicesComponents.manifest
@@ -709,13 +707,6 @@
@RESPATH@/components/pipnss.xpt
@RESPATH@/components/pippki.xpt
-; for Solaris SPARC
-#ifdef SOLARIS
-bin/libfreebl_32fpu_3.so
-bin/libfreebl_32int_3.so
-bin/libfreebl_32int64_3.so
-#endif
-
; [Updater]
;
#ifdef MOZ_UPDATER
diff --git a/application/basilisk/installer/windows/nsis/installer.nsi b/application/basilisk/installer/windows/nsis/installer.nsi
index fa8e95775..6b4b5ab9a 100644
--- a/application/basilisk/installer/windows/nsis/installer.nsi
+++ b/application/basilisk/installer/windows/nsis/installer.nsi
@@ -1080,7 +1080,6 @@ Function .onInit
!insertmacro InitInstallOptionsFile "options.ini"
!insertmacro InitInstallOptionsFile "shortcuts.ini"
- !insertmacro InitInstallOptionsFile "components.ini"
!insertmacro InitInstallOptionsFile "summary.ini"
WriteINIStr "$PLUGINSDIR\options.ini" "Settings" NumFields "5"
@@ -1155,36 +1154,6 @@ Function .onInit
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Bottom "50"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" State "1"
- ; Don't offer to install the quick launch shortcut on Windows 7
- ${Unless} ${AtLeastWin7}
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Type "checkbox"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Text "$(ICONS_QUICKLAUNCH)"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Left "0"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Right "-1"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Top "60"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Bottom "70"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" State "1"
- ${EndUnless}
-
- ; Setup the components.ini file for the Components Page
- WriteINIStr "$PLUGINSDIR\components.ini" "Settings" NumFields "2"
-
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Type "label"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Text "$(OPTIONAL_COMPONENTS_DESC)"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Left "0"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Right "-1"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Top "5"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Bottom "25"
-
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Type "checkbox"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Text "$(MAINTENANCE_SERVICE_CHECKBOX_DESC)"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Left "0"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Right "-1"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Top "27"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Bottom "37"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" State "1"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Flags "GROUP"
-
; There must always be a core directory.
${GetSize} "$EXEDIR\core\" "/S=0K" $R5 $R7 $R8
SectionSetSize ${APP_IDX} $R5
diff --git a/application/basilisk/locales/en-US/chrome/browser-region/region.properties b/application/basilisk/locales/en-US/chrome/browser-region/region.properties
index e35fc7497..8782ae46f 100644
--- a/application/basilisk/locales/en-US/chrome/browser-region/region.properties
+++ b/application/basilisk/locales/en-US/chrome/browser-region/region.properties
@@ -9,6 +9,7 @@ browser.search.defaultenginename=DuckDuckGo
browser.search.order.1=DuckDuckGo
browser.search.order.2=Yahoo
browser.search.order.3=Bing
+browser.search.order.4=Ecosia
# This is the default set of web based feed handlers shown in the reader
# selection UI
@@ -20,11 +21,7 @@ browser.contentHandlers.types.0.uri=https://add.my.yahoo.com/rss?url=%s
# profile database. Note that "new" is defined as "has a different URL"; this
# means that it's not possible to update the name of existing handler, so
# don't make any spelling errors here.
-gecko.handlerService.defaultHandlersVersion=4
-
-# The default set of protocol handlers for webcal:
-gecko.handlerService.schemes.webcal.0.name=30 Boxes
-gecko.handlerService.schemes.webcal.0.uriTemplate=https://30boxes.com/external/widget?refer=ff&url=%s
+gecko.handlerService.defaultHandlersVersion=5
# The default set of protocol handlers for mailto:
gecko.handlerService.schemes.mailto.0.name=Yahoo! Mail
diff --git a/application/basilisk/locales/en-US/chrome/browser/aboutAccounts.dtd b/application/basilisk/locales/en-US/chrome/browser/aboutAccounts.dtd
deleted file mode 100644
index 358722156..000000000
--- a/application/basilisk/locales/en-US/chrome/browser/aboutAccounts.dtd
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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/. -->
-
-<!ENTITY aboutAccounts.welcome "Welcome to &syncBrand.shortName.label;">
-<!ENTITY aboutAccounts.connected "Account connected">
-
-<!ENTITY aboutAccountsConfig.description "Sign in to sync your tabs, bookmarks, passwords &amp; more.">
-<!ENTITY aboutAccountsConfig.startButton.label "Get started">
-<!ENTITY aboutAccountsConfig.useOldSync.label "Using an older version of Sync?">
-<!ENTITY aboutAccountsConfig.syncPreferences.label "Sync preferences">
-<!ENTITY aboutAccounts.noConnection.title "No connection">
-<!ENTITY aboutAccounts.noConnection.description "You must be connected to the Internet to sign in.">
-<!ENTITY aboutAccounts.noConnection.retry "Try again">
-<!ENTITY aboutAccounts.badConfig.title "Bad configuration">
-<!ENTITY aboutAccounts.badConfig.description "Unable to determine your Firefox Account server configuration. Please try again later.">
diff --git a/application/basilisk/locales/en-US/chrome/browser/aboutHome.dtd b/application/basilisk/locales/en-US/chrome/browser/aboutHome.dtd
index 17b401c6c..40681c337 100644
--- a/application/basilisk/locales/en-US/chrome/browser/aboutHome.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/aboutHome.dtd
@@ -4,8 +4,10 @@
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
%brandDTD;
+#ifdef MOZ_SERVICES_SYNC
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
%syncBrandDTD;
+#endif
<!-- These strings are used in the about:home page -->
@@ -32,7 +34,9 @@
<!ENTITY abouthome.preferencesButtonUnix.label "Preferences">
<!ENTITY abouthome.addonsButton.label "Add-ons">
<!ENTITY abouthome.downloadsButton.label "Downloads">
+#ifdef MOZ_SERVICES_SYNC
<!ENTITY abouthome.syncButton.label "&syncBrand.shortName.label;">
+#endif
<!-- LOCALIZATION NOTE (abouthome.aboutMozilla.label): The (invisible) label for
the mozilla wordmark in the top-right corner that links to Mozilla's main
diff --git a/application/basilisk/locales/en-US/chrome/browser/aboutRobots.dtd b/application/basilisk/locales/en-US/chrome/browser/aboutRobots.dtd
deleted file mode 100644
index 23447add1..000000000
--- a/application/basilisk/locales/en-US/chrome/browser/aboutRobots.dtd
+++ /dev/null
@@ -1,29 +0,0 @@
-<!-- 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/. -->
-
-<!-- These strings are used in the about:robots page, which ties in with the
- robots theme used in the Firefox 3 Beta 2/3 first run pages.
- They're just meant to be fun and whimsical, with references to some geeky
- but well-known robots in movies and books. Be creative with translations! -->
-
-<!-- Nonsense line from the movie "The Day The Earth Stood Still". No translation needed. -->
-<!ENTITY robots.pagetitle "Gort! Klaatu barada nikto!">
-<!-- Movie: Logan's Run... Box (cybog): "Welcome Humans! I am ready for you." -->
-<!ENTITY robots.errorTitleText "Welcome Humans!">
-<!-- Movie: The Day The Earth Stood Still. Spoken by Klaatu. -->
-<!ENTITY robots.errorShortDescText "We have come to visit you in peace and with goodwill!">
-<!-- Various books by Isaac Asimov. http://en.wikipedia.org/wiki/Three_Laws_of_Robotics -->
-<!ENTITY robots.errorLongDesc1 "Robots may not injure a human being or, through inaction, allow a human being to come to harm.">
-<!-- Movie: Blade Runner. Batty: "I've seen things you people wouldn’t believe..." -->
-<!ENTITY robots.errorLongDesc2 "Robots have seen things you people wouldn’t believe.">
-<!-- Book: Hitchhiker’s Guide To The Galaxy. What the Sirius Cybernetics Corporation calls robots. -->
-<!ENTITY robots.errorLongDesc3 "Robots are Your Plastic Pal Who’s Fun To Be With.">
-<!-- TV: Futurama. Bender's first line is "Bite my shiny metal ass." -->
-<!ENTITY robots.errorLongDesc4 "Robots have shiny metal posteriors which should not be bitten.">
-<!-- TV: Battlestar Galactica (2004 series). From the opening text. -->
-<!ENTITY robots.errorTrailerDescText "And they have a plan.">
-<!-- TV: Battlestar Galactica (2004 series). Common expletive referring to Cylons. -->
-<!ENTITY robots.imgtitle "Frakkin' Toasters">
-<!-- Book: Hitchhiker's Guide To The Galaxy. Arthur presses a button and it warns him. -->
-<!ENTITY robots.dontpress "Please do not press this button again.">
diff --git a/application/basilisk/locales/en-US/chrome/browser/browser.dtd b/application/basilisk/locales/en-US/chrome/browser/browser.dtd
index d02a6eedb..fe856129f 100644
--- a/application/basilisk/locales/en-US/chrome/browser/browser.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/browser.dtd
@@ -40,12 +40,6 @@ can reach it easily. -->
<!ENTITY pinTab.accesskey "P">
<!ENTITY unpinTab.label "Unpin Tab">
<!ENTITY unpinTab.accesskey "b">
-<!ENTITY sendTabToDevice.label "Send Tab to Device">
-<!ENTITY sendTabToDevice.accesskey "D">
-<!ENTITY sendPageToDevice.label "Send Page to Device">
-<!ENTITY sendPageToDevice.accesskey "D">
-<!ENTITY sendLinkToDevice.label "Send Link to Device">
-<!ENTITY sendLinkToDevice.accesskey "D">
<!ENTITY moveToNewWindow.label "Move to New Window">
<!ENTITY moveToNewWindow.accesskey "W">
<!ENTITY bookmarkAllTabs.label "Bookmark All Tabs…">
@@ -115,11 +109,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY showAllTabsCmd.accesskey "A">
<!ENTITY toggleReaderMode.key "R">
-<!ENTITY fxaSignIn.label "Sign in to &syncBrand.shortName.label;">
-<!ENTITY fxaSignInError.label "Reconnect to &syncBrand.shortName.label;">
-<!ENTITY fxaUnverified.label "Verify Your Account">
-<!ENTITY syncSettings.label "Open &syncBrand.shortName.label; settings">
-
<!ENTITY fullScreenMinimize.tooltip "Minimize">
<!ENTITY fullScreenRestore.tooltip "Restore">
<!ENTITY fullScreenClose.tooltip "Close">
@@ -333,23 +322,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY appMenuHistory.viewSidebar.label "View History Sidebar">
<!ENTITY appMenuHelp.tooltip "Open Help Menu">
-<!ENTITY appMenuRemoteTabs.label "Synced Tabs">
-<!-- LOCALIZATION NOTE (appMenuRemoteTabs.notabs.label): This is shown beneath
- the name of a device when that device has no open tabs -->
-<!ENTITY appMenuRemoteTabs.notabs.label "No open tabs">
-<!-- LOCALIZATION NOTE (appMenuRemoteTabs.tabsnotsyncing.label): This is shown
- when Sync is configured but syncing tabs is disabled. -->
-<!ENTITY appMenuRemoteTabs.tabsnotsyncing.label "Turn on tab syncing to view a list of tabs from your other devices.">
-<!-- LOCALIZATION NOTE (appMenuRemoteTabs.noclients.label): This is shown
- when Sync is configured but this appears to be the only device attached to
- the account. We also show links to download Firefox for android/ios. -->
-<!ENTITY appMenuRemoteTabs.noclients.title "No synced tabs… yet!">
-<!ENTITY appMenuRemoteTabs.noclients.subtitle "Want to see your tabs from other devices here?">
-<!ENTITY appMenuRemoteTabs.openprefs.label "Sync Preferences">
-<!ENTITY appMenuRemoteTabs.notsignedin.label "Sign in to view a list of tabs from your other devices.">
-<!ENTITY appMenuRemoteTabs.signin.label "Sign in to Sync">
-<!ENTITY appMenuRemoteTabs.sidebar.label "View Synced Tabs">
-
<!ENTITY customizeMenu.addToToolbar.label "Add to Toolbar">
<!ENTITY customizeMenu.addToToolbar.accesskey "A">
<!ENTITY customizeMenu.addToPanel.label "Add to Menu">
@@ -723,43 +695,19 @@ you can use these alternative items. Otherwise, their values should be empty. -
The word "toolbar" is appended automatically and should not be contained below! -->
<!ENTITY tabsToolbar.label "Browser tabs">
-<!-- LOCALIZATION NOTE (syncTabsMenu3.label): This appears in the history menu -->
-<!ENTITY syncTabsMenu3.label "Synced Tabs">
-
-<!ENTITY syncedTabs.sidebar.label "Synced Tabs">
-<!ENTITY syncedTabs.sidebar.noclients.label "Sign in to Firefox from your other devices to view their tabs here.">
-<!ENTITY syncedTabs.sidebar.noclients.title "No synced tabs… yet!">
-<!ENTITY syncedTabs.sidebar.noclients.subtitle "Want to see your tabs from other devices here?">
-<!ENTITY syncedTabs.sidebar.notsignedin.label "Sign in to view a list of tabs from your other devices.">
-<!ENTITY syncedTabs.sidebar.notabs.label "No open tabs">
-<!ENTITY syncedTabs.sidebar.openprefs.label "Open &syncBrand.shortName.label; Preferences">
-<!-- LOCALIZATION NOTE (syncedTabs.sidebar.tabsnotsyncing.label): This is shown
- when Sync is configured but syncing tabs is disabled. -->
-<!ENTITY syncedTabs.sidebar.tabsnotsyncing.label "Turn on tab syncing to view a list of tabs from your other devices.">
-
-<!ENTITY syncedTabs.context.open.label "Open">
-<!ENTITY syncedTabs.context.open.accesskey "O">
-<!ENTITY syncedTabs.context.openInNewTab.label "Open in a New Tab">
-<!ENTITY syncedTabs.context.openInNewTab.accesskey "w">
-<!ENTITY syncedTabs.context.openInNewWindow.label "Open in a New Window">
-<!ENTITY syncedTabs.context.openInNewWindow.accesskey "N">
-<!ENTITY syncedTabs.context.openInNewPrivateWindow.label "Open in a New Private Window">
-<!ENTITY syncedTabs.context.openInNewPrivateWindow.accesskey "P">
-<!ENTITY syncedTabs.context.bookmarkSingleTab.label "Bookmark This Tab…">
-<!ENTITY syncedTabs.context.bookmarkSingleTab.accesskey "B">
-<!ENTITY syncedTabs.context.copy.label "Copy">
-<!ENTITY syncedTabs.context.copy.accesskey "C">
-
+#ifdef MOZ_SERVICES_SYNC
+<!-- LOCALIZATION NOTE (syncTabsMenu2.label): This appears in the history menu -->
+<!ENTITY syncTabsMenu2.label "Tabs From Other Devices">
<!ENTITY syncBrand.shortName.label "Sync">
-<!ENTITY syncSignIn.label "Sign In To &syncBrand.shortName.label;…">
-<!ENTITY syncSignIn.accesskey "Y">
+<!ENTITY syncSetup.label "Set Up &syncBrand.shortName.label;…">
+<!ENTITY syncSetup.accesskey "Y">
<!ENTITY syncSyncNowItem.label "Sync Now">
<!ENTITY syncSyncNowItem.accesskey "S">
-<!ENTITY syncReAuthItem.label "Reconnect to &syncBrand.shortName.label;…">
-<!ENTITY syncReAuthItem.accesskey "R">
<!ENTITY syncToolbarButton.label "Sync">
+<!ENTITY syncTabsToolbarButton.label "Synced Tabs">
+#endif
<!ENTITY customizeMode.menuAndToolbars.header2 "Additional Tools and Features">
<!ENTITY customizeMode.menuAndToolbars.empty "Want more tools?">
diff --git a/application/basilisk/locales/en-US/chrome/browser/browser.properties b/application/basilisk/locales/en-US/chrome/browser/browser.properties
index f1c39839b..abec30bf1 100644
--- a/application/basilisk/locales/en-US/chrome/browser/browser.properties
+++ b/application/basilisk/locales/en-US/chrome/browser/browser.properties
@@ -638,37 +638,6 @@ e10s.accessibilityNotice.acceptButton.accesskey = O
e10s.accessibilityNotice.enableAndRestart.label = Enable (Requires Restart)
e10s.accessibilityNotice.enableAndRestart.accesskey = E
-# LOCALIZATION NOTE (userContextPersonal.label,
-# userContextWork.label,
-# userContextShopping.label,
-# userContextBanking.label,
-# userContextNone.label):
-# These strings specify the four predefined contexts included in support of the
-# Contextual Identity / Containers project. Each context is meant to represent
-# the context that the user is in when interacting with the site. Different
-# contexts will store cookies and other information from those sites in
-# different, isolated locations. You can enable the feature by typing
-# about:config in the URL bar and changing privacy.userContext.enabled to true.
-# Once enabled, you can open a new tab in a specific context by clicking
-# File > New Container Tab > (1 of 4 contexts). Once opened, you will see these
-# strings on the right-hand side of the URL bar.
-userContextPersonal.label = Personal
-userContextWork.label = Work
-userContextBanking.label = Banking
-userContextShopping.label = Shopping
-userContextNone.label = No Container
-
-userContextPersonal.accesskey = P
-userContextWork.accesskey = W
-userContextBanking.accesskey = B
-userContextShopping.accesskey = S
-userContextNone.accesskey = N
-
-userContext.aboutPage.label = Manage containers
-userContext.aboutPage.accesskey = O
-
-userContextOpenLink.label = Open Link in New %S Tab
-
muteTab.label = Mute Tab
muteTab.accesskey = M
unmuteTab.label = Unmute Tab
diff --git a/application/basilisk/locales/en-US/chrome/browser/newTab.dtd b/application/basilisk/locales/en-US/chrome/browser/newTab.dtd
index 392aeb957..32a3ad70d 100644
--- a/application/basilisk/locales/en-US/chrome/browser/newTab.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/newTab.dtd
@@ -5,12 +5,9 @@
<!-- These strings are used in the about:newtab page -->
<!ENTITY newtab.pageTitle "New Tab">
<!ENTITY newtab.customize.classic "Show your top sites">
-<!ENTITY newtab.customize.cog.enhanced "Include suggested sites">
<!ENTITY newtab.customize.cog.title2 "NEW TAB CONTROLS">
<!ENTITY newtab.customize.cog.learn "Learn about New Tab">
<!ENTITY newtab.customize.title "Customize your New Tab page">
-<!ENTITY newtab.customize.suggested "Show suggested and your top sites">
-<!ENTITY newtab.customize.topsites "Show your top sites">
<!ENTITY newtab.customize.blank2 "Show blank page">
<!ENTITY newtab.undo.removedLabel "Thumbnail removed.">
<!ENTITY newtab.undo.undoButton "Undo.">
diff --git a/application/basilisk/locales/en-US/chrome/browser/newTab.properties b/application/basilisk/locales/en-US/chrome/browser/newTab.properties
index 7b3fe248e..922aa5847 100644
--- a/application/basilisk/locales/en-US/chrome/browser/newTab.properties
+++ b/application/basilisk/locales/en-US/chrome/browser/newTab.properties
@@ -5,42 +5,3 @@
newtab.pin=Pin this site at its current position
newtab.unpin=Unpin this site
newtab.block=Remove this site
-# LOCALIZATION NOTE(newtab.sponsored.button): This text appears for sponsored
-# and enhanced tiles on the same line as the tile's title, so prefer short
-# strings to avoid overlap. This string should be uppercase.
-newtab.sponsored.button=SPONSORED
-# LOCALIZATION NOTE(newtab.suggested.button): This text appears for sponsored
-# and suggested tiles on the same line as the tile's title, so prefer short
-# strings to avoid overlap. This string should be uppercase.
-newtab.suggested.tag=SUGGESTED
-# LOCALIZATION NOTE(newtab.suggested.button): %1$S will be replaced inline by
-# one of the user's top 100 sites that triggered this suggested tile.
-# This text appears for suggested tiles under the tile's title, so prefer short
-# strings to avoid truncating important text.
-newtab.suggested.button=Suggested for %1$S visitors
-# LOCALIZATION NOTE(newtab.sponsored.explain): %1$S will be replaced inline by
-# the (X) block icon. %2$S will be replaced by an active link using string
-# newtab.learn.link as text.
-newtab.sponsored.explain=This tile is being shown to you on behalf of a Mozilla partner. You can remove it at any time by clicking the %1$S button. %2$S
-# LOCALIZATION NOTE(newtab.sponsored.explain2): %1$S will be replaced inline by
-# the (X) block icon. %2$S will be replaced by an active link using string
-# newtab.learn.link as text.
-newtab.sponsored.explain2=This site is suggested to you on behalf of a Mozilla partner. You can remove it at any time by clicking the %1$S button. %2$S
-# LOCALIZATION NOTE(newtab.suggested.explain): %1$S will be replaced inline by
-# the (X) block icon. %2$S will be replaced by an active link using string
-# newtab.learn.link as text.
-newtab.suggested.explain=This site is suggested to you by Mozilla. You can remove it at any time by clicking the %1$S button. %2$S
-# LOCALIZATION NOTE(newtab.enhanced.explain): %1$S will be replaced inline by
-# the gear icon used to customize the new tab window. %2$S will be replaced by
-# an active link using string newtab.learn.link as text.
-newtab.enhanced.explain=A Mozilla partner has visually enhanced this tile, replacing the screenshot. You can turn off enhanced tiles by clicking the %1$S button for your preferences. %2$S
-newtab.intro1.paragraph1=Now when you open New Tab, you’ll also see sites we think might be interesting to you. Some may be suggested by Mozilla or sponsored by one of our partners.
-# LOCALIZATION NOTE(newtab.intro1.paragraph2): %1$S will be replaced inline by
-# an active link using string newtab.privacy.link as text. %2$S will be replaced
-# inline by the gear icon used to customize the new tab window.
-newtab.intro1.paragraph2=In order to provide this service, some data is automatically sent back to us in accordance with our %1$S. You can turn this off by unchecking the option under the gear icon (%2$S).
-newtab.learn.link=Learn more…
-newtab.privacy.link=Privacy Notice
-newtab.learn.link2=More about New Tab
-newtab.intro.header.update=New Tab got an update!
-newtab.intro.gotit=Got it!
diff --git a/application/basilisk/locales/en-US/chrome/browser/preferences/containers.dtd b/application/basilisk/locales/en-US/chrome/browser/preferences/containers.dtd
deleted file mode 100644
index 58eca1ace..000000000
--- a/application/basilisk/locales/en-US/chrome/browser/preferences/containers.dtd
+++ /dev/null
@@ -1,24 +0,0 @@
-<!-- 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/. -->
-
-<!ENTITY label.label "Name">
-<!ENTITY addButton.label "Add New Container">
-<!ENTITY addButton.accesskey "A">
-<!-- &#171; is &laquo; however it's not defined in XML -->
-<!ENTITY backLink.label "&#171; Go Back to Privacy">
-
-<!ENTITY window.title "Add New Container">
-<!ENTITY window.width "45em">
-
-<!ENTITY name.label "Name:">
-<!ENTITY name.accesskey "N">
-<!ENTITY icon.label "Icon:">
-<!ENTITY icon.accesskey "I">
-<!ENTITY color.label "Color:">
-<!ENTITY color.accesskey "o">
-<!ENTITY windowClose.key "w">
-
-<!ENTITY button.ok.label "Done">
-<!ENTITY button.ok.accesskey "D">
-
diff --git a/application/basilisk/locales/en-US/chrome/browser/preferences/containers.properties b/application/basilisk/locales/en-US/chrome/browser/preferences/containers.properties
deleted file mode 100644
index 9866a0659..000000000
--- a/application/basilisk/locales/en-US/chrome/browser/preferences/containers.properties
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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/.
-
-containers.removeButton = Remove
-containers.preferencesButton = Preferences
-containers.colorHeading = Color:
-containers.labelMinWidth = 4rem
-containers.nameLabel = Name:
-containers.namePlaceholder = Enter a container name
-containers.submitButton = Done
-containers.iconHeading = Icon:
-containers.updateContainerTitle = %S Container Preferences
-
-containers.blue.label = Blue
-containers.turquoise.label = Turquoise
-containers.green.label = Green
-containers.yellow.label = Yellow
-containers.orange.label = Orange
-containers.red.label = Red
-containers.pink.label = Pink
-containers.purple.label = Purple
-
-containers.fingerprint.label = Fingerprint
-containers.briefcase.label = Briefcase
-# LOCALIZATION NOTE (containers.dollar.label)
-# String represents a money sign but currently uses a dollar sign so don't change to local currency
-# See Bug 1291672
-containers.dollar.label = Dollar sign
-containers.cart.label = Shopping cart
-containers.circle.label = Dot
diff --git a/application/basilisk/locales/en-US/chrome/browser/preferences/cookies.dtd b/application/basilisk/locales/en-US/chrome/browser/preferences/cookies.dtd
index 5e7df9609..c83331328 100644
--- a/application/basilisk/locales/en-US/chrome/browser/preferences/cookies.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/preferences/cookies.dtd
@@ -14,7 +14,6 @@
<!ENTITY props.path.label "Path:">
<!ENTITY props.secure.label "Send For:">
<!ENTITY props.expires.label "Expires:">
-<!ENTITY props.container.label "Container:">
<!ENTITY window.title "Cookies">
<!ENTITY windowClose.key "w">
diff --git a/application/basilisk/locales/en-US/chrome/browser/preferences/preferences.dtd b/application/basilisk/locales/en-US/chrome/browser/preferences/preferences.dtd
index 7702c8c51..353e627d7 100644
--- a/application/basilisk/locales/en-US/chrome/browser/preferences/preferences.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/preferences/preferences.dtd
@@ -18,7 +18,6 @@
<!ENTITY paneContent.title "Content">
<!ENTITY paneApplications.title "Applications">
<!ENTITY panePrivacy.title "Privacy">
-<!ENTITY paneContainers.title "Container Tabs">
<!ENTITY paneSecurity.title "Security">
<!ENTITY paneAdvanced.title "Advanced">
diff --git a/application/basilisk/locales/en-US/chrome/browser/preferences/preferences.properties b/application/basilisk/locales/en-US/chrome/browser/preferences/preferences.properties
index 84fac427d..c0b7e1be0 100644
--- a/application/basilisk/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/application/basilisk/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -191,17 +191,3 @@ revertNoRestartButton=Revert
restartNow=Restart Now
restartLater=Restart Later
-
-disableContainersAlertTitle=Close All Container Tabs?
-
-# LOCALIZATION NOTE (disableContainersMsg): Semi-colon list of plural forms.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-# #S is the number of container tabs
-disableContainersMsg=If you disable Container Tabs now, #S container tab will be closed. Are you sure you want to disable Container Tabs?;If you disable Container Tabs now, #S container tabs will be closed. Are you sure you want to disable Container Tabs?
-
-# LOCALIZATION NOTE (disableContainersOkButton): Semi-colon list of plural forms.
-# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-# #S is the number of container tabs
-disableContainersOkButton=Close #S Container Tab;Close #S Container Tabs
-
-disableContainersButton2=Keep enabled
diff --git a/application/basilisk/locales/en-US/chrome/browser/preferences/privacy.dtd b/application/basilisk/locales/en-US/chrome/browser/preferences/privacy.dtd
index f743c4040..8820e92ab 100644
--- a/application/basilisk/locales/en-US/chrome/browser/preferences/privacy.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/preferences/privacy.dtd
@@ -110,10 +110,3 @@
<!ENTITY clearOnCloseSettings.label "Settings…">
<!ENTITY clearOnCloseSettings.accesskey "t">
-
-<!ENTITY browserContainersHeader.label "Container Tabs">
-<!ENTITY browserContainersLearnMore.label "Learn more">
-<!ENTITY browserContainersEnabled.label "Enable Container Tabs">
-<!ENTITY browserContainersEnabled.accesskey "n">
-<!ENTITY browserContainersSettings.label "Settings…">
-<!ENTITY browserContainersSettings.accesskey "i">
diff --git a/application/basilisk/locales/en-US/chrome/browser/preferences/sync.dtd b/application/basilisk/locales/en-US/chrome/browser/preferences/sync.dtd
index a5b290052..f6ef3b876 100644
--- a/application/basilisk/locales/en-US/chrome/browser/preferences/sync.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/preferences/sync.dtd
@@ -39,80 +39,9 @@
<!-- Device Settings -->
<!ENTITY syncDeviceName.label "Device Name:">
-<!ENTITY fxaSyncDeviceName.label "Device Name">
-<!ENTITY changeSyncDeviceName.label "Change Device Name…">
-<!ENTITY changeSyncDeviceName.accesskey "h">
-<!ENTITY cancelChangeSyncDeviceName.label "Cancel">
-<!ENTITY cancelChangeSyncDeviceName.accesskey "n">
-<!ENTITY saveChangeSyncDeviceName.label "Save">
-<!ENTITY saveChangeSyncDeviceName.accesskey "v">
+<!ENTITY syncDeviceName.accesskey "c">
<!ENTITY unlinkDevice.label "Unlink This Device">
<!-- Footer stuff -->
<!ENTITY prefs.tosLink.label "Terms of Service">
<!ENTITY prefs.ppLink.label "Privacy Policy">
-
-<!-- Firefox Accounts stuff -->
-<!ENTITY fxaPrivacyNotice.link.label "Privacy Notice">
-<!ENTITY determiningAcctStatus.label "Determining your account status…">
-
-<!-- LOCALIZATION NOTE (signedInUnverified.beforename.label,
-signedInUnverified.aftername.label): these two string are used respectively
-before and after the account email address. Localizers can use one of them, or
-both, to better adapt this sentence to their language.
--->
-<!ENTITY signedInUnverified.beforename.label "">
-<!ENTITY signedInUnverified.aftername.label "is not verified.">
-
-<!-- LOCALIZATION NOTE (signedInLoginFailure.beforename.label,
-signedInLoginFailure.aftername.label): these two string are used respectively
-before and after the account email address. Localizers can use one of them, or
-both, to better adapt this sentence to their language.
--->
-<!ENTITY signedInLoginFailure.beforename.label "Please sign in to reconnect">
-<!ENTITY signedInLoginFailure.aftername.label "">
-
-<!ENTITY notSignedIn.label "You are not signed in.">
-<!ENTITY signIn.label "Sign in">
-<!ENTITY signIn.accesskey "g">
-<!ENTITY profilePicture.tooltip "Change profile picture">
-<!ENTITY verifiedManage.label "Manage Account">
-<!ENTITY verifiedManage.accesskey "o">
-<!ENTITY disconnect.label "Disconnect…">
-<!ENTITY disconnect.accesskey "D">
-<!ENTITY verify.label "Verify Email">
-<!ENTITY verify.accesskey "V">
-<!ENTITY forget.label "Forget this Email">
-<!ENTITY forget.accesskey "F">
-
-<!ENTITY welcome.description "Access your tabs, bookmarks, passwords and more wherever you use &brandShortName;.">
-<!ENTITY welcome.signIn.label "Sign In">
-<!ENTITY welcome.createAccount.label "Create Account">
-
-<!ENTITY welcome.useOldSync.label "Using an older version of Sync?">
-
-<!ENTITY signedOut.caption "Take your Web with you">
-<!ENTITY signedOut.description "Synchronize your bookmarks, history, tabs, passwords, add-ons, and preferences across all your devices.">
-<!ENTITY signedOut.accountBox.title "Connect with a &syncBrand.fxAccount.label;">
-<!ENTITY signedOut.accountBox.create "Create Account">
-<!ENTITY signedOut.accountBox.create.accesskey "C">
-<!ENTITY signedOut.accountBox.signin "Sign In">
-<!ENTITY signedOut.accountBox.signin.accesskey "I">
-
-<!ENTITY signedIn.engines.label "Sync across all devices">
-
-<!-- LOCALIZATION NOTE (mobilePromo3.*): the following strings will be used to
- create a single sentence with active links.
- The resulting sentence in English is: "Download Firefox for
- Android or iOS to sync with your mobile device." -->
-
-<!ENTITY mobilePromo3.start "Download Firefox for ">
-<!-- LOCALIZATION NOTE (mobilePromo3.androidLink): This is a link title that links to https://www.mozilla.org/firefox/android/ -->
-<!ENTITY mobilePromo3.androidLink "Android">
-
-<!-- LOCALIZATION NOTE (mobilePromo3.iOSBefore): This is text displayed between mobilePromo3.androidLink and mobilePromo3.iosLink -->
-<!ENTITY mobilePromo3.iOSBefore " or ">
-<!-- LOCALIZATION NOTE (mobilePromo3.iOSLink): This is a link title that links to https://www.mozilla.org/firefox/ios/ -->
-<!ENTITY mobilePromo3.iOSLink "iOS">
-
-<!ENTITY mobilePromo3.end " to sync with your mobile device.">
diff --git a/application/basilisk/locales/en-US/chrome/browser/syncBrand.dtd b/application/basilisk/locales/en-US/chrome/browser/syncBrand.dtd
index 71a9f68af..bc4d1b3e0 100644
--- a/application/basilisk/locales/en-US/chrome/browser/syncBrand.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/syncBrand.dtd
@@ -4,4 +4,3 @@
<!ENTITY syncBrand.shortName.label "Sync">
<!ENTITY syncBrand.fullName.label "Pale Moon Sync">
-<!ENTITY syncBrand.fxAccount.label "Firefox Account">
diff --git a/application/basilisk/locales/en-US/chrome/browser/syncKey.dtd b/application/basilisk/locales/en-US/chrome/browser/syncKey.dtd
index 2ff001842..f37f2c92e 100644
--- a/application/basilisk/locales/en-US/chrome/browser/syncKey.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/syncKey.dtd
@@ -5,12 +5,12 @@
<!ENTITY syncKey.page.title "Your &syncBrand.fullName.label; Key">
<!ENTITY syncKey.page.description2 "This key is used to decode the data in your &syncBrand.fullName.label; account. You will need to enter the key each time you configure &syncBrand.fullName.label; on a new device.">
<!ENTITY syncKey.keepItSecret.heading "Keep it secret">
-<!ENTITY syncKey.keepItSecret.description "Your &syncBrand.fullName.label; account is encrypted to protect your privacy. Without this key, it would take years for anyone to decode your personal information. You are the only person who holds this key. This means you’re the only one who can access your &syncBrand.fullName.label; data.">
+<!ENTITY syncKey.keepItSecret.description "Your &syncBrand.fullName.label; account is encrypted to protect your privacy. Without this key, it would take years for anyone to decode your personal information. You are the only person who holds this key. This means you're the only one who can access your &syncBrand.fullName.label; data.">
<!ENTITY syncKey.keepItSafe.heading "Keep it safe">
<!ENTITY syncKey.keepItSafe1.description "Do not lose this key.">
-<!ENTITY syncKey.keepItSafe2.description " We don’t keep a copy of your key (that wouldn’t be keeping it secret!) so ">
-<!ENTITY syncKey.keepItSafe3.description "we can’t help you recover it">
-<!ENTITY syncKey.keepItSafe4a.description " if it’s lost. You’ll need to use this key any time you connect a new device to &syncBrand.fullName.label;.">
+<!ENTITY syncKey.keepItSafe2.description " We don't keep a copy of your key (that wouldn't be keeping it secret!) so ">
+<!ENTITY syncKey.keepItSafe3.description "we can't help you recover it">
+<!ENTITY syncKey.keepItSafe4a.description " if it's lost. You'll need to use this key any time you connect a new device to &syncBrand.fullName.label;.">
<!ENTITY syncKey.findOutMore1.label "Find out more about &syncBrand.fullName.label; and your privacy at ">
<!ENTITY syncKey.findOutMore2.label ".">
<!ENTITY syncKey.footer1.label "&syncBrand.fullName.label; Terms of Service are available at ">
diff --git a/application/basilisk/locales/en-US/chrome/browser/syncProgress.dtd b/application/basilisk/locales/en-US/chrome/browser/syncProgress.dtd
new file mode 100644
index 000000000..db45cb935
--- /dev/null
+++ b/application/basilisk/locales/en-US/chrome/browser/syncProgress.dtd
@@ -0,0 +1,15 @@
+<!-- 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/. -->
+
+<!ENTITY % brandDTD
+ SYSTEM "chrome://branding/locale/brand.dtd">
+ %brandDTD;
+
+<!-- These strings are used in the sync progress upload page -->
+<!ENTITY syncProgress.pageTitle "Your First Sync">
+<!ENTITY syncProgress.textBlurb "Your data is now being encrypted and uploaded in the background. You can close this tab and continue using &brandShortName;.">
+<!ENTITY syncProgress.closeButton "Close">
+<!ENTITY syncProgress.logoAltText "&brandShortName; logo">
+<!ENTITY syncProgress.diffText "&brandShortName; will now automatically sync in the background. You can close this tab and continue using &brandShortName;.">
+
diff --git a/application/basilisk/locales/en-US/chrome/browser/syncQuota.properties b/application/basilisk/locales/en-US/chrome/browser/syncQuota.properties
index 099090ec9..0e1b857ca 100644
--- a/application/basilisk/locales/en-US/chrome/browser/syncQuota.properties
+++ b/application/basilisk/locales/en-US/chrome/browser/syncQuota.properties
@@ -30,7 +30,7 @@ quota.remove.label = Remove
quota.treeCaption.label = Uncheck items to stop syncing them and free up space on the server.
# LOCALIZATION NOTE (quota.removal.label): %S is a list of engines that will be
# disabled and whose data will be removed once the user confirms.
-quota.removal.label = Firefox Sync will remove the following data: %S.
+quota.removal.label = Sync will remove the following data: %S.
# LOCALIZATION NOTE (quota.list.separator): This is the separator string used
# for the list of engines (incl. spaces where appropriate)
quota.list.separator = ,\u0020
diff --git a/application/basilisk/locales/en-US/chrome/browser/syncSetup.dtd b/application/basilisk/locales/en-US/chrome/browser/syncSetup.dtd
index 2657156b7..7ee938e5d 100644
--- a/application/basilisk/locales/en-US/chrome/browser/syncSetup.dtd
+++ b/application/basilisk/locales/en-US/chrome/browser/syncSetup.dtd
@@ -6,13 +6,13 @@
<!-- First page of the wizard -->
-<!ENTITY setup.pickSetupType.description2 "Welcome! If you’ve never used &syncBrand.fullName.label; before, you will need to create a new account.">
+<!ENTITY setup.pickSetupType.description2 "Welcome! If you've never used &syncBrand.fullName.label; before, you will need to create a new account.">
<!ENTITY button.createNewAccount.label "Create a New Account">
<!ENTITY button.haveAccount.label "I Have an Account">
<!ENTITY setup.choicePage.title.label "Have you used &syncBrand.fullName.label; before?">
-<!ENTITY setup.choicePage.new.label "I’ve never used &syncBrand.shortName.label; before">
-<!ENTITY setup.choicePage.existing2.label "I’m already using &syncBrand.shortName.label; on another device">
+<!ENTITY setup.choicePage.new.label "I've never used &syncBrand.shortName.label; before">
+<!ENTITY setup.choicePage.existing2.label "I'm already using &syncBrand.shortName.label; on another device">
<!-- New Account AND Existing Account -->
<!ENTITY server.label "Server">
@@ -33,6 +33,8 @@
<!ENTITY setup.choosePassword.accesskey "P">
<!ENTITY setup.confirmPassword.label "Confirm Password">
<!ENTITY setup.confirmPassword.accesskey "m">
+<!ENTITY setup.setupMetro.label "Sync with Windows 8 style &brandShortName;">
+<!ENTITY setup.setupMetro.accesskey "S">
<!-- LOCALIZATION NOTE: tosAgree1, tosLink, tosAgree2, ppLink, tosAgree3 are
joined with implicit white space, so spaces in the strings aren't necessary -->
@@ -60,7 +62,7 @@
<!-- Existing Account Page 1: Pair a Device (incl. Pair a Device dialog strings) -->
<!ENTITY pairDevice.title.label "Pair a Device">
<!ENTITY addDevice.showMeHow.label "Show me how.">
-<!ENTITY addDevice.dontHaveDevice.label "I don’t have the device with me">
+<!ENTITY addDevice.dontHaveDevice.label "I don't have the device with me">
<!ENTITY pairDevice.setup.description.label "To activate, select &#x0022;Pair a Device&#x0022; on your other device.">
<!ENTITY addDevice.setup.enterCode.label "Then, enter this code:">
<!ENTITY pairDevice.dialog.description.label "To activate your new device, select &#x0022;Set Up Sync&#x0022; on the device.">
@@ -72,7 +74,7 @@
<!-- Existing Account Page 2: Manual Login -->
<!ENTITY setup.signInPage.title.label "Sign In">
-<!ENTITY existingRecoveryKey.description "You can get a copy of your Recovery Key by going to &syncBrand.shortName.label; Preferences on your other device, and selecting &#x0022;My Recovery Key&#x0022; under &#x0022;Manage Account&#x0022;.">
+<!ENTITY existingRecoveryKey.description "You can get a copy of your Recovery Key by going to &syncBrand.shortName.label; Options on your other device, and selecting &#x0022;My Recovery Key&#x0022; under &#x0022;Manage Account&#x0022;.">
<!ENTITY verifying.label "Verifying…">
<!ENTITY resetPassword.label "Reset Password">
<!ENTITY resetSyncKey.label "I have lost my other device.">
@@ -96,14 +98,14 @@
<!ENTITY engine.addons.label "Add-ons">
<!ENTITY engine.addons.accesskey "A">
-<!ENTITY choice2a.merge.main.label "Merge this device’s data with my &syncBrand.shortName.label; data">
+<!ENTITY choice2a.merge.main.label "Merge this device's data with my &syncBrand.shortName.label; data">
<!ENTITY choice2.merge.recommended.label "Recommended:">
<!ENTITY choice2a.client.main.label "Replace all data on this device with my &syncBrand.shortName.label; data">
-<!ENTITY choice2a.server.main.label "Replace all other devices with this device’s data">
+<!ENTITY choice2a.server.main.label "Replace all other devices with this device's data">
<!-- Confirm Merge Options -->
<!ENTITY setup.optionsConfirmPage.title "Confirm">
-<!ENTITY confirm.merge2.label "&syncBrand.fullName.label; will now merge all this device’s browser data into your Sync account.">
+<!ENTITY confirm.merge2.label "&syncBrand.fullName.label; will now merge all this device's browser data into your Sync account.">
<!ENTITY confirm.client3.label "Warning: The following &brandShortName; data on this device will be deleted:">
<!ENTITY confirm.client2.moreinfo.label "&brandShortName; will then copy your &syncBrand.fullName.label; data to this device.">
<!ENTITY confirm.server2.label "Warning: The following devices will be overwritten with your local data:">
diff --git a/application/basilisk/locales/en-US/chrome/browser/syncSetup.properties b/application/basilisk/locales/en-US/chrome/browser/syncSetup.properties
index 9d388af86..8a5170adb 100644
--- a/application/basilisk/locales/en-US/chrome/browser/syncSetup.properties
+++ b/application/basilisk/locales/en-US/chrome/browser/syncSetup.properties
@@ -35,33 +35,17 @@ passwordsCount.label = #1 password;#1 passwords
# LOCALIZATION NOTE (addonsCount.label): Semicolon-separated list of plural forms.
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
# #1 is the number of add-ons, see the link above for forms
-addonsCount.label = #1 add-on;#1 add-ons
+addonsCount.label = #1 addon;#1 addons
save.recoverykey.title = Save Recovery Key
-save.recoverykey.defaultfilename = Firefox Recovery Key.html
+save.recoverykey.defaultfilename = Pale Moon Recovery Key.html
-newAccount.action.label = Firefox Sync is now set up to automatically sync all of your browser data.
+newAccount.action.label = Sync is now set up to automatically sync all of your browser data.
newAccount.change.label = You can choose exactly what to sync by selecting Sync Options below.
-resetClient.change2.label = Firefox Sync will now merge all this device’s browser data into your Sync account.
-wipeClient.change2.label = Firefox Sync will now replace all of the browser data on this device with the data in your Sync account.
-wipeRemote.change2.label = Firefox Sync will now replace all of the browser data in your Sync account with the data on this device.
+resetClient.change2.label = Sync will now merge all this device's browser data into your Sync account.
+wipeClient.change2.label = Sync will now replace all of the browser data on this device with the data in your Sync account.
+wipeRemote.change2.label = Sync will now replace all of the browser data in your Sync account with the data on this device.
existingAccount.change.label = You can change this preference by selecting Sync Options below.
# Several other strings are used (via Weave.Status.login), but they come from
# /services/sync
-
-# Firefox Accounts based setup.
-continue.label = Continue
-
-# LOCALIZATION NOTE (disconnect.label, disconnect.verify.title, disconnect.verify.bodyHeading, disconnect.verify.bodyText):
-# These strings are used in the confirmation dialog shown when the user hits the disconnect button
-# LOCALIZATION NOTE (disconnect.label): This is the label for the disconnect button
-disconnect.label = Disconnect
-disconnect.verify.title = Disconnect
-disconnect.verify.bodyHeading = Disconnect from Sync?
-disconnect.verify.bodyText = Your browsing data will remain on this computer, but it will no longer sync with your account.
-
-relinkVerify.title = Merge Warning
-relinkVerify.heading = Are you sure you want to sign in to Sync?
-# LOCALIZATION NOTE (relinkVerify.description): Email address of a user previously signed into sync.
-relinkVerify.description = A different user was previously signed in to Sync on this computer. Signing in will merge this browser’s bookmarks, passwords and other settings with %S
diff --git a/application/basilisk/locales/en-US/installer/custom.properties b/application/basilisk/locales/en-US/installer/custom.properties
index 4abb1a550..0f86f5528 100644
--- a/application/basilisk/locales/en-US/installer/custom.properties
+++ b/application/basilisk/locales/en-US/installer/custom.properties
@@ -25,10 +25,6 @@ OPTIONS_PAGE_TITLE=Setup Type
OPTIONS_PAGE_SUBTITLE=Choose setup options
SHORTCUTS_PAGE_TITLE=Set Up Shortcuts
SHORTCUTS_PAGE_SUBTITLE=Create Program Icons
-COMPONENTS_PAGE_TITLE=Set Up Optional Components
-COMPONENTS_PAGE_SUBTITLE=Optional Recommended Components
-OPTIONAL_COMPONENTS_DESC=The Maintenance Service will allow you to update $BrandShortName silently in the background.
-MAINTENANCE_SERVICE_CHECKBOX_DESC=Install &Maintenance Service
SUMMARY_PAGE_TITLE=Summary
SUMMARY_PAGE_SUBTITLE=Ready to start installing $BrandShortName
SUMMARY_INSTALLED_TO=$BrandShortName will be installed to the following location:
diff --git a/application/basilisk/locales/jar.mn b/application/basilisk/locales/jar.mn
index 5c5a72a1f..345c0525a 100644
--- a/application/basilisk/locales/jar.mn
+++ b/application/basilisk/locales/jar.mn
@@ -7,12 +7,10 @@
@AB_CD@.jar:
% locale browser @AB_CD@ %locale/browser/
* locale/browser/bookmarks.html (generic/profile/bookmarks.html.in)
- locale/browser/aboutAccounts.dtd (%chrome/browser/aboutAccounts.dtd)
locale/browser/aboutDialog.dtd (%chrome/browser/aboutDialog.dtd)
locale/browser/aboutPrivateBrowsing.dtd (%chrome/browser/aboutPrivateBrowsing.dtd)
locale/browser/aboutPrivateBrowsing.properties (%chrome/browser/aboutPrivateBrowsing.properties)
- locale/browser/aboutRobots.dtd (%chrome/browser/aboutRobots.dtd)
- locale/browser/aboutHome.dtd (%chrome/browser/aboutHome.dtd)
+* locale/browser/aboutHome.dtd (%chrome/browser/aboutHome.dtd)
locale/browser/accounts.properties (%chrome/browser/accounts.properties)
#ifdef MOZ_SERVICES_HEALTHREPORT
locale/browser/aboutHealthReport.dtd (%chrome/browser/aboutHealthReport.dtd)
@@ -21,8 +19,7 @@
locale/browser/aboutSessionRestore.dtd (%chrome/browser/aboutSessionRestore.dtd)
locale/browser/aboutTabCrashed.dtd (%chrome/browser/aboutTabCrashed.dtd)
locale/browser/syncCustomize.dtd (%chrome/browser/syncCustomize.dtd)
- locale/browser/aboutSyncTabs.dtd (%chrome/browser/aboutSyncTabs.dtd)
- locale/browser/browser.dtd (%chrome/browser/browser.dtd)
+* locale/browser/browser.dtd (%chrome/browser/browser.dtd)
locale/browser/baseMenuOverlay.dtd (%chrome/browser/baseMenuOverlay.dtd)
locale/browser/browser.properties (%chrome/browser/browser.properties)
locale/browser/customizableui/customizableWidgets.properties (%chrome/browser/customizableui/customizableWidgets.properties)
@@ -79,13 +76,14 @@
locale/browser/preferences/permissions.dtd (%chrome/browser/preferences/permissions.dtd)
locale/browser/preferences/preferences.dtd (%chrome/browser/preferences/preferences.dtd)
locale/browser/preferences/preferences.properties (%chrome/browser/preferences/preferences.properties)
- locale/browser/preferences/containers.properties (%chrome/browser/preferences/containers.properties)
* locale/browser/preferences/privacy.dtd (%chrome/browser/preferences/privacy.dtd)
locale/browser/preferences/security.dtd (%chrome/browser/preferences/security.dtd)
- locale/browser/preferences/containers.dtd (%chrome/browser/preferences/containers.dtd)
+#ifdef MOZ_SERVICES_SYNC
locale/browser/preferences/sync.dtd (%chrome/browser/preferences/sync.dtd)
+#endif
locale/browser/preferences/tabs.dtd (%chrome/browser/preferences/tabs.dtd)
locale/browser/preferences/search.dtd (%chrome/browser/preferences/search.dtd)
+#ifdef MOZ_SERVICES_SYNC
locale/browser/syncBrand.dtd (%chrome/browser/syncBrand.dtd)
locale/browser/syncSetup.dtd (%chrome/browser/syncSetup.dtd)
locale/browser/syncSetup.properties (%chrome/browser/syncSetup.properties)
@@ -93,6 +91,9 @@
locale/browser/syncKey.dtd (%chrome/browser/syncKey.dtd)
locale/browser/syncQuota.dtd (%chrome/browser/syncQuota.dtd)
locale/browser/syncQuota.properties (%chrome/browser/syncQuota.properties)
+ locale/browser/syncProgress.dtd (%chrome/browser/syncProgress.dtd)
+ locale/browser/aboutSyncTabs.dtd (%chrome/browser/aboutSyncTabs.dtd)
+#endif
% resource search-plugins chrome://browser/locale/searchplugins/
#if BUILD_FASTER
locale/browser/searchplugins/ (searchplugins/*.xml)
diff --git a/application/basilisk/modules/AboutHome.jsm b/application/basilisk/modules/AboutHome.jsm
index 639194c20..671448480 100644
--- a/application/basilisk/modules/AboutHome.jsm
+++ b/application/basilisk/modules/AboutHome.jsm
@@ -17,8 +17,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
"resource://gre/modules/AppConstants.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AutoMigrate",
"resource:///modules/AutoMigrate.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
- "resource://gre/modules/FxAccounts.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
diff --git a/application/basilisk/modules/AboutNewTab.jsm b/application/basilisk/modules/AboutNewTab.jsm
index 4337c5a2d..e170e9c8a 100644
--- a/application/basilisk/modules/AboutNewTab.jsm
+++ b/application/basilisk/modules/AboutNewTab.jsm
@@ -33,7 +33,6 @@ var AboutNewTab = {
customize: function(message) {
NewTabUtils.allPages.enabled = message.data.enabled;
- NewTabUtils.allPages.enhanced = message.data.enhanced;
},
uninit: function() {
diff --git a/application/basilisk/modules/ContentClick.jsm b/application/basilisk/modules/ContentClick.jsm
index 40101d5d3..4cd665f8c 100644
--- a/application/basilisk/modules/ContentClick.jsm
+++ b/application/basilisk/modules/ContentClick.jsm
@@ -88,11 +88,6 @@ var ContentClick = {
triggeringPrincipal: json.triggeringPrincipal,
};
- // The new tab/window must use the same userContextId.
- if (json.originAttributes.userContextId) {
- params.userContextId = json.originAttributes.userContextId;
- }
-
window.openLinkIn(json.href, where, params);
}
};
diff --git a/application/basilisk/modules/DirectoryLinksProvider.jsm b/application/basilisk/modules/DirectoryLinksProvider.jsm
deleted file mode 100644
index 117564099..000000000
--- a/application/basilisk/modules/DirectoryLinksProvider.jsm
+++ /dev/null
@@ -1,1255 +0,0 @@
-/* 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.EXPORTED_SYMBOLS = ["DirectoryLinksProvider"];
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cu = Components.utils;
-const ParserUtils = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils);
-
-Cu.importGlobalProperties(["XMLHttpRequest"]);
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/Timer.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
- "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
- "resource://gre/modules/NewTabUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "OS",
- "resource://gre/modules/osfile.jsm")
-XPCOMUtils.defineLazyModuleGetter(this, "Promise",
- "resource://gre/modules/Promise.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
- "resource://gre/modules/UpdateUtils.jsm");
-XPCOMUtils.defineLazyServiceGetter(this, "eTLD",
- "@mozilla.org/network/effective-tld-service;1",
- "nsIEffectiveTLDService");
-XPCOMUtils.defineLazyGetter(this, "gTextDecoder", () => {
- return new TextDecoder();
-});
-XPCOMUtils.defineLazyGetter(this, "gCryptoHash", function () {
- return Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
-});
-XPCOMUtils.defineLazyGetter(this, "gUnicodeConverter", function () {
- let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
- .createInstance(Ci.nsIScriptableUnicodeConverter);
- converter.charset = 'utf8';
- return converter;
-});
-
-
-// The filename where directory links are stored locally
-const DIRECTORY_LINKS_FILE = "directoryLinks.json";
-const DIRECTORY_LINKS_TYPE = "application/json";
-
-// The preference that tells whether to match the OS locale
-const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
-
-// The preference that tells what locale the user selected
-const PREF_SELECTED_LOCALE = "general.useragent.locale";
-
-// The preference that tells where to obtain directory links
-const PREF_DIRECTORY_SOURCE = "browser.newtabpage.directory.source";
-
-// The preference that tells where to send click/view pings
-const PREF_DIRECTORY_PING = "browser.newtabpage.directory.ping";
-
-// The preference that tells if newtab is enhanced
-const PREF_NEWTAB_ENHANCED = "browser.newtabpage.enhanced";
-
-// Only allow link urls that are http(s)
-const ALLOWED_LINK_SCHEMES = new Set(["http", "https"]);
-
-// Only allow link image urls that are https or data
-const ALLOWED_IMAGE_SCHEMES = new Set(["https", "data"]);
-
-// Only allow urls to Mozilla's CDN or empty (for data URIs)
-const ALLOWED_URL_BASE = new Set(["mozilla.net", ""]);
-
-// The frecency of a directory link
-const DIRECTORY_FRECENCY = 1000;
-
-// The frecency of a suggested link
-const SUGGESTED_FRECENCY = Infinity;
-
-// The filename where frequency cap data stored locally
-const FREQUENCY_CAP_FILE = "frequencyCap.json";
-
-// Default settings for daily and total frequency caps
-const DEFAULT_DAILY_FREQUENCY_CAP = 3;
-const DEFAULT_TOTAL_FREQUENCY_CAP = 10;
-
-// Default timeDelta to prune unused frequency cap objects
-// currently set to 10 days in milliseconds
-const DEFAULT_PRUNE_TIME_DELTA = 10*24*60*60*1000;
-
-// The min number of visible (not blocked) history tiles to have before showing suggested tiles
-const MIN_VISIBLE_HISTORY_TILES = 8;
-
-// The max number of visible (not blocked) history tiles to test for inadjacency
-const MAX_VISIBLE_HISTORY_TILES = 15;
-
-// Allowed ping actions remotely stored as columns: case-insensitive [a-z0-9_]
-const PING_ACTIONS = ["block", "click", "pin", "sponsored", "sponsored_link", "unpin", "view"];
-
-// Location of inadjacent sites json
-const INADJACENCY_SOURCE = "chrome://browser/content/newtab/newTab.inadjacent.json";
-
-// Fake URL to keep track of last block of a suggested tile in the frequency cap object
-const FAKE_SUGGESTED_BLOCK_URL = "ignore://suggested_block";
-
-// Time before suggested tile is allowed to play again after block - default to 1 day
-const AFTER_SUGGESTED_BLOCK_DECAY_TIME = 24*60*60*1000;
-
-/**
- * Singleton that serves as the provider of directory links.
- * Directory links are a hard-coded set of links shown if a user's link
- * inventory is empty.
- */
-var DirectoryLinksProvider = {
-
- __linksURL: null,
-
- _observers: new Set(),
-
- // links download deferred, resolved upon download completion
- _downloadDeferred: null,
-
- // download default interval is 24 hours in milliseconds
- _downloadIntervalMS: 86400000,
-
- /**
- * A mapping from eTLD+1 to an enhanced link objects
- */
- _enhancedLinks: new Map(),
-
- /**
- * A mapping from site to a list of suggested link objects
- */
- _suggestedLinks: new Map(),
-
- /**
- * Frequency Cap object - maintains daily and total tile counts, and frequency cap settings
- */
- _frequencyCaps: {},
-
- /**
- * A set of top sites that we can provide suggested links for
- */
- _topSitesWithSuggestedLinks: new Set(),
-
- /**
- * lookup Set of inadjacent domains
- */
- _inadjacentSites: new Set(),
-
- /**
- * This flag is set if there is a suggested tile configured to avoid
- * inadjacent sites in new tab
- */
- _avoidInadjacentSites: false,
-
- /**
- * This flag is set if _avoidInadjacentSites is true and there is
- * an inadjacent site in the new tab
- */
- _newTabHasInadjacentSite: false,
-
- get _observedPrefs() {
- return Object.freeze({
- enhanced: PREF_NEWTAB_ENHANCED,
- linksURL: PREF_DIRECTORY_SOURCE,
- matchOSLocale: PREF_MATCH_OS_LOCALE,
- prefSelectedLocale: PREF_SELECTED_LOCALE,
- });
- },
-
- get _linksURL() {
- if (!this.__linksURL) {
- try {
- this.__linksURL = Services.prefs.getCharPref(this._observedPrefs["linksURL"]);
- this.__linksURLModified = Services.prefs.prefHasUserValue(this._observedPrefs["linksURL"]);
- }
- catch (e) {
- Cu.reportError("Error fetching directory links url from prefs: " + e);
- }
- }
- return this.__linksURL;
- },
-
- /**
- * Gets the currently selected locale for display.
- * @return the selected locale or "en-US" if none is selected
- */
- get locale() {
- let matchOS;
- try {
- matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE);
- }
- catch (e) {}
-
- if (matchOS) {
- return Services.locale.getLocaleComponentForUserAgent();
- }
-
- try {
- let locale = Services.prefs.getComplexValue(PREF_SELECTED_LOCALE,
- Ci.nsIPrefLocalizedString);
- if (locale) {
- return locale.data;
- }
- }
- catch (e) {}
-
- try {
- return Services.prefs.getCharPref(PREF_SELECTED_LOCALE);
- }
- catch (e) {}
-
- return "en-US";
- },
-
- /**
- * Set appropriate default ping behavior controlled by enhanced pref
- */
- _setDefaultEnhanced: function DirectoryLinksProvider_setDefaultEnhanced() {
- if (!Services.prefs.prefHasUserValue(PREF_NEWTAB_ENHANCED)) {
- let enhanced = Services.prefs.getBoolPref(PREF_NEWTAB_ENHANCED);
- try {
- // Default to not enhanced if DNT is set to tell websites to not track
- if (Services.prefs.getBoolPref("privacy.donottrackheader.enabled")) {
- enhanced = false;
- }
- }
- catch (ex) {}
- Services.prefs.setBoolPref(PREF_NEWTAB_ENHANCED, enhanced);
- }
- },
-
- observe: function DirectoryLinksProvider_observe(aSubject, aTopic, aData) {
- if (aTopic == "nsPref:changed") {
- switch (aData) {
- // Re-set the default in case the user clears the pref
- case this._observedPrefs.enhanced:
- this._setDefaultEnhanced();
- break;
-
- case this._observedPrefs.linksURL:
- delete this.__linksURL;
- // fallthrough
-
- // Force directory download on changes to fetch related prefs
- case this._observedPrefs.matchOSLocale:
- case this._observedPrefs.prefSelectedLocale:
- this._fetchAndCacheLinksIfNecessary(true);
- break;
- }
- }
- },
-
- _addPrefsObserver: function DirectoryLinksProvider_addObserver() {
- for (let pref in this._observedPrefs) {
- let prefName = this._observedPrefs[pref];
- Services.prefs.addObserver(prefName, this, false);
- }
- },
-
- _removePrefsObserver: function DirectoryLinksProvider_removeObserver() {
- for (let pref in this._observedPrefs) {
- let prefName = this._observedPrefs[pref];
- Services.prefs.removeObserver(prefName, this);
- }
- },
-
- _cacheSuggestedLinks: function(link) {
- // Don't cache links that don't have the expected 'frecent_sites'
- if (!link.frecent_sites) {
- return;
- }
-
- for (let suggestedSite of link.frecent_sites) {
- let suggestedMap = this._suggestedLinks.get(suggestedSite) || new Map();
- suggestedMap.set(link.url, link);
- this._setupStartEndTime(link);
- this._suggestedLinks.set(suggestedSite, suggestedMap);
- }
- },
-
- _fetchAndCacheLinks: function DirectoryLinksProvider_fetchAndCacheLinks(uri) {
- // Replace with the same display locale used for selecting links data
- uri = uri.replace("%LOCALE%", this.locale);
- uri = uri.replace("%CHANNEL%", UpdateUtils.UpdateChannel);
-
- return this._downloadJsonData(uri).then(json => {
- return OS.File.writeAtomic(this._directoryFilePath, json, {tmpPath: this._directoryFilePath + ".tmp"});
- });
- },
-
- /**
- * Downloads a links with json content
- * @param download uri
- * @return promise resolved to json string, "{}" returned if status != 200
- */
- _downloadJsonData: function DirectoryLinksProvider__downloadJsonData(uri) {
- let deferred = Promise.defer();
- let xmlHttp = this._newXHR();
-
- xmlHttp.onload = function(aResponse) {
- let json = this.responseText;
- if (this.status && this.status != 200) {
- json = "{}";
- }
- deferred.resolve(json);
- };
-
- xmlHttp.onerror = function(e) {
- deferred.reject("Fetching " + uri + " results in error code: " + e.target.status);
- };
-
- try {
- xmlHttp.open("GET", uri);
- // Override the type so XHR doesn't complain about not well-formed XML
- xmlHttp.overrideMimeType(DIRECTORY_LINKS_TYPE);
- // Set the appropriate request type for servers that require correct types
- xmlHttp.setRequestHeader("Content-Type", DIRECTORY_LINKS_TYPE);
- xmlHttp.send();
- } catch (e) {
- deferred.reject("Error fetching " + uri);
- Cu.reportError(e);
- }
- return deferred.promise;
- },
-
- /**
- * Downloads directory links if needed
- * @return promise resolved immediately if no download needed, or upon completion
- */
- _fetchAndCacheLinksIfNecessary: function DirectoryLinksProvider_fetchAndCacheLinksIfNecessary(forceDownload=false) {
- if (this._downloadDeferred) {
- // fetching links already - just return the promise
- return this._downloadDeferred.promise;
- }
-
- if (forceDownload || this._needsDownload) {
- this._downloadDeferred = Promise.defer();
- this._fetchAndCacheLinks(this._linksURL).then(() => {
- // the new file was successfully downloaded and cached, so update a timestamp
- this._lastDownloadMS = Date.now();
- this._downloadDeferred.resolve();
- this._downloadDeferred = null;
- this._callObservers("onManyLinksChanged")
- },
- error => {
- this._downloadDeferred.resolve();
- this._downloadDeferred = null;
- this._callObservers("onDownloadFail");
- });
- return this._downloadDeferred.promise;
- }
-
- // download is not needed
- return Promise.resolve();
- },
-
- /**
- * @return true if download is needed, false otherwise
- */
- get _needsDownload () {
- // fail if last download occured less then 24 hours ago
- if ((Date.now() - this._lastDownloadMS) > this._downloadIntervalMS) {
- return true;
- }
- return false;
- },
-
- /**
- * Create a new XMLHttpRequest that is anonymous, i.e., doesn't send cookies
- */
- _newXHR() {
- return new XMLHttpRequest({mozAnon: true});
- },
-
- /**
- * Reads directory links file and parses its content
- * @return a promise resolved to an object with keys 'directory' and 'suggested',
- * each containing a valid list of links,
- * or {'directory': [], 'suggested': []} if read or parse fails.
- */
- _readDirectoryLinksFile: function DirectoryLinksProvider_readDirectoryLinksFile() {
- let emptyOutput = {directory: [], suggested: [], enhanced: []};
- return OS.File.read(this._directoryFilePath).then(binaryData => {
- let output;
- try {
- let json = gTextDecoder.decode(binaryData);
- let linksObj = JSON.parse(json);
- output = {directory: linksObj.directory || [],
- suggested: linksObj.suggested || [],
- enhanced: linksObj.enhanced || []};
- }
- catch (e) {
- Cu.reportError(e);
- }
- return output || emptyOutput;
- },
- error => {
- Cu.reportError(error);
- return emptyOutput;
- });
- },
-
- /**
- * Translates link.time_limits to UTC miliseconds and sets
- * link.startTime and link.endTime properties in link object
- */
- _setupStartEndTime: function DirectoryLinksProvider_setupStartEndTime(link) {
- // set start/end limits. Use ISO_8601 format: '2014-01-10T20:20:20.600Z'
- // (details here http://en.wikipedia.org/wiki/ISO_8601)
- // Note that if timezone is missing, FX will interpret as local time
- // meaning that the server can sepecify any time, but if the capmaign
- // needs to start at same time across multiple timezones, the server
- // omits timezone indicator
- if (!link.time_limits) {
- return;
- }
-
- let parsedTime;
- if (link.time_limits.start) {
- parsedTime = Date.parse(link.time_limits.start);
- if (parsedTime && !isNaN(parsedTime)) {
- link.startTime = parsedTime;
- }
- }
- if (link.time_limits.end) {
- parsedTime = Date.parse(link.time_limits.end);
- if (parsedTime && !isNaN(parsedTime)) {
- link.endTime = parsedTime;
- }
- }
- },
-
- /*
- * Handles campaign timeout
- */
- _onCampaignTimeout: function DirectoryLinksProvider_onCampaignTimeout() {
- // _campaignTimeoutID is invalid here, so just set it to null
- this._campaignTimeoutID = null;
- this._updateSuggestedTile();
- },
-
- /*
- * Clears capmpaign timeout
- */
- _clearCampaignTimeout: function DirectoryLinksProvider_clearCampaignTimeout() {
- if (this._campaignTimeoutID) {
- clearTimeout(this._campaignTimeoutID);
- this._campaignTimeoutID = null;
- }
- },
-
- /**
- * Setup capmpaign timeout to recompute suggested tiles upon
- * reaching soonest start or end time for the campaign
- * @param timeout in milliseconds
- */
- _setupCampaignTimeCheck: function DirectoryLinksProvider_setupCampaignTimeCheck(timeout) {
- // sanity check
- if (!timeout || timeout <= 0) {
- return;
- }
- this._clearCampaignTimeout();
- // setup next timeout
- this._campaignTimeoutID = setTimeout(this._onCampaignTimeout.bind(this), timeout);
- },
-
- /**
- * Test link for campaign time limits: checks if link falls within start/end time
- * and returns an object containing a use flag and the timeoutDate milliseconds
- * when the link has to be re-checked for campaign start-ready or end-reach
- * @param link
- * @return object {use: true or false, timeoutDate: milliseconds or null}
- */
- _testLinkForCampaignTimeLimits: function DirectoryLinksProvider_testLinkForCampaignTimeLimits(link) {
- let currentTime = Date.now();
- // test for start time first
- if (link.startTime && link.startTime > currentTime) {
- // not yet ready for start
- return {use: false, timeoutDate: link.startTime};
- }
- // otherwise check for end time
- if (link.endTime) {
- // passed end time
- if (link.endTime <= currentTime) {
- return {use: false};
- }
- // otherwise link is still ok, but we need to set timeoutDate
- return {use: true, timeoutDate: link.endTime};
- }
- // if we are here, the link is ok and no timeoutDate needed
- return {use: true};
- },
-
- /**
- * Handles block on suggested tile: updates fake block url with current timestamp
- */
- handleSuggestedTileBlock: function DirectoryLinksProvider_handleSuggestedTileBlock() {
- this._updateFrequencyCapSettings({url: FAKE_SUGGESTED_BLOCK_URL});
- this._writeFrequencyCapFile();
- this._updateSuggestedTile();
- },
-
- /**
- * Checks if suggested tile is being blocked for the rest of "decay time"
- * @return True if blocked, false otherwise
- */
- _isSuggestedTileBlocked: function DirectoryLinksProvider__isSuggestedTileBlocked() {
- let capObject = this._frequencyCaps[FAKE_SUGGESTED_BLOCK_URL];
- if (!capObject || !capObject.lastUpdated) {
- // user never blocked suggested tile or lastUpdated is missing
- return false;
- }
- // otherwise, make sure that enough time passed after suggested tile was blocked
- return (capObject.lastUpdated + AFTER_SUGGESTED_BLOCK_DECAY_TIME) > Date.now();
- },
-
- /**
- * Report some action on a newtab page (view, click)
- * @param sites Array of sites shown on newtab page
- * @param action String of the behavior to report
- * @param triggeringSiteIndex optional Int index of the site triggering action
- * @return download promise
- */
- reportSitesAction: function DirectoryLinksProvider_reportSitesAction(sites, action, triggeringSiteIndex) {
- // Check if the suggested tile was shown
- if (action == "view") {
- sites.slice(0, triggeringSiteIndex + 1).filter(s => s).forEach(site => {
- let {targetedSite, url} = site.link;
- if (targetedSite) {
- this._addFrequencyCapView(url);
- }
- });
- }
- // any click action on a suggested tile should stop that tile suggestion
- // click/block - user either removed a tile or went to a landing page
- // pin - tile turned into history tile, should no longer be suggested
- // unpin - the tile was pinned before, should not matter
- else {
- // suggested tile has targetedSite, or frecent_sites if it was pinned
- let {frecent_sites, targetedSite, url} = sites[triggeringSiteIndex].link;
- if (frecent_sites || targetedSite) {
- this._setFrequencyCapClick(url);
- }
- }
-
- let newtabEnhanced = false;
- let pingEndPoint = "";
- try {
- newtabEnhanced = Services.prefs.getBoolPref(PREF_NEWTAB_ENHANCED);
- pingEndPoint = Services.prefs.getCharPref(PREF_DIRECTORY_PING);
- }
- catch (ex) {}
-
- // Bug 1240245 - We no longer send pings, but frequency capping and fetching
- // tests depend on the following actions, so references to PING remain.
- let invalidAction = PING_ACTIONS.indexOf(action) == -1;
- if (!newtabEnhanced || pingEndPoint == "" || invalidAction) {
- return Promise.resolve();
- }
-
- return Task.spawn(function* () {
- // since we updated views/clicks we need write _frequencyCaps to disk
- yield this._writeFrequencyCapFile();
- // Use this as an opportunity to potentially fetch new links
- yield this._fetchAndCacheLinksIfNecessary();
- }.bind(this));
- },
-
- /**
- * Get the enhanced link object for a link (whether history or directory)
- */
- getEnhancedLink: function DirectoryLinksProvider_getEnhancedLink(link) {
- // Use the provided link if it's already enhanced
- return link.enhancedImageURI && link ? link :
- this._enhancedLinks.get(NewTabUtils.extractSite(link.url));
- },
-
- /**
- * Check if a url's scheme is in a Set of allowed schemes and if the base
- * domain is allowed.
- * @param url to check
- * @param allowed Set of allowed schemes
- * @param checkBase boolean to check the base domain
- */
- isURLAllowed(url, allowed, checkBase) {
- // Assume no url is an allowed url
- if (!url) {
- return true;
- }
-
- let scheme = "", base = "";
- try {
- // A malformed url will not be allowed
- let uri = Services.io.newURI(url, null, null);
- scheme = uri.scheme;
-
- // URIs without base domains will be allowed
- base = Services.eTLD.getBaseDomain(uri);
- }
- catch (ex) {}
- // Require a scheme match and the base only if desired
- return allowed.has(scheme) && (!checkBase || ALLOWED_URL_BASE.has(base));
- },
-
- _escapeChars(text) {
- let charMap = {
- '&': '&amp;',
- '<': '&lt;',
- '>': '&gt;',
- '"': '&quot;',
- "'": '&#039;'
- };
-
- return text.replace(/[&<>"']/g, (character) => charMap[character]);
- },
-
- /**
- * Gets the current set of directory links.
- * @param aCallback The function that the array of links is passed to.
- */
- getLinks: function DirectoryLinksProvider_getLinks(aCallback) {
- this._readDirectoryLinksFile().then(rawLinks => {
- // Reset the cache of suggested tiles and enhanced images for this new set of links
- this._enhancedLinks.clear();
- this._suggestedLinks.clear();
- this._clearCampaignTimeout();
- this._avoidInadjacentSites = false;
-
- // Only check base domain for images when using the default pref
- let checkBase = !this.__linksURLModified;
- let validityFilter = function(link) {
- // Make sure the link url is allowed and images too if they exist
- return this.isURLAllowed(link.url, ALLOWED_LINK_SCHEMES, false) &&
- (!link.imageURI ||
- this.isURLAllowed(link.imageURI, ALLOWED_IMAGE_SCHEMES, checkBase)) &&
- (!link.enhancedImageURI ||
- this.isURLAllowed(link.enhancedImageURI, ALLOWED_IMAGE_SCHEMES, checkBase));
- }.bind(this);
-
- rawLinks.suggested.filter(validityFilter).forEach((link, position) => {
- // Suggested sites must have an adgroup name.
- if (!link.adgroup_name) {
- return;
- }
-
- let sanitizeFlags = ParserUtils.SanitizerCidEmbedsOnly |
- ParserUtils.SanitizerDropForms |
- ParserUtils.SanitizerDropNonCSSPresentation;
-
- link.explanation = this._escapeChars(link.explanation ? ParserUtils.convertToPlainText(link.explanation, sanitizeFlags, 0) : "");
- link.targetedName = this._escapeChars(ParserUtils.convertToPlainText(link.adgroup_name, sanitizeFlags, 0));
- link.lastVisitDate = rawLinks.suggested.length - position;
- // check if link wants to avoid inadjacent sites
- if (link.check_inadjacency) {
- this._avoidInadjacentSites = true;
- }
-
- // We cache suggested tiles here but do not push any of them in the links list yet.
- // The decision for which suggested tile to include will be made separately.
- this._cacheSuggestedLinks(link);
- this._updateFrequencyCapSettings(link);
- });
-
- rawLinks.enhanced.filter(validityFilter).forEach((link, position) => {
- link.lastVisitDate = rawLinks.enhanced.length - position;
-
- // Stash the enhanced image for the site
- if (link.enhancedImageURI) {
- this._enhancedLinks.set(NewTabUtils.extractSite(link.url), link);
- }
- });
-
- let links = rawLinks.directory.filter(validityFilter).map((link, position) => {
- link.lastVisitDate = rawLinks.directory.length - position;
- link.frecency = DIRECTORY_FRECENCY;
- return link;
- });
-
- // Allow for one link suggestion on top of the default directory links
- this.maxNumLinks = links.length + 1;
-
- // prune frequency caps of outdated urls
- this._pruneFrequencyCapUrls();
- // write frequency caps object to disk asynchronously
- this._writeFrequencyCapFile();
-
- return links;
- }).catch(ex => {
- Cu.reportError(ex);
- return [];
- }).then(links => {
- aCallback(links);
- this._populatePlacesLinks();
- });
- },
-
- init: function DirectoryLinksProvider_init() {
- this._setDefaultEnhanced();
- this._addPrefsObserver();
- // setup directory file path and last download timestamp
- this._directoryFilePath = OS.Path.join(OS.Constants.Path.localProfileDir, DIRECTORY_LINKS_FILE);
- this._lastDownloadMS = 0;
-
- // setup frequency cap file path
- this._frequencyCapFilePath = OS.Path.join(OS.Constants.Path.localProfileDir, FREQUENCY_CAP_FILE);
- // setup inadjacent sites URL
- this._inadjacentSitesUrl = INADJACENCY_SOURCE;
-
- NewTabUtils.placesProvider.addObserver(this);
- NewTabUtils.links.addObserver(this);
-
- return Task.spawn(function*() {
- // get the last modified time of the links file if it exists
- let doesFileExists = yield OS.File.exists(this._directoryFilePath);
- if (doesFileExists) {
- let fileInfo = yield OS.File.stat(this._directoryFilePath);
- this._lastDownloadMS = Date.parse(fileInfo.lastModificationDate);
- }
- // read frequency cap file
- yield this._readFrequencyCapFile();
- // fetch directory on startup without force
- yield this._fetchAndCacheLinksIfNecessary();
- // fecth inadjacent sites on startup
- yield this._loadInadjacentSites();
- }.bind(this));
- },
-
- _handleManyLinksChanged: function() {
- this._topSitesWithSuggestedLinks.clear();
- this._suggestedLinks.forEach((suggestedLinks, site) => {
- if (NewTabUtils.isTopPlacesSite(site)) {
- this._topSitesWithSuggestedLinks.add(site);
- }
- });
- this._updateSuggestedTile();
- },
-
- /**
- * Updates _topSitesWithSuggestedLinks based on the link that was changed.
- *
- * @return true if _topSitesWithSuggestedLinks was modified, false otherwise.
- */
- _handleLinkChanged: function(aLink) {
- let changedLinkSite = NewTabUtils.extractSite(aLink.url);
- let linkStored = this._topSitesWithSuggestedLinks.has(changedLinkSite);
-
- if (!NewTabUtils.isTopPlacesSite(changedLinkSite) && linkStored) {
- this._topSitesWithSuggestedLinks.delete(changedLinkSite);
- return true;
- }
-
- if (this._suggestedLinks.has(changedLinkSite) &&
- NewTabUtils.isTopPlacesSite(changedLinkSite) && !linkStored) {
- this._topSitesWithSuggestedLinks.add(changedLinkSite);
- return true;
- }
-
- // always run _updateSuggestedTile if aLink is inadjacent
- // and there are tiles configured to avoid it
- if (this._avoidInadjacentSites && this._isInadjacentLink(aLink)) {
- return true;
- }
-
- return false;
- },
-
- _populatePlacesLinks: function () {
- NewTabUtils.links.populateProviderCache(NewTabUtils.placesProvider, () => {
- this._handleManyLinksChanged();
- });
- },
-
- onDeleteURI: function(aProvider, aLink) {
- let {url} = aLink;
- // remove clicked flag for that url and
- // call observer upon disk write completion
- this._removeTileClick(url).then(() => {
- this._callObservers("onDeleteURI", url);
- });
- },
-
- onClearHistory: function() {
- // remove all clicked flags and call observers upon file write
- this._removeAllTileClicks().then(() => {
- this._callObservers("onClearHistory");
- });
- },
-
- onLinkChanged: function (aProvider, aLink) {
- // Make sure NewTabUtils.links handles the notification first.
- setTimeout(() => {
- if (this._handleLinkChanged(aLink) || this._shouldUpdateSuggestedTile()) {
- this._updateSuggestedTile();
- }
- }, 0);
- },
-
- onManyLinksChanged: function () {
- // Make sure NewTabUtils.links handles the notification first.
- setTimeout(() => {
- this._handleManyLinksChanged();
- }, 0);
- },
-
- _getCurrentTopSiteCount: function() {
- let visibleTopSiteCount = 0;
- let newTabLinks = NewTabUtils.links.getLinks();
- for (let link of newTabLinks.slice(0, MIN_VISIBLE_HISTORY_TILES)) {
- // compute visibleTopSiteCount for suggested tiles
- if (link && (link.type == "history" || link.type == "enhanced")) {
- visibleTopSiteCount++;
- }
- }
- // since newTabLinks are available, set _newTabHasInadjacentSite here
- // note that _shouldUpdateSuggestedTile is called by _updateSuggestedTile
- this._newTabHasInadjacentSite = this._avoidInadjacentSites && this._checkForInadjacentSites(newTabLinks);
-
- return visibleTopSiteCount;
- },
-
- _shouldUpdateSuggestedTile: function() {
- let sortedLinks = NewTabUtils.getProviderLinks(this);
-
- let mostFrecentLink = {};
- if (sortedLinks && sortedLinks.length) {
- mostFrecentLink = sortedLinks[0]
- }
-
- let currTopSiteCount = this._getCurrentTopSiteCount();
- if ((!mostFrecentLink.targetedSite && currTopSiteCount >= MIN_VISIBLE_HISTORY_TILES) ||
- (mostFrecentLink.targetedSite && currTopSiteCount < MIN_VISIBLE_HISTORY_TILES)) {
- // If mostFrecentLink has a targetedSite then mostFrecentLink is a suggested link.
- // If we have enough history links (8+) to show a suggested tile and we are not
- // already showing one, then we should update (to *attempt* to add a suggested tile).
- // OR if we don't have enough history to show a suggested tile (<8) and we are
- // currently showing one, we should update (to remove it).
- return true;
- }
-
- return false;
- },
-
- /**
- * Chooses and returns a suggested tile based on a user's top sites
- * that we have an available suggested tile for.
- *
- * @return the chosen suggested tile, or undefined if there isn't one
- */
- _updateSuggestedTile: function() {
- let sortedLinks = NewTabUtils.getProviderLinks(this);
-
- if (!sortedLinks) {
- // If NewTabUtils.links.resetCache() is called before getting here,
- // sortedLinks may be undefined.
- return undefined;
- }
-
- // Delete the current suggested tile, if one exists.
- let initialLength = sortedLinks.length;
- if (initialLength) {
- let mostFrecentLink = sortedLinks[0];
- if (mostFrecentLink.targetedSite) {
- this._callObservers("onLinkChanged", {
- url: mostFrecentLink.url,
- frecency: SUGGESTED_FRECENCY,
- lastVisitDate: mostFrecentLink.lastVisitDate,
- type: mostFrecentLink.type,
- }, 0, true);
- }
- }
-
- if (this._topSitesWithSuggestedLinks.size == 0 ||
- !this._shouldUpdateSuggestedTile() ||
- this._isSuggestedTileBlocked()) {
- // There are no potential suggested links we can show or not
- // enough history for a suggested tile, or suggested tile was
- // recently blocked and wait time interval has not decayed yet
- return undefined;
- }
-
- // Create a flat list of all possible links we can show as suggested.
- // Note that many top sites may map to the same suggested links, but we only
- // want to count each suggested link once (based on url), thus possibleLinks is a map
- // from url to suggestedLink. Thus, each link has an equal chance of being chosen at
- // random from flattenedLinks if it appears only once.
- let nextTimeout;
- let possibleLinks = new Map();
- let targetedSites = new Map();
- this._topSitesWithSuggestedLinks.forEach(topSiteWithSuggestedLink => {
- let suggestedLinksMap = this._suggestedLinks.get(topSiteWithSuggestedLink);
- suggestedLinksMap.forEach((suggestedLink, url) => {
- // Skip this link if we've shown it too many times already
- if (!this._testFrequencyCapLimits(url)) {
- return;
- }
-
- // as we iterate suggestedLinks, check for campaign start/end
- // time limits, and set nextTimeout to the closest timestamp
- let {use, timeoutDate} = this._testLinkForCampaignTimeLimits(suggestedLink);
- // update nextTimeout is necessary
- if (timeoutDate && (!nextTimeout || nextTimeout > timeoutDate)) {
- nextTimeout = timeoutDate;
- }
- // Skip link if it falls outside campaign time limits
- if (!use) {
- return;
- }
-
- // Skip link if it avoids inadjacent sites and newtab has one
- if (suggestedLink.check_inadjacency && this._newTabHasInadjacentSite) {
- return;
- }
-
- possibleLinks.set(url, suggestedLink);
-
- // Keep a map of URL to targeted sites. We later use this to show the user
- // what site they visited to trigger this suggestion.
- if (!targetedSites.get(url)) {
- targetedSites.set(url, []);
- }
- targetedSites.get(url).push(topSiteWithSuggestedLink);
- })
- });
-
- // setup timeout check for starting or ending campaigns
- if (nextTimeout) {
- this._setupCampaignTimeCheck(nextTimeout - Date.now());
- }
-
- // We might have run out of possible links to show
- let numLinks = possibleLinks.size;
- if (numLinks == 0) {
- return undefined;
- }
-
- let flattenedLinks = [...possibleLinks.values()];
-
- // Choose our suggested link at random
- let suggestedIndex = Math.floor(Math.random() * numLinks);
- let chosenSuggestedLink = flattenedLinks[suggestedIndex];
-
- // Add the suggested link to the front with some extra values
- this._callObservers("onLinkChanged", Object.assign({
- frecency: SUGGESTED_FRECENCY,
-
- // Choose the first site a user has visited as the target. In the future,
- // this should be the site with the highest frecency. However, we currently
- // store frecency by URL not by site.
- targetedSite: targetedSites.get(chosenSuggestedLink.url).length ?
- targetedSites.get(chosenSuggestedLink.url)[0] : null
- }, chosenSuggestedLink));
- return chosenSuggestedLink;
- },
-
- /**
- * Loads inadjacent sites
- * @return a promise resolved when lookup Set for sites is built
- */
- _loadInadjacentSites: function DirectoryLinksProvider_loadInadjacentSites() {
- return this._downloadJsonData(this._inadjacentSitesUrl).then(jsonString => {
- let jsonObject = {};
- try {
- jsonObject = JSON.parse(jsonString);
- }
- catch (e) {
- Cu.reportError(e);
- }
-
- this._inadjacentSites = new Set(jsonObject.domains);
- });
- },
-
- /**
- * Genegrates hash suitable for looking up inadjacent site
- * @param value to hsh
- * @return hased value, base64-ed
- */
- _generateHash: function DirectoryLinksProvider_generateHash(value) {
- let byteArr = gUnicodeConverter.convertToByteArray(value);
- gCryptoHash.init(gCryptoHash.MD5);
- gCryptoHash.update(byteArr, byteArr.length);
- return gCryptoHash.finish(true);
- },
-
- /**
- * Checks if link belongs to inadjacent domain
- * @param link to check
- * @return true for inadjacent domains, false otherwise
- */
- _isInadjacentLink: function DirectoryLinksProvider_isInadjacentLink(link) {
- let baseDomain = link.baseDomain || NewTabUtils.extractSite(link.url || "");
- if (!baseDomain) {
- return false;
- }
- // check if hashed domain is inadjacent
- return this._inadjacentSites.has(this._generateHash(baseDomain));
- },
-
- /**
- * Checks if new tab has inadjacent site
- * @param new tab links (or nothing, in which case NewTabUtils.links.getLinks() is called
- * @return true if new tab shows has inadjacent site
- */
- _checkForInadjacentSites: function DirectoryLinksProvider_checkForInadjacentSites(newTabLink) {
- let links = newTabLink || NewTabUtils.links.getLinks();
- for (let link of links.slice(0, MAX_VISIBLE_HISTORY_TILES)) {
- // check links against inadjacent list - specifically include ALL link types
- if (this._isInadjacentLink(link)) {
- return true;
- }
- }
- return false;
- },
-
- /**
- * Reads json file, parses its content, and returns resulting object
- * @param json file path
- * @param json object to return in case file read or parse fails
- * @return a promise resolved to a valid object or undefined upon error
- */
- _readJsonFile: Task.async(function* (filePath, nullObject) {
- let jsonObj;
- try {
- let binaryData = yield OS.File.read(filePath);
- let json = gTextDecoder.decode(binaryData);
- jsonObj = JSON.parse(json);
- }
- catch (e) {}
- return jsonObj || nullObject;
- }),
-
- /**
- * Loads frequency cap object from file and parses its content
- * @return a promise resolved upon load completion
- * on error or non-exstent file _frequencyCaps is set to empty object
- */
- _readFrequencyCapFile: Task.async(function* () {
- // set _frequencyCaps object to file's content or empty object
- this._frequencyCaps = yield this._readJsonFile(this._frequencyCapFilePath, {});
- }),
-
- /**
- * Saves frequency cap object to file
- * @return a promise resolved upon file i/o completion
- */
- _writeFrequencyCapFile: function DirectoryLinksProvider_writeFrequencyCapFile() {
- let json = JSON.stringify(this._frequencyCaps || {});
- return OS.File.writeAtomic(this._frequencyCapFilePath, json, {tmpPath: this._frequencyCapFilePath + ".tmp"});
- },
-
- /**
- * Clears frequency cap object and writes empty json to file
- * @return a promise resolved upon file i/o completion
- */
- _clearFrequencyCap: function DirectoryLinksProvider_clearFrequencyCap() {
- this._frequencyCaps = {};
- return this._writeFrequencyCapFile();
- },
-
- /**
- * updates frequency cap configuration for a link
- */
- _updateFrequencyCapSettings: function DirectoryLinksProvider_updateFrequencyCapSettings(link) {
- let capsObject = this._frequencyCaps[link.url];
- if (!capsObject) {
- // create an object with empty counts
- capsObject = {
- dailyViews: 0,
- totalViews: 0,
- lastShownDate: 0,
- };
- this._frequencyCaps[link.url] = capsObject;
- }
- // set last updated timestamp
- capsObject.lastUpdated = Date.now();
- // check for link configuration
- if (link.frequency_caps) {
- capsObject.dailyCap = link.frequency_caps.daily || DEFAULT_DAILY_FREQUENCY_CAP;
- capsObject.totalCap = link.frequency_caps.total || DEFAULT_TOTAL_FREQUENCY_CAP;
- }
- else {
- // fallback to defaults
- capsObject.dailyCap = DEFAULT_DAILY_FREQUENCY_CAP;
- capsObject.totalCap = DEFAULT_TOTAL_FREQUENCY_CAP;
- }
- },
-
- /**
- * Prunes frequency cap objects for outdated links
- * @param timeDetla milliseconds
- * all cap objects with lastUpdated less than (now() - timeDelta)
- * will be removed. This is done to remove frequency cap objects
- * for unused tile urls
- */
- _pruneFrequencyCapUrls: function DirectoryLinksProvider_pruneFrequencyCapUrls(timeDelta = DEFAULT_PRUNE_TIME_DELTA) {
- let timeThreshold = Date.now() - timeDelta;
- Object.keys(this._frequencyCaps).forEach(url => {
- // remove url if it is not ignorable and wasn't updated for a while
- if (!url.startsWith("ignore") && this._frequencyCaps[url].lastUpdated <= timeThreshold) {
- delete this._frequencyCaps[url];
- }
- });
- },
-
- /**
- * Checks if supplied timestamp happened today
- * @param timestamp in milliseconds
- * @return true if the timestamp was made today, false otherwise
- */
- _wasToday: function DirectoryLinksProvider_wasToday(timestamp) {
- let showOn = new Date(timestamp);
- let today = new Date();
- // call timestamps identical if both day and month are same
- return showOn.getDate() == today.getDate() &&
- showOn.getMonth() == today.getMonth() &&
- showOn.getYear() == today.getYear();
- },
-
- /**
- * adds some number of views for a url
- * @param url String url of the suggested link
- */
- _addFrequencyCapView: function DirectoryLinksProvider_addFrequencyCapView(url) {
- let capObject = this._frequencyCaps[url];
- // sanity check
- if (!capObject) {
- return;
- }
-
- // if the day is new: reset the daily counter and lastShownDate
- if (!this._wasToday(capObject.lastShownDate)) {
- capObject.dailyViews = 0;
- // update lastShownDate
- capObject.lastShownDate = Date.now();
- }
-
- // bump both daily and total counters
- capObject.totalViews++;
- capObject.dailyViews++;
-
- // if any of the caps is reached - update suggested tiles
- if (capObject.totalViews >= capObject.totalCap ||
- capObject.dailyViews >= capObject.dailyCap) {
- this._updateSuggestedTile();
- }
- },
-
- /**
- * Sets clicked flag for link url
- * @param url String url of the suggested link
- */
- _setFrequencyCapClick(url) {
- let capObject = this._frequencyCaps[url];
- // sanity check
- if (!capObject) {
- return;
- }
- capObject.clicked = true;
- // and update suggested tiles, since current tile became invalid
- this._updateSuggestedTile();
- },
-
- /**
- * Tests frequency cap limits for link url
- * @param url String url of the suggested link
- * @return true if link is viewable, false otherwise
- */
- _testFrequencyCapLimits: function DirectoryLinksProvider_testFrequencyCapLimits(url) {
- let capObject = this._frequencyCaps[url];
- // sanity check: if url is missing - do not show this tile
- if (!capObject) {
- return false;
- }
-
- // check for clicked set or total views reached
- if (capObject.clicked || capObject.totalViews >= capObject.totalCap) {
- return false;
- }
-
- // otherwise check if link is over daily views limit
- if (this._wasToday(capObject.lastShownDate) &&
- capObject.dailyViews >= capObject.dailyCap) {
- return false;
- }
-
- // we passed all cap tests: return true
- return true;
- },
-
- /**
- * Removes clicked flag from frequency cap entry for tile landing url
- * @param url String url of the suggested link
- * @return promise resolved upon disk write completion
- */
- _removeTileClick: function DirectoryLinksProvider_removeTileClick(url = "") {
- // remove trailing slash, to accomodate Places sending site urls ending with '/'
- let noTrailingSlashUrl = url.replace(/\/$/, "");
- let capObject = this._frequencyCaps[url] || this._frequencyCaps[noTrailingSlashUrl];
- // return resolved promise if capObject is not found
- if (!capObject) {
- return Promise.resolve();
- }
- // otherwise remove clicked flag
- delete capObject.clicked;
- return this._writeFrequencyCapFile();
- },
-
- /**
- * Removes all clicked flags from frequency cap object
- * @return promise resolved upon disk write completion
- */
- _removeAllTileClicks: function DirectoryLinksProvider_removeAllTileClicks() {
- Object.keys(this._frequencyCaps).forEach(url => {
- delete this._frequencyCaps[url].clicked;
- });
- return this._writeFrequencyCapFile();
- },
-
- /**
- * Return the object to its pre-init state
- */
- reset: function DirectoryLinksProvider_reset() {
- delete this.__linksURL;
- this._removePrefsObserver();
- this._removeObservers();
- },
-
- addObserver: function DirectoryLinksProvider_addObserver(aObserver) {
- this._observers.add(aObserver);
- },
-
- removeObserver: function DirectoryLinksProvider_removeObserver(aObserver) {
- this._observers.delete(aObserver);
- },
-
- _callObservers(methodName, ...args) {
- for (let obs of this._observers) {
- if (typeof(obs[methodName]) == "function") {
- try {
- obs[methodName](this, ...args);
- } catch (err) {
- Cu.reportError(err);
- }
- }
- }
- },
-
- _removeObservers: function() {
- this._observers.clear();
- }
-};
diff --git a/application/basilisk/modules/PermissionUI.jsm b/application/basilisk/modules/PermissionUI.jsm
index 5fa0f9f06..5c8b94421 100644
--- a/application/basilisk/modules/PermissionUI.jsm
+++ b/application/basilisk/modules/PermissionUI.jsm
@@ -437,26 +437,12 @@ GeolocationPermissionPrompt.prototype = {
},
get promptActions() {
- // We collect Telemetry data on Geolocation prompts and how users
- // respond to them. The probe keys are a bit verbose, so let's alias them.
- const SHARE_LOCATION =
- Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST_SHARE_LOCATION;
- const ALWAYS_SHARE =
- Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST_ALWAYS_SHARE;
- const NEVER_SHARE =
- Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST_NEVER_SHARE;
-
- let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
-
let actions = [{
label: gBrowserBundle.GetStringFromName("geolocation.shareLocation"),
accessKey:
gBrowserBundle.GetStringFromName("geolocation.shareLocation.accesskey"),
action: null,
expireType: null,
- callback: function() {
- secHistogram.add(SHARE_LOCATION);
- },
}];
if (!this.principal.URI.schemeIs("file")) {
@@ -467,9 +453,6 @@ GeolocationPermissionPrompt.prototype = {
gBrowserBundle.GetStringFromName("geolocation.alwaysShareLocation.accesskey"),
action: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: null,
- callback: function() {
- secHistogram.add(ALWAYS_SHARE);
- },
});
// Never share location action.
@@ -479,9 +462,6 @@ GeolocationPermissionPrompt.prototype = {
gBrowserBundle.GetStringFromName("geolocation.neverShareLocation.accesskey"),
action: Ci.nsIPermissionManager.DENY_ACTION,
expireType: null,
- callback: function() {
- secHistogram.add(NEVER_SHARE);
- },
});
}
@@ -489,9 +469,6 @@ GeolocationPermissionPrompt.prototype = {
},
onBeforeShow() {
- let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
- const SHOW_REQUEST = Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST;
- secHistogram.add(SHOW_REQUEST);
},
};
diff --git a/application/basilisk/modules/ProcessHangMonitor.jsm b/application/basilisk/modules/ProcessHangMonitor.jsm
index e048f5b40..b1f6f2a97 100644
--- a/application/basilisk/modules/ProcessHangMonitor.jsm
+++ b/application/basilisk/modules/ProcessHangMonitor.jsm
@@ -316,7 +316,7 @@ var ProcessHangMonitor = {
nb.appendNotification(bundle.getString("processHang.label"),
"process-hang",
- "chrome://browser/content/aboutRobots-icon.png",
+ "chrome://browser/skin/slowStartup-16.png",
nb.PRIORITY_WARNING_HIGH, buttons);
},
diff --git a/application/basilisk/modules/moz.build b/application/basilisk/modules/moz.build
index d043d4799..cd8f2ce62 100644
--- a/application/basilisk/modules/moz.build
+++ b/application/basilisk/modules/moz.build
@@ -16,7 +16,6 @@ EXTRA_JS_MODULES += [
'ContentObservers.jsm',
'ContentSearch.jsm',
'ContentWebRTC.jsm',
- 'DirectoryLinksProvider.jsm',
'E10SUtils.jsm',
'Feeds.jsm',
'FormSubmitObserver.jsm',
diff --git a/application/basilisk/themes/linux/jar.mn b/application/basilisk/themes/linux/jar.mn
index 189027812..e9f666418 100644
--- a/application/basilisk/themes/linux/jar.mn
+++ b/application/basilisk/themes/linux/jar.mn
@@ -8,8 +8,9 @@ browser.jar:
#include ../shared/jar.inc.mn
skin/classic/browser/sanitizeDialog.css
skin/classic/browser/aboutSessionRestore-window-icon.png
+#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/aboutSyncTabs.css
-* skin/classic/browser/syncedtabs/sidebar.css (syncedtabs/sidebar.css)
+#endif
skin/classic/browser/actionicon-tab.png
* skin/classic/browser/browser.css
* skin/classic/browser/devedition.css
@@ -107,6 +108,7 @@ browser.jar:
skin/classic/browser/tabbrowser/tab-stroke-start@2x.png (tabbrowser/tab-stroke-start@2x.png)
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
+#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-16.png
skin/classic/browser/sync-32.png
skin/classic/browser/sync-bg.png
@@ -125,6 +127,8 @@ browser.jar:
skin/classic/browser/syncQuota.css
skin/classic/browser/syncProgress-horizontalbar.png
skin/classic/browser/syncProgress-horizontalbar@2x.png
+ skin/classic/browser/syncProgress.css
+#endif
[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
% override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png
diff --git a/application/basilisk/themes/linux/syncProgress.css b/application/basilisk/themes/linux/syncProgress.css
new file mode 100644
index 000000000..d7aa59976
--- /dev/null
+++ b/application/basilisk/themes/linux/syncProgress.css
@@ -0,0 +1,46 @@
+/* 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 url(chrome://global/skin/inContentUI.css);
+
+:root {
+ height: 100%;
+ width: 100%;
+ padding: 0;
+}
+
+body {
+ margin: 0;
+ padding: 0 2em;
+}
+
+#floatingBox {
+ margin: 4em auto;
+ max-width: 40em;
+ min-width: 23em;
+ padding: 1em 1.5em;
+ position: relative;
+ text-align: center;
+}
+
+#successLogo {
+ margin: 1em 2em;
+}
+
+#loadingText {
+ margin: 2em 6em;
+}
+
+#progressBar {
+ margin: 2em 10em;
+}
+
+#uploadProgressBar{
+ width: 100%;
+}
+
+#bottomRow {
+ margin-top: 2em;
+ padding: 0;
+ text-align: end;
+}
diff --git a/application/basilisk/themes/linux/syncedtabs/sidebar.css b/application/basilisk/themes/linux/syncedtabs/sidebar.css
deleted file mode 100644
index 04e00a7d4..000000000
--- a/application/basilisk/themes/linux/syncedtabs/sidebar.css
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 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/. */
-
-%include ../../shared/syncedtabs/sidebar.inc.css
-
-/* These styles are intended to mimic XUL trees and the XUL search box. */
-
-html {
- border: 1px solid ThreeDShadow;
- background-color: -moz-Field;
- color: -moz-FieldText;
- box-sizing: border-box;
-}
-
-.item {
- padding-inline-end: 0;
-}
-
-.item-title {
- margin: 1px 0 0;
- margin-inline-end: 6px;
-}
-
-
-.search-box {
- -moz-appearance: textfield;
- cursor: text;
- margin: 2px 4px;
- border: 2px solid;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
- -moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
- -moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
- padding: 2px 2px 3px;
- padding-inline-start: 4px;
- background-color: -moz-Field;
- color: -moz-FieldText;
-}
-
-.textbox-search-clear {
- background-image: url(moz-icon://stock/gtk-clear?size=menu);
- background-repeat: no-repeat;
- width: 16px;
- height: 16px;
-}
-
-.textbox-search-icon {
- background-image: url(moz-icon://stock/gtk-find?size=menu);
- background-repeat: no-repeat;
- width: 16px;
- height: 16px;
- display: block;
-}
-
-.textbox-search-icon[searchbutton]:not([disabled]) ,
-.textbox-search-clear:not([disabled]) {
- cursor: pointer;
-}
-
-.item.client .item-twisty-container {
- -moz-appearance: treetwistyopen;
- margin-top: 3px;
- margin-left: 2px;
-}
-
-.item.client.closed .item-twisty-container {
- -moz-appearance: treetwisty;
-}
diff --git a/application/basilisk/themes/osx/jar.mn b/application/basilisk/themes/osx/jar.mn
index 27802843d..92d2ceedf 100644
--- a/application/basilisk/themes/osx/jar.mn
+++ b/application/basilisk/themes/osx/jar.mn
@@ -7,8 +7,9 @@ browser.jar:
#include ../shared/jar.inc.mn
skin/classic/browser/sanitizeDialog.css
skin/classic/browser/aboutSessionRestore-window-icon.png
+#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/aboutSyncTabs.css
-* skin/classic/browser/syncedtabs/sidebar.css (syncedtabs/sidebar.css)
+#endif
skin/classic/browser/actionicon-tab.png
skin/classic/browser/actionicon-tab@2x.png
* skin/classic/browser/browser.css
@@ -159,6 +160,7 @@ browser.jar:
skin/classic/browser/tabbrowser/tab-stroke-start@2x.png (tabbrowser/tab-stroke-start@2x.png)
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
skin/classic/browser/tabbrowser/tabDragIndicator@2x.png (tabbrowser/tabDragIndicator@2x.png)
+#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-16.png
skin/classic/browser/sync-32.png
skin/classic/browser/sync-bg.png
@@ -179,6 +181,8 @@ browser.jar:
skin/classic/browser/syncProgress-toolbar@2x.png
skin/classic/browser/syncProgress-toolbar-inverted.png
skin/classic/browser/syncProgress-toolbar-inverted@2x.png
+ skin/classic/browser/syncProgress.css
+#endif
skin/classic/browser/Toolbar-background-noise.png (Toolbar-background-noise.png)
skin/classic/browser/lion/toolbarbutton-dropmarker.png (toolbarbutton-dropmarker-lion.png)
skin/classic/browser/toolbarbutton-dropmarker@2x.png (toolbarbutton-dropmarker-lion@2x.png)
@@ -195,8 +199,10 @@ browser.jar:
skin/classic/browser/yosemite/menuPanel-help@2x.png (menuPanel-help-yosemite@2x.png)
skin/classic/browser/yosemite/reload-stop-go.png (reload-stop-go-yosemite.png)
skin/classic/browser/yosemite/reload-stop-go@2x.png (reload-stop-go-yosemite@2x.png)
+#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/yosemite/sync-horizontalbar.png (sync-horizontalbar-yosemite.png)
skin/classic/browser/yosemite/sync-horizontalbar@2x.png (sync-horizontalbar-yosemite@2x.png)
+#endif
skin/classic/browser/yosemite/tab-selected-end-inactive.svg (tabbrowser/tab-selected-end-yosemite-inactive.svg)
skin/classic/browser/yosemite/tab-selected-start-inactive.svg (tabbrowser/tab-selected-start-yosemite-inactive.svg)
skin/classic/browser/yosemite/tab-active-middle-inactive.png (tabbrowser/tab-active-middle-yosemite-inactive.png)
@@ -224,5 +230,7 @@ browser.jar:
% override chrome://browser/skin/menuPanel-help@2x.png chrome://browser/skin/yosemite/menuPanel-help@2x.png os=Darwin osversion>=10.10
% override chrome://browser/skin/reload-stop-go.png chrome://browser/skin/yosemite/reload-stop-go.png os=Darwin osversion>=10.10
% override chrome://browser/skin/reload-stop-go@2x.png chrome://browser/skin/yosemite/reload-stop-go@2x.png os=Darwin osversion>=10.10
+#ifdef MOZ_SERVICES_SYNC
% override chrome://browser/skin/sync-horizontalbar.png chrome://browser/skin/yosemite/sync-horizontalbar.png os=Darwin osversion>=10.10
% override chrome://browser/skin/sync-horizontalbar@2x.png chrome://browser/skin/yosemite/sync-horizontalbar@2x.png os=Darwin osversion>=10.10
+#endif
diff --git a/application/basilisk/themes/osx/syncProgress.css b/application/basilisk/themes/osx/syncProgress.css
new file mode 100644
index 000000000..d7aa59976
--- /dev/null
+++ b/application/basilisk/themes/osx/syncProgress.css
@@ -0,0 +1,46 @@
+/* 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 url(chrome://global/skin/inContentUI.css);
+
+:root {
+ height: 100%;
+ width: 100%;
+ padding: 0;
+}
+
+body {
+ margin: 0;
+ padding: 0 2em;
+}
+
+#floatingBox {
+ margin: 4em auto;
+ max-width: 40em;
+ min-width: 23em;
+ padding: 1em 1.5em;
+ position: relative;
+ text-align: center;
+}
+
+#successLogo {
+ margin: 1em 2em;
+}
+
+#loadingText {
+ margin: 2em 6em;
+}
+
+#progressBar {
+ margin: 2em 10em;
+}
+
+#uploadProgressBar{
+ width: 100%;
+}
+
+#bottomRow {
+ margin-top: 2em;
+ padding: 0;
+ text-align: end;
+}
diff --git a/application/basilisk/themes/osx/syncedtabs/sidebar.css b/application/basilisk/themes/osx/syncedtabs/sidebar.css
deleted file mode 100644
index 4d1de766c..000000000
--- a/application/basilisk/themes/osx/syncedtabs/sidebar.css
+++ /dev/null
@@ -1,154 +0,0 @@
-/* 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/. */
-
-%include ../../shared/syncedtabs/sidebar.inc.css
-
-/* These styles are intended to mimic XUL trees and the XUL search box. */
-
-.content-container {
- -moz-appearance: -moz-mac-source-list;
-}
-
-.item {
- color: -moz-DialogText;
-}
-
-.item-title-container {
- box-sizing: border-box;
- align-items: center;
- height: 24px;
- font-size: 12px;
-}
-
-.item.selected > .item-title-container {
- color: HighlightText;
- font-weight: bold;
-}
-
-.item.selected > .item-title-container {
- -moz-appearance: -moz-mac-source-list-selection;
-}
-
-.item.selected:focus > .item-title-container {
- -moz-appearance: -moz-mac-active-source-list-selection;
-}
-
-.item.client .item-twisty-container {
- min-width: 16px;
- height: 16px;
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-expanded");
-}
-
-@media not all and (-moz-mac-yosemite-theme) {
- .item.client.selected .item-twisty-container {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-expanded-inverted");
- }
-
- .item.client.selected.closed .item-twisty-container {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-collapsed-inverted");
- }
-
- .item.client.selected .item-twisty-container:dir(rtl) {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-expanded-inverted");
- }
-
- .item.client.selected.closed .item-twisty-container:dir(rtl) {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-collapsed-inverted-rtl");
- }
-}
-
-.item.client.closed .item-twisty-container {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-collapsed");
-}
-
-.item.client.selected:focus .item-twisty-container {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-expanded-inverted");
-}
-
-.item.client.selected.closed:focus .item-twisty-container {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-collapsed-inverted");
-}
-
-.item.client .item-twisty-container:dir(rtl) {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-expanded");
-}
-
-.item.client.closed .item-twisty-container:dir(rtl) {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-collapsed-rtl");
-}
-
-.item.client.selected:focus .item-twisty-container:dir(rtl) {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-expanded-inverted");
-}
-
-.item.client.selected.closed:focus .item-twisty-container:dir(rtl) {
- background-image: url("chrome://global/skin/tree/arrow-disclosure.svg#arrow-disclosure-collapsed-inverted-rtl");
-}
-
-@media (-moz-mac-yosemite-theme) {
- .item.selected > .item-title-container {
- color: -moz-dialogtext;
- font-weight: 500;
- }
-
- .item.selected:focus > .item-title-container {
- color: #fff;
- }
-}
-
-.sidebar-search-container {
- border-bottom: 1px solid #bdbdbd;
-}
-
-.search-box {
- -moz-appearance: searchfield;
- padding: 1px;
- font-size: 12px;
- cursor: text;
- margin: 4px 8px 10px;
- border-width: 3px;
- border-style: solid;
- border-color: currentcolor;
- border-image: none;
- -moz-border-top-colors: transparent #888 #000;
- -moz-border-right-colors: transparent #FFF #000;
- -moz-border-bottom-colors: transparent #FFF #000;
- -moz-border-left-colors: transparent #888 #000;
- border-top-right-radius: 2px;
- border-bottom-left-radius: 2px;
- background-color: #FFF;
- color: #000;
- -moz-user-select: text;
- text-shadow: none;
-}
-
-.search-box.compact > .textbox-input-box > .textbox-search-icons > .textbox-search-clear {
- background-image: url(chrome://global/skin/icons/searchfield-cancel.svg);
- background-repeat: no-repeat;
- background-size: 11px 11px;
- width: 11px;
- height: 11px;
-}
-
-.search-box.compact > .textbox-input-box > .textbox-search-icons > .textbox-search-icon {
- display: none;
-}
-
-.search-box[focused="true"] {
- -moz-border-top-colors: -moz-mac-focusring -moz-mac-focusring #000000;
- -moz-border-right-colors: -moz-mac-focusring -moz-mac-focusring #000000;
- -moz-border-bottom-colors: -moz-mac-focusring -moz-mac-focusring #000000;
- -moz-border-left-colors: -moz-mac-focusring -moz-mac-focusring #000000;
-}
-
-.search-box.compact {
- padding: 0px;
- /* font size is in px because the XUL it was copied from uses px */
- font-size: 11px;
-}
-
-.textbox-search-clear,
-.textbox-search-icon {
- margin-top: 1px;
-}
diff --git a/application/basilisk/themes/shared/browser.inc b/application/basilisk/themes/shared/browser.inc
index 81caf94d6..6989f064a 100644
--- a/application/basilisk/themes/shared/browser.inc
+++ b/application/basilisk/themes/shared/browser.inc
@@ -2,7 +2,7 @@
% Note that zoom-reset-button is a bit different since it doesn't use an image and thus has the image with display: none.
%define nestedButtons #zoom-out-button, #zoom-reset-button, #zoom-in-button, #cut-button, #copy-button, #paste-button
-%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #fullscreen-button, #sync-button, #feed-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button, #sidebar-button, @nestedButtons@, #e10s-button, #panic-button, #webide-button, #containers-panelmenu
+%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #fullscreen-button, #sync-button, #sync-tabs-button, #feed-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button, #sidebar-button, @nestedButtons@, #e10s-button, #panic-button, #webide-button, #containers-panelmenu
%ifdef XP_MACOSX
% Prior to 10.7 there wasn't a native fullscreen button so we use #restore-button to exit fullscreen
diff --git a/application/basilisk/themes/shared/customizableui/panelUI.inc.css b/application/basilisk/themes/shared/customizableui/panelUI.inc.css
index ba36da995..5550ef295 100644
--- a/application/basilisk/themes/shared/customizableui/panelUI.inc.css
+++ b/application/basilisk/themes/shared/customizableui/panelUI.inc.css
@@ -61,8 +61,7 @@
height: 13px;
}
-#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
-#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
box-shadow: none;
filter: drop-shadow(0 1px 0 hsla(206, 50%, 10%, .15));
}
@@ -86,13 +85,7 @@
background: #D90000;
}
-#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
- height: 13px;
- background: transparent url(chrome://browser/skin/warning.svg) no-repeat center;
-}
-
-#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive,
-#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
+#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
filter: none;
}
@@ -381,9 +374,6 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"] > iframe {
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-contents-scroller > #PanelUI-contents > .panel-wide-item,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-contents-scroller > #PanelUI-contents > .toolbarbutton-1:not([panel-multiview-anchor="true"]),
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-update-status,
-#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-fxa > #PanelUI-fxa-status > #PanelUI-fxa-avatar,
-#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-fxa > #PanelUI-fxa-status > #PanelUI-fxa-label,
-#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-fxa > #PanelUI-fxa-icon,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-inner > toolbarseparator,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-inner > #PanelUI-customize,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-inner > #PanelUI-help:not([panel-multiview-anchor="true"]) {
@@ -481,26 +471,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
margin: 0;
}
-#main-window[customizing] #PanelUI-footer-fxa {
- display: none;
-}
-
-#PanelUI-footer-fxa:not([fxastatus="signedin"]) > toolbarseparator,
-#PanelUI-footer-fxa:not([fxastatus="signedin"]) > #PanelUI-fxa-icon,
-#PanelUI-footer-fxa:not([fxaprofileimage]) > #PanelUI-fxa-status > #PanelUI-fxa-avatar {
- display: none;
-}
-
-#PanelUI-footer-fxa[fxastatus="error"] > #PanelUI-fxa-status::after {
- content: url(chrome://browser/skin/warning.svg);
- filter: drop-shadow(0 1px 0 hsla(206,50%,10%,.15));
- width: 47px;
- padding-top: 1px;
- display: block;
- text-align: center;
- position: relative;
- top: 25%;
-}
#PanelUI-update-status[update-status]::after {
content: "";
@@ -523,40 +493,28 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
background-color: #D90000;
}
-#PanelUI-fxa-status {
- display: flex;
- flex: 1 1 0%;
- width: 1px;
-}
-
-#PanelUI-footer-inner,
-#PanelUI-footer-fxa:not([hidden]) {
+#PanelUI-footer-inner {
display: flex;
border-top: 1px solid var(--panel-separator-color);
}
-#PanelUI-multiView[viewtype="subview"] #PanelUI-footer-inner,
-#PanelUI-multiView[viewtype="subview"] #PanelUI-footer-fxa {
+#PanelUI-multiView[viewtype="subview"] #PanelUI-footer-inner {
position: relative;
}
-#PanelUI-footer-inner > toolbarseparator,
-#PanelUI-footer-fxa > toolbarseparator {
+#PanelUI-footer-inner > toolbarseparator {
border: 0;
border-left: 1px solid var(--panel-separator-color);
margin: 7px 0 7px;
-moz-appearance: none;
}
-#PanelUI-footer-inner:hover > toolbarseparator,
-#PanelUI-footer-fxa:hover > toolbarseparator {
+#PanelUI-footer-inner:hover > toolbarseparator {
margin: 0;
}
#PanelUI-update-status,
#PanelUI-help,
-#PanelUI-fxa-label,
-#PanelUI-fxa-icon,
#PanelUI-customize,
#PanelUI-quit {
margin: 0;
@@ -590,7 +548,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
}
#PanelUI-update-status > .toolbarbutton-text,
-#PanelUI-fxa-label > .toolbarbutton-text,
#PanelUI-customize > .toolbarbutton-text {
margin: 0;
padding: 0 6px;
@@ -598,37 +555,23 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
}
#PanelUI-help > .toolbarbutton-text,
-#PanelUI-quit > .toolbarbutton-text,
-#PanelUI-fxa-avatar > .toolbarbutton-text {
+#PanelUI-quit > .toolbarbutton-text {
display: none;
}
#PanelUI-update-status > .toolbarbutton-icon,
-#PanelUI-fxa-label > .toolbarbutton-icon,
-#PanelUI-fxa-icon > .toolbarbutton-icon,
#PanelUI-customize > .toolbarbutton-icon,
#PanelUI-help > .toolbarbutton-icon,
#PanelUI-quit > .toolbarbutton-icon {
margin-inline-end: 0;
}
-#PanelUI-fxa-icon {
- padding-inline-start: 15px;
- padding-inline-end: 15px;
-}
-
-#PanelUI-fxa-label,
#PanelUI-customize {
flex: 1;
padding-inline-start: 15px;
border-inline-start-style: none;
}
-#PanelUI-footer-fxa[fxaprofileimage="set"] > #PanelUI-fxa-status > #PanelUI-fxa-label,
-#PanelUI-footer-fxa[fxaprofileimage="enabled"]:not([fxastatus="error"]) > #PanelUI-fxa-status > #PanelUI-fxa-label {
- padding-inline-start: 0px;
-}
-
#PanelUI-update-status {
width: calc(@menuPanelWidth@ + 30px);
padding-inline-start: 15px;
@@ -639,130 +582,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
list-style-image: url(chrome://branding/content/icon16.png);
}
-#PanelUI-fxa-label,
-#PanelUI-fxa-icon {
- list-style-image: url(chrome://browser/skin/sync-horizontalbar.png);
-}
-
-#PanelUI-remotetabs {
- --panel-ui-sync-illustration-height: 157.5px;
-}
-
-.PanelUI-remotetabs-instruction-title,
-.PanelUI-remotetabs-instruction-label,
-#PanelUI-remotetabs-mobile-promo {
- /* If you change the margin here, the min-height of the synced tabs panel
- (e.g. #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync, etc) may
- need adjusting (see bug 1248506) */
- margin: 15px;
- text-align: center;
- text-shadow: none;
- max-width: 15em;
- color: GrayText;
-}
-
-.PanelUI-remotetabs-instruction-title {
- font-size: 1.3em;
-}
-
-/* The boxes with "instructions" get extra top and bottom padding for space
- around the illustration and buttons */
-.PanelUI-remotetabs-instruction-box {
- /* If you change the padding here, the min-height of the synced tabs panel
- (e.g. #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync, etc) may
- need adjusting (see bug 1248506) */
- padding-bottom: 30px;
- padding-top: 15px;
-}
-
-.PanelUI-remotetabs-prefs-button {
- -moz-appearance: none;
- background-color: #0096dd;
- /* !important for the color as an OSX specific rule when a lightweight theme
- is used for buttons in the toolbox overrides. See bug 1238531 for details */
- color: white !important;
- border-radius: 2px;
- /* If you change the margin or padding below, the min-height of the synced tabs
- panel (e.g. #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync,
- etc) may need adjusting (see bug 1248506) */
- margin-top: 10px;
- margin-bottom: 10px;
- padding: 8px;
- text-shadow: none;
- min-width: 200px;
-}
-
-.PanelUI-remotetabs-prefs-button:hover,
-.PanelUI-remotetabs-prefs-button:hover:active {
- background-color: #018acb;
-}
-
-.remotetabs-promo-link {
- margin: 0;
-}
-
-.PanelUI-remotetabs-notabsforclient-label {
- color: GrayText;
- /* This margin is to line this label up with the labels in toolbarbuttons. */
- margin-left: 28px;
-}
-
-.fxaSyncIllustration {
- height: var(--panel-ui-sync-illustration-height);
- list-style-image: url(chrome://browser/skin/fxa/sync-illustration.svg);
-}
-
-.PanelUI-remotetabs-prefs-button > .toolbarbutton-text {
- /* !important to override ".cui-widget-panel toolbarbutton > .toolbarbutton-text" above. */
- text-align: center !important;
- text-shadow: none;
-}
-
-#PanelUI-remotetabs[mainview] { /* panel anchored to toolbar button might be too skinny */
- min-width: 19em;
-}
-
-/* Work around bug 1224412 - these boxes will cause scrollbars to appear when
- the panel is anchored to a toolbar button.
-*/
-#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync,
-#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-reauthsync,
-#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-nodevicespane,
-#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-tabsdisabledpane {
- min-height: calc(var(--panel-ui-sync-illustration-height) +
- 20px + /* margin of .PanelUI-remotetabs-prefs-button */
- 16px + /* padding of .PanelUI-remotetabs-prefs-button */
- 30px + /* margin of .PanelUI-remotetabs-instruction-label */
- 30px + 15px + /* padding of .PanelUI-remotetabs-instruction-box */
- 11em);
-}
-
-#PanelUI-remotetabs-tabslist > label[itemtype="client"] {
- color: GrayText;
-}
-
-/* Collapse the non-active vboxes in the remotetabs deck to use only the
- height the active box needs */
-#PanelUI-remotetabs-deck:not([selectedIndex="1"]) > #PanelUI-remotetabs-tabsdisabledpane,
-#PanelUI-remotetabs-deck:not([selectedIndex="2"]) > #PanelUI-remotetabs-fetching,
-#PanelUI-remotetabs-deck:not([selectedIndex="3"]) > #PanelUI-remotetabs-nodevicespane {
- visibility: collapse;
-}
-
-#PanelUI-remotetabs-main[devices-status="single"] > #PanelUI-remotetabs-buttons {
- display: none;
-}
-
-#PanelUI-fxa-icon[syncstatus="active"]:not([disabled]) {
- list-style-image: url(chrome://browser/skin/syncProgress-horizontalbar.png);
-}
-
-#PanelUI-footer-fxa[fxastatus="migrate-signup"] > #PanelUI-fxa-status > #PanelUI-fxa-label,
-#PanelUI-footer-fxa[fxastatus="migrate-verify"] > #PanelUI-fxa-status > #PanelUI-fxa-label {
- list-style-image: url(chrome://browser/skin/warning.svg);
- -moz-image-region: auto;
-}
-
#PanelUI-customize {
list-style-image: url(chrome://browser/skin/menuPanel-customize.png);
}
@@ -780,46 +599,12 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
list-style-image: url(chrome://browser/skin/menuPanel-exit.png);
}
-#PanelUI-fxa-label,
-#PanelUI-fxa-icon,
#PanelUI-customize,
#PanelUI-help,
#PanelUI-quit {
-moz-image-region: rect(0, 16px, 16px, 0);
}
-#PanelUI-footer-fxa[fxastatus="signedin"] > #PanelUI-fxa-status > #PanelUI-fxa-label > .toolbarbutton-icon,
-#PanelUI-footer-fxa[fxastatus="error"][fxaprofileimage="set"] > #PanelUI-fxa-status > #PanelUI-fxa-label > .toolbarbutton-icon {
- display: none;
-}
-
-#PanelUI-footer-fxa[fxastatus="error"]:not([fxaprofileimage="set"]) > #PanelUI-fxa-status > #PanelUI-fxa-avatar {
- display: none;
-}
-
-#PanelUI-fxa-status[disabled],
-#PanelUI-fxa-icon[disabled] {
- pointer-events: none;
-}
-
-#PanelUI-fxa-avatar {
- width: 32px;
- height: 32px;
- border-radius: 50%;
- background-repeat: no-repeat;
- background-position: 0 0;
- background-size: contain;
- align-self: center;
- margin: 0px 7px;
- padding: 0px;
- border: 0px none;
- margin-inline-end: 0;
-}
-
-#PanelUI-footer-fxa[fxaprofileimage="enabled"] > #PanelUI-fxa-status > #PanelUI-fxa-avatar {
- list-style-image: url(chrome://browser/skin/fxa/default-avatar.svg);
-}
-
#PanelUI-customize:hover,
#PanelUI-help:not([disabled]):hover,
#PanelUI-quit:not([disabled]):hover {
@@ -837,16 +622,10 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
}
#PanelUI-help[disabled],
-#PanelUI-quit[disabled],
-#PanelUI-fxa-icon[disabled],
-#PanelUI-fxa-avatar[disabled],
-#PanelUI-fxa-label[disabled] > .toolbarbutton-icon,
-#PanelUI-fxa-status::after {
+#PanelUI-quit[disabled] {
opacity: 0.4;
}
-#PanelUI-fxa-status:not([disabled]):hover,
-#PanelUI-fxa-icon:not([disabled]):hover,
#PanelUI-help:not([disabled]):hover,
#PanelUI-customize:hover,
#PanelUI-quit:not([disabled]):hover {
@@ -854,8 +633,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
background-color: var(--arrowpanel-dimmed);
}
-#PanelUI-fxa-status:not([disabled]):hover:active,
-#PanelUI-fxa-icon:not([disabled]):hover:active,
#PanelUI-help:not([disabled]):hover:active,
#PanelUI-customize:hover:active,
#PanelUI-quit:not([disabled]):hover:active {
@@ -864,27 +641,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
}
-#PanelUI-fxa-status:not([disabled]):hover,
-#PanelUI-fxa-status:not([disabled]):hover:active,
-#PanelUI-fxa-icon:not([disabled]):hover,
-#PanelUI-fxa-icon:not([disabled]):hover:active {
- outline: none;
-}
-
-#PanelUI-footer-fxa[fxastatus="error"] {
- background-color: hsl(42,94%,88%);
- border-top: 1px solid hsl(42,94%,70%);
-}
-
-#PanelUI-footer-fxa[fxastatus="error"] > #PanelUI-fxa-status:hover {
- background-color: hsl(42,94%,85%);
-}
-
-#PanelUI-footer-fxa[fxastatus="error"] > #PanelUI-fxa-status:hover:active {
- background-color: hsl(42,94%,82%);
- box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
-}
-
#PanelUI-update-status {
color: black;
}
@@ -1150,19 +906,16 @@ menuitem.panel-subview-footer@menuStateActive@,
color: GrayText;
}
-#PanelUI-remotetabs-tabslist > toolbarbutton,
#PanelUI-historyItems > toolbarbutton {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
}
@media (min-resolution: 1.1dppx) {
- #PanelUI-remotetabs-tabslist > toolbarbutton,
#PanelUI-historyItems > toolbarbutton {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png");
}
}
-#PanelUI-remotetabs-tabslist > toolbarbutton > .toolbarbutton-icon,
#PanelUI-recentlyClosedWindows > toolbarbutton > .toolbarbutton-icon,
#PanelUI-recentlyClosedTabs > toolbarbutton > .toolbarbutton-icon,
#PanelUI-historyItems > toolbarbutton > .toolbarbutton-icon {
@@ -1616,15 +1369,6 @@ menuitem[checked="true"].subviewbutton > .menu-iconic-left {
list-style-image: url(chrome://branding/content/icon32.png);
}
- #PanelUI-fxa-label,
- #PanelUI-fxa-icon {
- list-style-image: url(chrome://browser/skin/sync-horizontalbar@2x.png);
- }
-
- #PanelUI-fxa-icon[syncstatus="active"]:not([disabled]) {
- list-style-image: url(chrome://browser/skin/syncProgress-horizontalbar@2x.png);
- }
-
#PanelUI-customize {
list-style-image: url(chrome://browser/skin/menuPanel-customize@2x.png);
}
@@ -1641,8 +1385,6 @@ menuitem[checked="true"].subviewbutton > .menu-iconic-left {
list-style-image: url(chrome://browser/skin/menuPanel-exit@2x.png);
}
- #PanelUI-fxa-label,
- #PanelUI-fxa-icon,
#PanelUI-customize,
#PanelUI-help,
#PanelUI-quit {
@@ -1650,8 +1392,6 @@ menuitem[checked="true"].subviewbutton > .menu-iconic-left {
}
#PanelUI-update-status > .toolbarbutton-icon,
- #PanelUI-fxa-label > .toolbarbutton-icon,
- #PanelUI-fxa-icon > .toolbarbutton-icon,
#PanelUI-customize > .toolbarbutton-icon,
#PanelUI-help > .toolbarbutton-icon,
#PanelUI-quit > .toolbarbutton-icon {
diff --git a/application/basilisk/themes/shared/incontentprefs/containers.css b/application/basilisk/themes/shared/incontentprefs/containers.css
deleted file mode 100644
index 5446dccce..000000000
--- a/application/basilisk/themes/shared/incontentprefs/containers.css
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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/. */
-
-%include ../../../components/contextualidentity/content/usercontext.css
-
-.container-header-links {
- margin-block-end: 15px;
-}
-
-[data-identity-icon] {
- margin: 0;
- margin-inline-end: 16px;
-}
-
-#containersView {
- border: 0 none;
- background: transparent;
-}
-
-#containersView richlistitem {
- margin: 0px;
- margin-inline-end: 8px;
- padding: 0;
- padding-block-end: 8px;
- border-block-end: 1px solid var(--in-content-header-border-color);
-}
-
-#containersView richlistitem:last-of-type {
- border-block-end: 0 none;
- margin-block-end: 8px;
-}
diff --git a/application/basilisk/themes/shared/incontentprefs/preferences.inc.css b/application/basilisk/themes/shared/incontentprefs/preferences.inc.css
index 0e62660de..20ea98327 100644
--- a/application/basilisk/themes/shared/incontentprefs/preferences.inc.css
+++ b/application/basilisk/themes/shared/incontentprefs/preferences.inc.css
@@ -237,8 +237,7 @@ treecol {
/* Privacy pane */
#trackingProtectionPBMLearnMore,
-#trackingProtectionLearnMore,
-#browserContainersLearnMore {
+#trackingProtectionLearnMore {
margin-inline-start: 1.5em !important;
margin-top: 0;
font-weight: normal;
diff --git a/application/basilisk/themes/shared/jar.inc.mn b/application/basilisk/themes/shared/jar.inc.mn
index 361edd311..5750d2dc5 100644
--- a/application/basilisk/themes/shared/jar.inc.mn
+++ b/application/basilisk/themes/shared/jar.inc.mn
@@ -73,8 +73,6 @@
skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico)
skin/classic/browser/preferences/in-content/icons.svg (../shared/incontentprefs/icons.svg)
skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css)
-* skin/classic/browser/preferences/in-content/containers.css (../shared/incontentprefs/containers.css)
-* skin/classic/browser/preferences/containers.css (../shared/preferences/containers.css)
skin/classic/browser/fxa/default-avatar.svg (../shared/fxa/default-avatar.svg)
skin/classic/browser/fxa/logo.png (../shared/fxa/logo.png)
skin/classic/browser/fxa/logo@2x.png (../shared/fxa/logo@2x.png)
diff --git a/application/basilisk/themes/shared/menupanel.inc.css b/application/basilisk/themes/shared/menupanel.inc.css
index 266e1c83e..da2f07e1e 100644
--- a/application/basilisk/themes/shared/menupanel.inc.css
+++ b/application/basilisk/themes/shared/menupanel.inc.css
@@ -48,10 +48,29 @@ toolbarpaletteitem[place="palette"] > #save-page-button {
-moz-image-region: rect(0px, 352px, 32px, 320px);
}
+%ifdef MOZ_SERVICES_SYNC
#sync-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #sync-button {
+ -moz-image-region: rect(0px, 384px, 32px, 352px)
+}
+
+#sync-button[cui-areatype="menu-panel"][status="active"] {
+ list-style-image: url("chrome://browser/skin/syncProgress-menuPanel.png");
+ -moz-image-region: rect(0, 32px, 32px, 0);
+}
+
+@media (min-resolution: 1.1dppx) {
+ #sync-button[cui-areatype="menu-panel"][status="active"] {
+ list-style-image: url("chrome://browser/skin/syncProgress-menuPanel@2x.png");
+ -moz-image-region: rect(0, 64px, 64px, 0);
+ }
+}
+
+#sync-tabs-button[cui-areatype="menu-panel"],
+toolbarpaletteitem[place="palette"] > #sync-tabs-button {
-moz-image-region: rect(0px, 1024px, 32px, 992px);
}
+%endif
#containers-panelmenu[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #containers-panelmenu {
diff --git a/application/basilisk/themes/shared/newtab/newTab.inc.css b/application/basilisk/themes/shared/newtab/newTab.inc.css
index 8ecd603c9..5cbdb240e 100644
--- a/application/basilisk/themes/shared/newtab/newTab.inc.css
+++ b/application/basilisk/themes/shared/newtab/newTab.inc.css
@@ -99,19 +99,6 @@
border-radius: 2px;
}
-/* GRID */
-#topsites-heading {
- color: #7A7A7A;
- font-size: 1em;
- font-weight: normal;
- /* Position the heading such that it doesn't affect how many cells we
- can fit into the grid. */
- position: absolute;
- /* The top margin moves the heading away from the grid.
- The horizontal margin aligns the heading with the cells. */
- margin: -1em 10px 0;
-}
-
/* CELLS */
.newtab-cell {
--cell-corner-radius: 8px;
@@ -119,10 +106,6 @@
border-radius: var(--cell-corner-radius);
}
-body.compact .newtab-cell {
- --cell-corner-radius: 2px;
-}
-
.newtab-cell:empty {
outline: 2px dashed #c1c1c1;
outline-offset: -2px;
@@ -172,49 +155,16 @@ body.compact .newtab-cell {
transition: opacity 100ms ease-out;
}
-body.compact .newtab-thumbnail {
- height: 100%;
- border-radius: calc(var(--cell-corner-radius) + 1px);
- outline: 1px solid hsla(0,0%,0%,.1);
- -moz-outline-radius: var(--cell-corner-radius);
- outline-offset: -1px;
-}
-
.newtab-thumbnail.placeholder {
color: white;
font-size: 85px;
line-height: 200%;
}
-body.compact .newtab-thumbnail.placeholder {
- font-size: 45px;
-}
-
-.newtab-cell:not([ignorehover]) .newtab-site:hover .newtab-thumbnail.enhanced-content {
- opacity: 0;
-}
-
-.newtab-site[type=affiliate] .newtab-thumbnail,
-.newtab-site[type=enhanced] .newtab-thumbnail,
-.newtab-site[type=organic] .newtab-thumbnail,
-.newtab-site[type=sponsored] .newtab-thumbnail {
- background-position: center center;
-}
-
-body.compact .newtab-site[type=affiliate] .newtab-thumbnail {
- background-position: center 30%;
-}
-
-.newtab-site[type=affiliate] .newtab-thumbnail,
-body:not(.compact) .newtab-site[type=enhanced] .newtab-thumbnail,
-body:not(.compact) .newtab-site[type=organic] .newtab-thumbnail,
-body:not(.compact) .newtab-site[type=sponsored] .newtab-thumbnail {
- background-size: auto;
-}
-
/* TITLES */
.newtab-title {
+ color: #5c5c5c;
background-color: #F2F2F2;
font-size: 13px;
line-height: 30px;
@@ -222,45 +172,13 @@ body:not(.compact) .newtab-site[type=sponsored] .newtab-thumbnail {
border-radius: 0 0 var(--cell-corner-radius) var(--cell-corner-radius);
}
-body.compact .newtab-title {
- background-color: hsla(0,0%,100%,.85);
- font-size: 12px;
- line-height: 21px;
- border: 1px solid hsla(0,0%,80%,.8);
- border-top-color: hsla(0,0%,0%,.1);
- background-clip: padding-box;
-}
-
-.newtab-title,
-.newtab-suggested {
- color: #5c5c5c;
-}
-
-body.compact .newtab-title,
-body.compact .newtab-suggested {
- color: black;
-}
-
-.newtab-suggested[active] {
- background-color: rgba(51, 51, 51, 0.95);
- border: 0;
- color: white;
-}
-
-body:not(.compact) .newtab-site:hover .newtab-title {
+.newtab-site:hover .newtab-title {
color: white;
background-color: #333;
border-color: #333;
border-top-color: white;
}
-body.compact .newtab-site:hover .newtab-title {
- color: white;
- background-color: hsla(0,0%,20%,.85);
- border-color: hsla(0,0%,0%,.8);
- border-top-color: white;
-}
-
.newtab-site[pinned] .newtab-title {
padding-inline-start: 24px;
}
@@ -302,20 +220,6 @@ body.compact .newtab-site:hover .newtab-title {
right: 4px;
}
-body.compact .newtab-control {
- top: -8px;
-}
-
-body.compact .newtab-control-pin:dir(ltr),
-body.compact .newtab-control-block:dir(rtl) {
- left: -8px;
-}
-
-body.compact .newtab-control-block:dir(ltr),
-body.compact .newtab-control-pin:dir(rtl) {
- right: -8px;
-}
-
.newtab-control-pin,
.newtab-site[pinned] .newtab-control-pin:hover:active {
background-image: -moz-image-rect(url(chrome://browser/skin/newtab/controls.svg), 0, 96, 32, 64);
diff --git a/application/basilisk/themes/shared/preferences/containers.css b/application/basilisk/themes/shared/preferences/containers.css
deleted file mode 100644
index 3fb965331..000000000
--- a/application/basilisk/themes/shared/preferences/containers.css
+++ /dev/null
@@ -1,53 +0,0 @@
-/* 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/. */
-
-%include ../../../components/contextualidentity/content/usercontext.css
-
-:root {
- --preference-selected-color: #0996f8;
- --preference-unselected-color: #333;
- --preference-active-color: #858585;
-}
-
-radiogroup {
- display: flex;
- margin-inline-start: 0.35rem;
-}
-
-radio {
- flex: auto;
- display: flex;
- align-items: center;
- justify-content: center;
- -moz-user-select: none;
- outline: 2px solid transparent;
- outline-offset: 4px;
- -moz-outline-radius: 100%;
- min-block-size: 24px;
- min-inline-size: 24px;
- border-radius: 50%;
- padding: 2px;
- margin: 10px;
-}
-
-.icon-buttons > radio > [data-identity-icon] {
- fill: #4d4d4d;
-}
-
-radio > [data-identity-icon] {
- inline-size: 22px;
- block-size: 22px;
-}
-
-radio[selected=true] {
- outline-color: var(--preference-unselected-color);
-}
-
-radio[focused=true] {
- outline-color: var(--preference-selected-color);
-}
-
-radio:hover:active {
- outline-color: var(--preference-active-color);
-}
diff --git a/application/basilisk/themes/shared/syncedtabs/sidebar.inc.css b/application/basilisk/themes/shared/syncedtabs/sidebar.inc.css
deleted file mode 100644
index 4e76a7fc5..000000000
--- a/application/basilisk/themes/shared/syncedtabs/sidebar.inc.css
+++ /dev/null
@@ -1,234 +0,0 @@
-% 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/.
-
-/* These styles are intended to mimic XUL trees and the XUL search box. */
-
-html {
- height: 100%;
-}
-
-body {
- height: 100%;
- margin: 0;
- font: message-box;
- color: #333333;
- -moz-user-select: none;
-}
-
-/* The content-container holds the non-scrollable header and the scrollable
- content area.
-*/
-.content-container {
- display: flex;
- flex-flow: column;
- height: 100%;
-}
-
-/* The content header is not scrollable */
-.content-header {
- flex: 0 1 auto;
-}
-
-/* The main content area is scrollable and fills the rest of the area */
-.content-scrollable {
- flex: 1 1 auto;
- overflow: auto;
-}
-
-.emptyListInfo {
- cursor: default;
- padding: 3em 1em;
- text-align: center;
-}
-
-.list,
-.item-tabs-list {
- display: flex;
- flex-flow: column;
- flex-grow: 1;
-}
-
-.item.client {
- opacity: 1;
- max-height: unset;
- display: unset;
-}
-
-.item.client.closed .item-tabs-list {
- display: none;
-}
-
-.item {
- display: inline-block;
- opacity: 1;
- flex: 1;
- min-width: 0;
- white-space: nowrap;
- overflow: hidden;
- outline: none;
- color: -moz-FieldText;
-}
-
-.item.selected > .item-title-container {
- background-color: -moz-cellhighlight;
- color: -moz-cellhighlighttext;
- font-weight: bold;
-}
-
-.item.selected:focus > .item-title-container {
- background-color: Highlight;
- color: HighlightText;
-}
-
-.client .item.tab > .item-title-container {
- padding-inline-start: 35px;
-}
-
-.item.tab > .item-title-container {
- padding-inline-start: 20px;
-}
-
-.item.client.device-image-desktop > .item-title-container > .item-icon-container {
- background-image: url("chrome://browser/skin/sync-desktopIcon.svg#icon");
-}
-
-.item.client.device-image-desktop.selected:focus > .item-title-container > .item-icon-container {
- background-image: url("chrome://browser/skin/sync-desktopIcon.svg#icon-inverted");
-}
-
-.item.client.device-image-mobile > .item-title-container > .item-icon-container {
- background-image: url("chrome://browser/skin/sync-mobileIcon.svg#icon");
-}
-
-.item.client.device-image-mobile.selected:focus > .item-title-container > .item-icon-container {
- background-image: url("chrome://browser/skin/sync-mobileIcon.svg#icon-inverted");
-}
-
-.item.tab > .item-title-container > .item-icon-container {
- background-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
-}
-
-@media (min-resolution: 1.1dppx) {
-.item.tab > .item-title-container > .item-icon-container {
- background-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png");
- }
-}
-
-.item-icon-container {
- min-width: 16px;
- max-width: 16px;
- min-height: 16px;
- max-height: 16px;
- margin-right: 5px;
- margin-left: 5px;
- background-size: 16px 16px;
- background-size: contain;
- background-repeat: no-repeat;
- background-position: center;
-}
-
-.item-title-container {
- display: flex;
- flex-flow: row;
- overflow: hidden;
- flex-grow: 1;
- padding: 1px 0px 1px 0px;
-}
-
-.item-title {
- flex-grow: 1;
- overflow: hidden;
- text-overflow: ellipsis;
- margin: 0px;
- line-height: 1.3;
- cursor: default;
-}
-
-.item[hidden] {
- opacity: 0;
- max-height: 0;
- transition: opacity 150ms ease-in-out, max-height 150ms ease-in-out 150ms;
-}
-
-.item.empty .item-title-container {
- color: #aeaeae;
-}
-
-.client .item.empty > .item-title-container {
- padding-inline-start: 35px;
-}
-
-.text-input-box {
- display: flex;
- flex-flow: row nowrap;
-}
-
-.textbox-input-box {
- display: flex;
- flex-direction: row;
-}
-
-.tabsFilter {
- flex: 1;
- /* min-width of anything to override the implicit "-moz-min-content" value.
- 0px is safe as the sidebar itself has a constrained size meaning we will
- never actually hit this minimum
- */
- min-width: 0px;
-}
-
-.sync-state > p {
- padding-inline-end: 10px;
- padding-inline-start: 10px;
- color: #888;
-}
-
-.text-link {
- color: rgb(0, 149, 221);
- cursor: pointer;
-}
-
-.text-link:hover {
- text-decoration: underline;
-}
-
-.text-link,
-.text-link:focus {
- margin: 0px;
- padding: 0px;
- border: 0px;
-}
-
-.deck .sync-state {
- display: none;
- opacity: 0;
- transition: opacity 1.5s;
- border-top: 1px solid #bdbdbd;
-}
-
-.deck .sync-state.tabs-container {
- border-top: 0px;
-}
-
-.deck .sync-state.selected {
- display: unset;
- opacity: 100;
-}
-
-.sidebar-search-container.tabs-container:not(.selected) {
- display: none;
-}
-
-.textbox-search-clear:not([disabled]) {
- cursor: default;
-}
-
-.textbox-search-icons .textbox-search-clear,
-.filtered .textbox-search-icons .textbox-search-icon {
- display: none;
-}
-
-.filtered .textbox-search-icons .textbox-search-clear {
- display: block;
-}
diff --git a/application/basilisk/themes/shared/toolbarbuttons.inc.css b/application/basilisk/themes/shared/toolbarbuttons.inc.css
index c043b8192..8992bfcb1 100644
--- a/application/basilisk/themes/shared/toolbarbuttons.inc.css
+++ b/application/basilisk/themes/shared/toolbarbuttons.inc.css
@@ -52,9 +52,32 @@ toolbar[brighttext] #bookmarks-menu-button > .toolbarbutton-menubutton-dropmarke
-moz-image-region: rect(0, 252px, 18px, 234px);
}
+%ifdef MOZ_SERVICES_SYNC
#sync-button[cui-areatype="toolbar"] {
+ -moz-image-region: rect(0, 270px, 18px, 252px);
+}
+
+#sync-button[cui-areatype="toolbar"][status="active"] {
+ list-style-image: url("chrome://browser/skin/syncProgress-toolbar.png");
+ -moz-image-region: rect(0, 18px, 18px, 0);
+}
+
+@media (-moz-os-version: windows-win7) {
+ #sync-button[cui-areatype="toolbar"][status="active"] {
+ list-style-image: url("chrome://browser/skin/syncProgress-toolbar-win7.png");
+ -moz-image-region: rect(0, 18px, 18px, 0);
+ }
+}
+
+toolbar[brighttext] #sync-button[cui-areatype="toolbar"][status="active"] {
+ list-style-image: url("chrome://browser/skin/syncProgress-toolbar-inverted.png");
+ -moz-image-region: rect(0, 18px, 18px, 0);
+}
+
+#sync-tabs-button[cui-areatype="toolbar"] {
-moz-image-region: rect(0, 792px, 18px, 774px);
}
+%endif
#containers-panelmenu[cui-areatype="toolbar"] {
-moz-image-region: rect(0, 810px, 18px, 792px);
@@ -226,9 +249,32 @@ toolbar[brighttext] #bookmarks-menu-button > .toolbarbutton-menubutton-dropmarke
-moz-image-region: rect(0, 504px, 36px, 468px);
}
+%ifdef MOZ_SERVICES_SYNC
#sync-button[cui-areatype="toolbar"] {
+ -moz-image-region: rect(0, 540px, 36px, 504px);
+ }
+
+ #sync-button[cui-areatype="toolbar"][status="active"] {
+ list-style-image: url("chrome://browser/skin/syncProgress-toolbar@2x.png");
+ -moz-image-region: rect(0, 36px, 36px, 0);
+ }
+
+ @media (-moz-os-version: windows-win7) {
+ #sync-button[cui-areatype="toolbar"][status="active"] {
+ list-style-image: url("chrome://browser/skin/syncProgress-toolbar-win7@2x.png");
+ -moz-image-region: rect(0, 36px, 36px, 0);
+ }
+ }
+
+ toolbar[brighttext] #sync-button[cui-areatype="toolbar"][status="active"] {
+ list-style-image: url("chrome://browser/skin/syncProgress-toolbar-inverted@2x.png");
+ -moz-image-region: rect(0, 36px, 36px, 0);
+ }
+
+ #sync-tabs-button[cui-areatype="toolbar"] {
-moz-image-region: rect(0, 1584px, 36px, 1548px);
}
+%endif
#containers-panelmenu[cui-areatype="toolbar"] {
-moz-image-region: rect(0, 1620px, 36px, 1584px);
diff --git a/application/basilisk/themes/windows/jar.mn b/application/basilisk/themes/windows/jar.mn
index e8db7eed2..28c6c6465 100644
--- a/application/basilisk/themes/windows/jar.mn
+++ b/application/basilisk/themes/windows/jar.mn
@@ -7,8 +7,9 @@ browser.jar:
#include ../shared/jar.inc.mn
skin/classic/browser/sanitizeDialog.css
skin/classic/browser/aboutSessionRestore-window-icon.png
+#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/aboutSyncTabs.css
-* skin/classic/browser/syncedtabs/sidebar.css (syncedtabs/sidebar.css)
+#endif
skin/classic/browser/actionicon-tab.png
skin/classic/browser/actionicon-tab@2x.png
skin/classic/browser/actionicon-tab-win7.png
@@ -141,6 +142,7 @@ browser.jar:
skin/classic/browser/tabbrowser/tab-stroke-start.png (tabbrowser/tab-stroke-start.png)
skin/classic/browser/tabbrowser/tab-stroke-start@2x.png (tabbrowser/tab-stroke-start@2x.png)
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
+#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-16.png
skin/classic/browser/sync-32.png
skin/classic/browser/sync-128.png
@@ -167,6 +169,8 @@ browser.jar:
skin/classic/browser/syncProgress-toolbar-inverted@2x.png
skin/classic/browser/syncProgress-toolbar-win7.png
skin/classic/browser/syncProgress-toolbar-win7@2x.png
+ skin/classic/browser/syncProgress.css
+#endif
[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
% override chrome://browser/skin/page-livemarks.png chrome://browser/skin/feeds/feedIcon16.png
@@ -182,12 +186,14 @@ browser.jar:
% override chrome://browser/skin/privatebrowsing-mask-titlebar.png chrome://browser/skin/privatebrowsing-mask-titlebar-win7.png os=WINNT osversion<=6.1
% override chrome://browser/skin/reload-stop-go.png chrome://browser/skin/reload-stop-go-win7.png os=WINNT osversion<=6.1
% override chrome://browser/skin/reload-stop-go@2x.png chrome://browser/skin/reload-stop-go-win7@2x.png os=WINNT osversion<=6.1
+#ifdef MOZ_SERVICES_SYNC
% override chrome://browser/skin/sync-horizontalbar.png chrome://browser/skin/sync-horizontalbar-win7.png os=WINNT osversion<=6.1
% override chrome://browser/skin/sync-horizontalbar@2x.png chrome://browser/skin/sync-horizontalbar-win7@2x.png os=WINNT osversion<=6.1
% override chrome://browser/skin/syncProgress-horizontalbar.png chrome://browser/skin/syncProgress-horizontalbar-win7.png os=WINNT osversion<=6.1
% override chrome://browser/skin/syncProgress-horizontalbar@2x.png chrome://browser/skin/syncProgress-horizontalbar-win7@2x.png os=WINNT osversion<=6.1
% override chrome://browser/skin/syncProgress-toolbar.png chrome://browser/skin/syncProgress-toolbar-win7.png os=WINNT osversion<=6.1
% override chrome://browser/skin/syncProgress-toolbar@2x.png chrome://browser/skin/syncProgress-toolbar-win7@2x.png os=WINNT osversion<=6.1
+#endif
% override chrome://browser/skin/toolbarbutton-dropdown-arrow.png chrome://browser/skin/toolbarbutton-dropdown-arrow-win7.png os=WINNT osversion<=6.1
% override chrome://browser/skin/urlbar-history-dropmarker.png chrome://browser/skin/urlbar-history-dropmarker-win7.png os=WINNT osversion<=6.1
% override chrome://browser/skin/urlbar-history-dropmarker@2x.png chrome://browser/skin/urlbar-history-dropmarker-win7@2x.png os=WINNT osversion<=6.1
diff --git a/application/basilisk/themes/windows/syncProgress.css b/application/basilisk/themes/windows/syncProgress.css
new file mode 100644
index 000000000..d7aa59976
--- /dev/null
+++ b/application/basilisk/themes/windows/syncProgress.css
@@ -0,0 +1,46 @@
+/* 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 url(chrome://global/skin/inContentUI.css);
+
+:root {
+ height: 100%;
+ width: 100%;
+ padding: 0;
+}
+
+body {
+ margin: 0;
+ padding: 0 2em;
+}
+
+#floatingBox {
+ margin: 4em auto;
+ max-width: 40em;
+ min-width: 23em;
+ padding: 1em 1.5em;
+ position: relative;
+ text-align: center;
+}
+
+#successLogo {
+ margin: 1em 2em;
+}
+
+#loadingText {
+ margin: 2em 6em;
+}
+
+#progressBar {
+ margin: 2em 10em;
+}
+
+#uploadProgressBar{
+ width: 100%;
+}
+
+#bottomRow {
+ margin-top: 2em;
+ padding: 0;
+ text-align: end;
+}
diff --git a/application/basilisk/themes/windows/syncedtabs/sidebar.css b/application/basilisk/themes/windows/syncedtabs/sidebar.css
deleted file mode 100644
index 6473206bc..000000000
--- a/application/basilisk/themes/windows/syncedtabs/sidebar.css
+++ /dev/null
@@ -1,132 +0,0 @@
-/* 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/. */
-
-%include ../../shared/syncedtabs/sidebar.inc.css
-
-/* These styles are intended to mimic XUL trees and the XUL search box. */
-
-html {
- background-color: #EEF3FA;
-}
-
-.item {
- padding-inline-end: 0;
-}
-
-.item-title {
- margin: 1px 0 0;
-}
-
-.item-title {
- margin-inline-end: 6px;
-}
-
-.search-box {
- -moz-appearance: textfield;
- cursor: text;
- margin: 2px 4px;
- padding: 2px 2px 3px;
- padding-inline-start: 4px;
- color: -moz-FieldText;
-}
-
-.textbox-search-icon {
- width: 16px;
- height: 16px;
- background-image: url(chrome://global/skin/icons/Search-glass.png);
- background-repeat: no-repeat;
- display: block;
-}
-
-.textbox-search-icon:-moz-locale-dir(rtl) {
- transform: scaleX(-1);
-}
-
-.textbox-search-icon[searchbutton]:not([disabled]) {
- cursor: pointer;
-}
-
-.textbox-search-clear {
- width: 16px;
- height: 16px;
- background-image: url(chrome://global/skin/icons/Search-close.png);
- background-repeat: no-repeat;
-}
-
-.textbox-search-clear:not([disabled]) {
- cursor: default;
-}
-
-.textbox-search-icon:not([disabled]) {
- cursor: text;
-}
-
-.textbox-search-clear:not([disabled]):hover ,
-.textbox-search-icon:not([disabled]):hover {
- background-position: -16px 0;
-}
-
-.textbox-search-clear:not([disabled]):hover:active ,
-.textbox-search-icon:not([disabled]):hover:active {
- background-position: -32px 0;
-}
-
-.client .item.tab > .item-title-container {
- padding-inline-start: 26px;
-}
-.item.tab > .item-title-container {
- padding-inline-start: 14px;
-}
-
-.item-icon-container {
- min-width: 16px;
- max-width: 16px;
- min-height: 16px;
- max-height: 16px;
- margin-right: 5px;
- background-size: 16px 16px;
- background-repeat: no-repeat;
- background-position: center;
-}
-
-.item-twisty-container {
- background-size: contain;
- background-repeat: no-repeat;
- background-position: center;
- padding-top: 5px;
- min-width: 9px; /* The image's width is 9 pixels */
- height: 9px;
-}
-
-.item.client .item-twisty-container {
- background-image: url("chrome://global/skin/tree/twisty.svg#open");
-}
-
-.item.client.closed .item-twisty-container {
- background-image: url("chrome://global/skin/tree/twisty.svg#clsd");
-}
-
-.item.client .item-twisty-container:hover {
- background-image: url("chrome://global/skin/tree/twisty.svg#open-hover");
-}
-
-.item.client.closed .item-twisty-container:hover {
- background-image: url("chrome://global/skin/tree/twisty.svg#clsd-hover");
-}
-
-.item.client .item-twisty-container:dir(rtl) {
- background-image: url("chrome://global/skin/tree/twisty.svg#open-rtl");
-}
-
-.item.client.closed .item-twisty-container:dir(rtl) {
- background-image: url("chrome://global/skin/tree/twisty.svg#clsd-rtl");
-}
-
-.item.client .item-twisty-container:hover:dir(rtl) {
- background-image: url("chrome://global/skin/tree/twisty.svg#open-hover-rtl");
-}
-
-.item.client.closed .item-twisty-container:hover:dir(rtl) {
- background-image: url("chrome://global/skin/tree/twisty.svg#clsd-hover-rtl");
-}
diff --git a/application/palemoon/app/blocklist.xml b/application/palemoon/app/blocklist.xml
index d55784169..fa594aabe 100644
--- a/application/palemoon/app/blocklist.xml
+++ b/application/palemoon/app/blocklist.xml
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
-<blocklist lastupdate="1534840140000"
+<blocklist lastupdate="1554898538000"
xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem blockID="i545" id="superlrcs@svenyor.net">
@@ -2524,6 +2524,11 @@ xmlns="http://www.mozilla.org/2006/addons-blocklist">
</versionRange>
<prefs></prefs>
</emItem>
+ <emItem blockID="pm114" id="jid1-KKzOGWgsW3Ao4Q@jetpack">
+ <versionRange minVersion="2.9.9" maxVersion="2.9.9" severity="3">
+ </versionRange>
+ <prefs></prefs>
+ </emItem>
</emItems>
<pluginItems>
<pluginItem blockID="p26">
diff --git a/application/palemoon/app/moz.build b/application/palemoon/app/moz.build
index c11f4c37e..8166760af 100644
--- a/application/palemoon/app/moz.build
+++ b/application/palemoon/app/moz.build
@@ -20,6 +20,7 @@ if CONFIG['LIBXUL_SDK']:
SOURCES += ['nsBrowserApp.cpp']
FINAL_TARGET_FILES += ['blocklist.xml']
+FINAL_TARGET_FILES.defaults += ['permissions']
FINAL_TARGET_FILES.defaults.profile += ['profile/prefs.js']
DEFINES['APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
diff --git a/application/palemoon/app/permissions b/application/palemoon/app/permissions
new file mode 100644
index 000000000..4d90be82a
--- /dev/null
+++ b/application/palemoon/app/permissions
@@ -0,0 +1,14 @@
+# This file has default permissions for the permission manager.
+# The file-format is strict:
+# * matchtype \t type \t permission \t host
+# * "origin" should be used for matchtype, "host" is supported for legacy reasons
+# * type is a string that identifies the type of permission (e.g. "cookie")
+# * permission is an integer between 1 and 15
+# See nsPermissionManager.cpp for more...
+
+# XPInstall
+origin install 1 http://www.palemoon.org
+origin install 1 https://www.palemoon.org
+
+origin install 1 http://addons.palemoon.org
+origin install 1 https://addons.palemoon.org
diff --git a/application/palemoon/app/profile/palemoon.js b/application/palemoon/app/profile/palemoon.js
index 85dc41c15..d0e078eb7 100644
--- a/application/palemoon/app/profile/palemoon.js
+++ b/application/palemoon/app/profile/palemoon.js
@@ -206,9 +206,6 @@ pref("extensions.dss.switchPending", false); // Non-dynamic switch pending af
pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name", "chrome://browser/locale/browser.properties");
pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description", "chrome://browser/locale/browser.properties");
-pref("xpinstall.whitelist.add", "addons.mozilla.org,www.palemoon.org,addons.palemoon.org");
-pref("xpinstall.whitelist.add.36", "");
-pref("xpinstall.whitelist.add.180", "");
pref("xpinstall.whitelist.required", false);
// Allow installing XPI add-ons by direct URL requests (no referrer)
pref("xpinstall.whitelist.directRequest", true);
@@ -1080,17 +1077,12 @@ pref("browser.newtab.preload", false);
// Toggles the content of 'about:newtab'. Shows the grid when enabled.
pref("browser.newtabpage.enabled", true);
-// XXX: Remove this when "enhanced" tiles are dead
-pref("browser.newtabpage.enhanced", false);
-
// Disables capturing of page thumbnails
pref("browser.pagethumbnails.capturing_disabled", false);
// enables showing basic placeholders for missing thumbnails
pref("browser.newtabpage.thumbnailPlaceholder", false);
-pref("privacy.usercontext.about_newtab_segregation.enabled", false);
-
// number of columns of newtab grid
pref("browser.newtabpage.columns", 4);
@@ -1105,6 +1097,9 @@ pref("full-screen-api.enabled", true);
// 0-100 (currently)
pref("permissions.places-sites-limit", 50);
+// Built-in default permissions.
+pref("permissions.manager.defaultsUrl", "resource://app/defaults/permissions");
+
// Startup Crash Tracking
// number of startup crashes that can occur before starting into safe mode automatically
// (this pref has no effect if more than 6 hours have passed since the last crash)
diff --git a/application/palemoon/base/content/aboutRobots-icon.png b/application/palemoon/base/content/aboutRobots-icon.png
deleted file mode 100644
index 1c4899aaf..000000000
--- a/application/palemoon/base/content/aboutRobots-icon.png
+++ /dev/null
Binary files differ
diff --git a/application/palemoon/base/content/aboutRobots-widget-left.png b/application/palemoon/base/content/aboutRobots-widget-left.png
deleted file mode 100644
index 3a1e48d5f..000000000
--- a/application/palemoon/base/content/aboutRobots-widget-left.png
+++ /dev/null
Binary files differ
diff --git a/application/palemoon/base/content/aboutRobots.xhtml b/application/palemoon/base/content/aboutRobots.xhtml
deleted file mode 100644
index 23fe3ba17..000000000
--- a/application/palemoon/base/content/aboutRobots.xhtml
+++ /dev/null
@@ -1,108 +0,0 @@
-<?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 [
- <!ENTITY % htmlDTD
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "DTD/xhtml1-strict.dtd">
- %htmlDTD;
- <!ENTITY % netErrorDTD
- SYSTEM "chrome://global/locale/netError.dtd">
- %netErrorDTD;
- <!ENTITY % globalDTD
- SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
- <!ENTITY % aboutrobotsDTD
- SYSTEM "chrome://browser/locale/aboutRobots.dtd">
- %aboutrobotsDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>&robots.pagetitle;</title>
- <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" />
- <link rel="icon" type="image/png" id="favicon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAACGFjVEwAAAASAAAAAJNtBPIAAAAaZmNUTAAAAAAAAAAQAAAAEAAAAAAAAAAALuAD6AABhIDeugAAALhJREFUOI2Nk8sNxCAMRDlGohauXFOMpfTiAlxICqAELltHLqlgctg1InzMRhpFAc%2BLGWTnmoeZYamt78zXdZmaQtQMADlnU0OIAlbmJUBEcO4bRKQY2rUXIPmAGnDuG%2FBx3%2FfvOPVaDUg%2BoAPUf1PArIMCSD5glMEsUGaG%2BkyAFWIBaCsKuA%2BHGCNijLgP133XgOEtaPFMy2vUolEGJoCIzBmoRUR9%2B7rxj16DZaW%2FmgtmxnJ8V3oAnApQwNS5zpcAAAAaZmNUTAAAAAEAAAAQAAAAEAAAAAAAAAAAAB4D6AIB52fclgAAACpmZEFUAAAAAjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9WF%2Bu8QAAABpmY1RMAAAAAwAAABAAAAAQAAAAAAAAAAAAHgPoAgEK8Q9%2FAAAAFmZkQVQAAAAEOI1jYBgFo2AUjAIIAAAEEAAB0xIn4wAAABpmY1RMAAAABQAAABAAAAAQAAAAAAAAAAAAHgPoAgHnO30FAAAAQGZkQVQAAAAGOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVfozYcAAAABpmY1RMAAAABwAAABAAAAAQAAAAAAAAAAAAHgPoAgEKra7sAAAAFmZkQVQAAAAIOI1jYBgFo2AUjAIIAAAEEAABM9s3hAAAABpmY1RMAAAACQAAABAAAAAQAAAAAAAAAAAAHgPoAgHn3p%2BwAAAAKmZkQVQAAAAKOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F1BhPl6AAAAGmZjVEwAAAALAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQpITFkAAAAWZmRBVAAAAAw4jWNgGAWjYBSMAggAAAQQAAHaszpmAAAAGmZjVEwAAAANAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeeCPiMAAABAZmRBVAAAAA44jWNgGJ5gpxrDf2LEcIL%2FpzAVYxPDavP%2FUwz%2FpW79%2F%2F%2F%2FFMP%2FnWoQjC5GOxcgu4QYsVEwCmAAAOE0KxUmBL0KAAAAGmZjVEwAAAAPAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQoU7coAAAAWZmRBVAAAABA4jWNgGAWjYBSMAggAAAQQAAEpOBELAAAAGmZjVEwAAAARAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeYVWtoAAAAqZmRBVAAAABI4jWNgGAVYQXNz839ixHBq3qnG8B9ZAzYx2rlgFIwCcgAA8psX%2FWvpAecAAAAaZmNUTAAAABMAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC4OJMwAAABZmZEFUAAAAFDiNY2AYBaNgFIwCCAAABBAAAcBQHOkAAAAaZmNUTAAAABUAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5kn7SQAAAEBmZEFUAAAAFjiNY2AYnmCnGsN%2FYsRwgv%2BnMBVjE8Nq8%2F9TDP%2Blbv3%2F%2F%2F8Uw%2F%2BdahCMLkY7FyC7hBixUTAKYAAA4TQrFc%2BcEoQAAAAaZmNUTAAAABcAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC98ooAAAABZmZEFUAAAAGDiNY2AYBaNgFIwCCAAABBAAASCZDI4AAAAaZmNUTAAAABkAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5qwZ%2FAAAACpmZEFUAAAAGjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9cjJWbAAAABpmY1RMAAAAGwAAABAAAAAQAAAAAAAAAAAAHgPoAgELOsoVAAAAFmZkQVQAAAAcOI1jYBgFo2AUjAIIAAAEEAAByfEBbAAAABpmY1RMAAAAHQAAABAAAAAQAAAAAAAAAAAAHgPoAgHm8LhvAAAAQGZkQVQAAAAeOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVlxR3%2FgAAABpmY1RMAAAAHwAAABAAAAAQAAAAAAAAAAAAHgPoAgELZmuGAAAAFmZkQVQAAAAgOI1jYBgFo2AUjAIIAAAEEAABHP5cFQAAABpmY1RMAAAAIQAAABAAAAAQAAAAAAAAAAAAHgPoAgHlgtAOAAAAKmZkQVQAAAAiOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F0%2FMvDdAAAAAElFTkSuQmCC"/>
-
- <script type="application/javascript"><![CDATA[
- var buttonClicked = false;
- function robotButton()
- {
- var button = document.getElementById('errorTryAgain');
- if (buttonClicked) {
- button.style.visibility = "hidden";
- } else {
- var newLabel = button.getAttribute("label2");
- button.textContent = newLabel;
- buttonClicked = true;
- }
- }
- ]]></script>
-
- <style type="text/css"><![CDATA[
- #errorPageContainer {
- background-image: none;
- }
-
- #errorPageContainer:before {
- content: url('chrome://browser/content/aboutRobots-icon.png');
- position: absolute;
- }
-
- body[dir=rtl] #icon,
- body[dir=rtl] #errorPageContainer:before {
- transform: scaleX(-1);
- }
- ]]></style>
- </head>
-
- <body dir="&locale.dir;">
-
- <!-- PAGE CONTAINER (for styling purposes only) -->
- <div id="errorPageContainer">
-
- <!-- Error Title -->
- <div id="errorTitle">
- <h1 id="errorTitleText">&robots.errorTitleText;</h1>
- </div>
-
- <!-- LONG CONTENT (the section most likely to require scrolling) -->
- <div id="errorLongContent">
-
- <!-- Short Description -->
- <div id="errorShortDesc">
- <p id="errorShortDescText">&robots.errorShortDescText;</p>
- </div>
-
- <!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
- <div id="errorLongDesc">
- <ul>
- <li>&robots.errorLongDesc1;</li>
- <li>&robots.errorLongDesc2;</li>
- <li>&robots.errorLongDesc3;</li>
- <li>&robots.errorLongDesc4;</li>
- </ul>
- </div>
-
- <!-- Short Description -->
- <div id="errorTrailerDesc">
- <p id="errorTrailerDescText">&robots.errorTrailerDescText;</p>
- </div>
-
- </div>
-
- <!-- Button -->
- <button id="errorTryAgain"
- label2="&robots.dontpress;"
- onclick="robotButton();">&retry.label;</button>
-
- <img src="chrome://browser/content/aboutRobots-widget-left.png"
- style="position: absolute; bottom: -12px; left: -10px;"/>
- <img src="chrome://browser/content/aboutRobots-widget-left.png"
- style="position: absolute; bottom: -12px; right: -10px; transform: scaleX(-1);"/>
- </div>
-
- </body>
-</html>
diff --git a/application/palemoon/base/content/baseMenuOverlay.xul b/application/palemoon/base/content/baseMenuOverlay.xul
index a006ed5c6..bccdec265 100644
--- a/application/palemoon/base/content/baseMenuOverlay.xul
+++ b/application/palemoon/base/content/baseMenuOverlay.xul
@@ -57,15 +57,21 @@
label="&helpTroubleshootingInfo.label;"
oncommand="openTroubleshootingPage()"
onclick="checkForMiddleClick(this, event);"/>
+ <menuitem id="helpSafeMode"
+ accesskey="&helpSafeMode.accesskey;"
+ label="&helpSafeMode.label;"
+ oncommand="restart(true);"/>
+ <menuseparator/>
+ <menuitem id="releaseNotes"
+ accesskey="&helpReleaseNotes.accesskey;"
+ label="&helpReleaseNotes.label;"
+ oncommand="openReleaseNotes();"
+ onclick="checkForMiddleClick(this, event);"/>
<menuitem id="feedbackPage"
accesskey="&helpFeedbackPage.accesskey;"
label="&helpFeedbackPage.label;"
oncommand="openFeedbackPage()"
onclick="checkForMiddleClick(this, event);"/>
- <menuitem id="helpSafeMode"
- accesskey="&helpSafeMode.accesskey;"
- label="&helpSafeMode.label;"
- oncommand="restart(true);"/>
<menuseparator id="updatesSeparator"/>
<menuitem id="checkForUpdates" class="menuitem-iconic"
#ifdef MOZ_UPDATER
diff --git a/application/palemoon/base/content/browser-appmenu.inc b/application/palemoon/base/content/browser-appmenu.inc
index ffb117a60..9d202c965 100644
--- a/application/palemoon/base/content/browser-appmenu.inc
+++ b/application/palemoon/base/content/browser-appmenu.inc
@@ -350,14 +350,19 @@
label="&helpTroubleshootingInfo.label;"
oncommand="openTroubleshootingPage()"
onclick="checkForMiddleClick(this,event);"/>
+ <menuitem id="appmenu_safeMode"
+ label="&appMenuSafeMode.label;"
+ oncommand="restart(true);"/>
+ <menuseparator/>
+ <menuitem id="appmenu_releaseNotes"
+ accesskey="&helpReleaseNotes.accesskey;"
+ label="&helpReleaseNotes.label;"
+ oncommand="openReleaseNotes();"
+ onclick="checkForMiddleClick(this, event);"/>
<menuitem id="appmenu_feedbackPage"
label="&helpFeedbackPage.label;"
oncommand="openFeedbackPage()"
onclick="checkForMiddleClick(this, event);"/>
- <menuseparator/>
- <menuitem id="appmenu_safeMode"
- label="&appMenuSafeMode.label;"
- oncommand="restart(true);"/>
#ifdef MOZ_UPDATER
<menuseparator/>
<menuitem id="appmenu_checkForUpdates"
diff --git a/application/palemoon/base/content/browser-menudragging.js b/application/palemoon/base/content/browser-menudragging.js
index cf26b2ba4..f3f00d72c 100644
--- a/application/palemoon/base/content/browser-menudragging.js
+++ b/application/palemoon/base/content/browser-menudragging.js
@@ -52,11 +52,9 @@ var browserMenuDragging = {
initPref: function(){
this.STAY_OPEN_ONDRAGEXIT =
- this.getPref('browser.menu.dragging.stayOpen',
- 'bool', false);
+ Services.prefs.getBoolPref('browser.menu.dragging.stayOpen', false);
this.DEBUG =
- this.getPref('browser.menu.dragging.debug',
- 'bool', false);
+ Services.prefs.getBoolPref('browser.menu.dragging.debug', false);
},
//delayed startup
@@ -291,26 +289,6 @@ var browserMenuDragging = {
.logStringMessage(aMsg);
},
- getPref: function(aPrefString, aPrefType, aDefault){
- var xpPref = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefService);
- try{
- switch (aPrefType){
- case 'complex':
- return xpPref.getComplexValue(aPrefString, Components.interfaces.nsILocalFile); break;
- case 'str':
- return xpPref.getCharPref(aPrefString).toString(); break;
- case 'int':
- return xpPref.getIntPref(aPrefString); break;
- case 'bool':
- default:
- return xpPref.getBoolPref(aPrefString); break;
- }
- }catch(e){
- }
- return aDefault;
- },
-
setPref: function(aPrefString, aPrefType, aValue){
var xpPref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
diff --git a/application/palemoon/base/content/browser-syncui.js b/application/palemoon/base/content/browser-syncui.js
index 67056e221..86f6f48f1 100644
--- a/application/palemoon/base/content/browser-syncui.js
+++ b/application/palemoon/base/content/browser-syncui.js
@@ -83,10 +83,7 @@ var gSyncUI = {
_wasDelayed: false,
_needsSetup: function SUI__needsSetup() {
- let firstSync = "";
- try {
- firstSync = Services.prefs.getCharPref("services.sync.firstSync");
- } catch (e) { }
+ let firstSync = Services.prefs.getCharPref("services.sync.firstSync", "");
return Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED ||
firstSync == "notReady";
},
@@ -96,17 +93,25 @@ var gSyncUI = {
document.getElementById("sync-setup-state").hidden = !needsSetup;
document.getElementById("sync-syncnow-state").hidden = needsSetup;
- if (!gBrowser)
+ if (!gBrowser) {
return;
+ }
let button = document.getElementById("sync-button");
- if (!button)
+ if (!button) {
return;
+ }
button.removeAttribute("status");
+
this._updateLastSyncTime();
- if (needsSetup)
+
+ if (needsSetup) {
button.removeAttribute("tooltiptext");
+ button.setAttribute("label", this._stringBundle.GetStringFromName("setupsync.label"));
+ } else {
+ button.setAttribute("label", this._stringBundle.GetStringFromName("syncnow.label"));
+ }
},
@@ -120,6 +125,7 @@ var gSyncUI = {
return;
button.setAttribute("status", "active");
+ button.setAttribute("label", this._stringBundle.GetStringFromName("syncing2.label"));
},
onSyncDelay: function SUI_onSyncDelay() {
@@ -285,11 +291,7 @@ var gSyncUI = {
if (!syncButton)
return;
- let lastSync;
- try {
- lastSync = Services.prefs.getCharPref("services.sync.lastSync");
- }
- catch (e) { };
+ let lastSync = Services.prefs.getCharPref("services.sync.lastSync", "");
if (!lastSync || this._needsSetup()) {
syncButton.removeAttribute("tooltiptext");
return;
diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js
index 4e753d422..16b7c0019 100644
--- a/application/palemoon/base/content/browser.js
+++ b/application/palemoon/base/content/browser.js
@@ -412,6 +412,10 @@ var gURLBarSettings = {
},
writePlaceholder: function() {
+ if (!gURLBar) {
+ return;
+ }
+
let attribute = "placeholder";
let prefs = this.prefSuggests.map(pref => {
return this.prefSuggest + pref;
@@ -1147,7 +1151,7 @@ var gBrowserInit = {
// Setup click-and-hold gestures access to the session history
// menus if global click-and-hold isn't turned on
- if (!getBoolPref("ui.click_hold_context_menus", false))
+ if (!Services.prefs.getBoolPref("ui.click_hold_context_menus", false))
SetClickAndHoldHandlers();
// Initialize the full zoom setting.
@@ -1783,7 +1787,7 @@ function BrowserGoHome(aEvent) {
case "tabshifted":
case "tab":
urls = homePage.split("|");
- var loadInBackground = getBoolPref("browser.tabs.loadBookmarksInBackground", false);
+ var loadInBackground = Services.prefs.getBoolPref("browser.tabs.loadBookmarksInBackground", false);
gBrowser.loadTabs(urls, loadInBackground);
break;
case "window":
@@ -3402,7 +3406,7 @@ function BrowserCustomizeToolbar() {
TabsInTitlebar.allowedBy("customizing-toolbars", false);
var customizeURL = "chrome://global/content/customizeToolbar.xul";
- gCustomizeSheet = getBoolPref("toolbar.customization.usesheet", false);
+ gCustomizeSheet = Services.prefs.getBoolPref("toolbar.customization.usesheet", false);
if (gCustomizeSheet) {
let sheetFrame = document.createElement("iframe");
@@ -3471,6 +3475,7 @@ function BrowserToolboxCustomizeDone(aToolboxChanged) {
// Update the urlbar
if (gURLBar) {
+ gURLBarSettings.writePlaceholder();
URLBarSetURI();
XULBrowserWindow.asyncUpdateUI();
BookmarkingUI.updateStarState();
@@ -3486,7 +3491,7 @@ function BrowserToolboxCustomizeDone(aToolboxChanged) {
cmd.removeAttribute("disabled");
// make sure to re-enable click-and-hold
- if (!getBoolPref("ui.click_hold_context_menus", false))
+ if (!Services.prefs.getBoolPref("ui.click_hold_context_menus", false))
SetClickAndHoldHandlers();
gBrowser.selectedBrowser.focus();
@@ -4476,14 +4481,15 @@ nsBrowserAccess.prototype = {
}
let loadInBackground = gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground");
- let referrer = aOpener ? makeURI(aOpener.location.href) : null;
+ let openerWindow = (aContext & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener;
let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", {
triggeringPrincipal: triggeringPrincipal,
referrerURI: referrer,
referrerPolicy: referrerPolicy,
fromExternal: isExternal,
- inBackground: loadInBackground});
+ inBackground: loadInBackground,
+ opener: openerWindow });
let browser = win.gBrowser.getBrowserForTab(tab);
if (gPrefService.getBoolPref("browser.tabs.noWindowActivationOnExternal")) {
@@ -5338,9 +5344,6 @@ function handleDroppedLink(event, urlOrLinks, name)
let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange;
- let userContextId = gBrowser.selectedBrowser
- .getAttribute("usercontextid") || 0;
-
let inBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground");
if (event.shiftKey)
inBackground = !inBackground;
@@ -5359,7 +5362,6 @@ function handleDroppedLink(event, urlOrLinks, name)
replace: true,
allowThirdPartyFixup: false,
postDatas,
- userContextId,
});
}
});
diff --git a/application/palemoon/base/content/content.js b/application/palemoon/base/content/content.js
index 653dac3e3..211a24a8b 100644
--- a/application/palemoon/base/content/content.js
+++ b/application/palemoon/base/content/content.js
@@ -139,7 +139,6 @@ var handleContentContextMenu = function (event) {
let selectionInfo = BrowserUtils.getSelectionDetails(content);
let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
- let userContextId = loadContext.originAttributes.userContextId;
let browser = docShell.chromeEventHandler;
let mainWin = browser.ownerGlobal;
@@ -160,7 +159,6 @@ var handleContentContextMenu = function (event) {
selectionInfo: selectionInfo,
loginFillInfo,
parentAllowsMixedContent,
- userContextId,
};
}
diff --git a/application/palemoon/base/content/palemoon.xhtml b/application/palemoon/base/content/palemoon.xhtml
index 96757052c..f145550a9 100644
--- a/application/palemoon/base/content/palemoon.xhtml
+++ b/application/palemoon/base/content/palemoon.xhtml
@@ -13,7 +13,7 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset='utf-8' />
- <title>&chronicles.title.55.2;</title>
+ <title>&chronicles.title.66.1;</title>
<style type="text/css">
html {
@@ -54,11 +54,11 @@ a {
<section>
<p id="moztext">
- &chronicles.quote.55.2;
+ &chronicles.quote.66.1;
</p>
<p id="from">
- &chronicles.from.55.2;
+ &chronicles.from.66.1;
</p>
</section>
diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml
index cbe029af0..b5edd54b7 100644
--- a/application/palemoon/base/content/tabbrowser.xml
+++ b/application/palemoon/base/content/tabbrowser.xml
@@ -402,11 +402,18 @@
let promptBox = {
appendPrompt : function(args, onCloseCallback) {
let newPrompt = document.createElementNS(XUL_NS, "tabmodalprompt");
- stack.appendChild(newPrompt);
+ // stack.appendChild(newPrompt);
+ stack.insertBefore(newPrompt, browser.nextSibling);
browser.setAttribute("tabmodalPromptShowing", true);
newPrompt.clientTop; // style flush to assure binding is attached
+ let prompts = this.listPrompts();
+ if (prompts.length > 1) {
+ // Let's hide ourself behind the current prompt.
+ newPrompt.hidden = true;
+ }
+
let tab = self._getTabForContentWindow(browser.contentWindow);
newPrompt.init(args, tab, onCloseCallback);
return newPrompt;
@@ -418,6 +425,7 @@
let prompts = this.listPrompts();
if (prompts.length) {
let prompt = prompts[prompts.length - 1];
+ prompt.hidden = false;
prompt.Dialog.setDefaultFocus();
} else {
browser.removeAttribute("tabmodalPromptShowing");
@@ -737,8 +745,7 @@
let autocomplete = this.mTabBrowser._placesAutocomplete;
if (this.mBrowser.registeredOpenURI) {
- autocomplete.unregisterOpenPage(this.mBrowser.registeredOpenURI,
- this.mBrowser.getAttribute("usercontextid") || 0);
+ autocomplete.unregisterOpenPage(this.mBrowser.registeredOpenURI);
delete this.mBrowser.registeredOpenURI;
}
// Tabs in private windows aren't registered as "Open" so
@@ -746,8 +753,7 @@
if (!isBlankPageURL(aLocation.spec) &&
(!PrivateBrowsingUtils.isWindowPrivate(window) ||
PrivateBrowsingUtils.permanentPrivateBrowsing)) {
- autocomplete.registerOpenPage(aLocation,
- this.mBrowser.getAttribute("usercontextid") || 0);
+ autocomplete.registerOpenPage(aLocation);
this.mBrowser.registeredOpenURI = aLocation;
}
}
@@ -825,13 +831,8 @@
}
let sizedIconUrl = browser.mIconURL || "";
- if (sizedIconUrl) {
- let size = Math.round(16 * window.devicePixelRatio);
- sizedIconUrl += (sizedIconUrl.includes("#") ? "&" : "#") +
- "-moz-resolution=" + size + "," + size;
- }
if (sizedIconUrl != aTab.getAttribute("image")) {
- if (browser.mIconURL)
+ if (sizedIconUrl)
aTab.setAttribute("image", sizedIconUrl);
else
aTab.removeAttribute("image");
@@ -1336,6 +1337,7 @@
var aFromExternal;
var aRelatedToCurrent;
var aOriginPrincipal;
+ var aOpener;
if (arguments.length == 2 &&
typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) {
@@ -1350,6 +1352,7 @@
aFromExternal = params.fromExternal;
aRelatedToCurrent = params.relatedToCurrent;
aOriginPrincipal = params.originPrincipal;
+ aOpener = params.opener;
}
var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
@@ -1365,7 +1368,8 @@
allowThirdPartyFixup: aAllowThirdPartyFixup,
fromExternal: aFromExternal,
originPrincipal: aOriginPrincipal,
- relatedToCurrent: aRelatedToCurrent});
+ relatedToCurrent: aRelatedToCurrent,
+ opener: aOpener });
if (!bgLoad)
this.selectedTab = tab;
@@ -1383,7 +1387,6 @@
let aTargetTab;
let aNewIndex = -1;
let aPostDatas = [];
- let aUserContextId;
if (arguments.length == 2 &&
typeof arguments[1] == "object") {
let params = arguments[1];
@@ -1394,7 +1397,6 @@
aNewIndex = typeof params.newIndex === "number" ?
params.newIndex : aNewIndex;
aPostDatas = params.postDatas || aPostDatas;
- aUserContextId = params.userContextId;
}
if (!aURIs.length)
@@ -1443,8 +1445,7 @@
ownerTab: owner,
skipAnimation: multiple,
allowThirdPartyFixup: aAllowThirdPartyFixup,
- postData: aPostDatas[0],
- userContextId: aUserContextId
+ postData: aPostDatas[0]
});
if (aNewIndex !== -1) {
this.moveTabTo(firstTabAdded, aNewIndex);
@@ -1457,8 +1458,7 @@
let tab = this.addTab(aURIs[i], {
skipAnimation: true,
allowThirdPartyFixup: aAllowThirdPartyFixup,
- postData: aPostDatas[i],
- userContextId: aUserContextId
+ postData: aPostDatas[i]
});
if (targetTabIndex !== -1)
this.moveTabTo(tab, ++tabNum);
@@ -1492,6 +1492,7 @@
var aSkipAnimation;
var aOriginPrincipal;
var aSkipBackgroundNotify;
+ var aOpener;
if (arguments.length == 2 &&
typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) {
@@ -1507,6 +1508,7 @@
aRelatedToCurrent = params.relatedToCurrent;
aSkipAnimation = params.skipAnimation;
aOriginPrincipal = params.originPrincipal;
+ aOpener = params.opener;
aSkipBackgroundNotify = params.skipBackgroundNotify;
}
@@ -1581,6 +1583,10 @@
b.setAttribute("showresizer", "true");
}
+ if (aOpener) {
+ b.QueryInterface(Ci.nsIFrameLoaderOwner).presetOpenerWindow(aOpener);
+ }
+
if (this.hasAttribute("autocompletepopup"))
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
@@ -2059,8 +2065,7 @@
this.mTabListeners[aTab._tPos].destroy();
if (browser.registeredOpenURI && !aTabWillBeMoved) {
- this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI,
- browser.getAttribute("usercontextid") || 0);
+ this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI);
delete browser.registeredOpenURI;
}
@@ -2428,8 +2433,7 @@
<![CDATA[
// If the current URI is registered as open remove it from the list.
if (aOurBrowser.registeredOpenURI) {
- this._placesAutocomplete.unregisterOpenPage(aOurBrowser.registeredOpenURI,
- aOurBrowser.getAttribute("usercontextid") || 0);
+ this._placesAutocomplete.unregisterOpenPage(aOurBrowser.registeredOpenURI);
delete aOurBrowser.registeredOpenURI;
}
@@ -3339,8 +3343,7 @@
for (var i = 0; i < this.mTabListeners.length; ++i) {
let browser = this.getBrowserAtIndex(i);
if (browser.registeredOpenURI) {
- this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI,
- browser.getAttribute("usercontextid") || 0);
+ this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI);
delete browser.registeredOpenURI;
}
browser.webProgress.removeProgressListener(this.mTabFilters[i]);
@@ -3637,11 +3640,7 @@
window.addEventListener("resize", this, false);
window.addEventListener("load", this, false);
- try {
- this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled");
- } catch (ex) {
- this._tabAnimationLoggingEnabled = false;
- }
+ this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled", false);
this._browserNewtabpageEnabled = Services.prefs.getBoolPref("browser.newtabpage.enabled");
]]>
</constructor>
@@ -4799,8 +4798,6 @@
inBackground = !inBackground;
let targetTab = this._getDragTargetTab(event);
- let userContextId = this.selectedItem
- .getAttribute("usercontextid") || 0;
let replace = !(!targetTab || dropEffect == "copy");
let newIndex = this._getDropIndex(event);
let urls = links.map(link => link.url);
@@ -4810,7 +4807,6 @@
allowThirdPartyFixup: true,
targetTab,
newIndex,
- userContextId,
});
}
diff --git a/application/palemoon/base/content/utilityOverlay.js b/application/palemoon/base/content/utilityOverlay.js
index fe148ad04..1d284ba2a 100644
--- a/application/palemoon/base/content/utilityOverlay.js
+++ b/application/palemoon/base/content/utilityOverlay.js
@@ -12,6 +12,9 @@ Components.utils.import("resource:///modules/RecentWindow.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ShellService",
"resource:///modules/ShellService.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
+ "resource://gre/modules/Deprecated.jsm");
+
XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () {
const PREF = "browser.newtab.url";
@@ -57,6 +60,14 @@ function getBrowserURL()
return "chrome://browser/content/browser.xul";
}
+function getBoolPref(pref, defaultValue) {
+ Deprecated.warning("getBoolPref is deprecated and will be removed in a future release. " +
+ "You should use Services.pref.getBoolPref (Services.jsm).",
+ "https://github.com/MoonchildProductions/UXP/issues/989");
+ return Services.prefs.getBoolPref(pref, defaultValue);
+}
+
+
function getTopWin(skipPopups) {
// If this is called in a browser window, use that window regardless of
// whether it's the frontmost window, since commands can be executed in
@@ -75,16 +86,6 @@ function openTopWin(url) {
openUILinkIn(url, "current");
}
-function getBoolPref(prefname, def)
-{
- try {
- return Services.prefs.getBoolPref(prefname);
- }
- catch(er) {
- return def;
- }
-}
-
/* openUILink handles clicks on UI elements that cause URLs to load.
*
* As the third argument, you may pass an object with the same properties as
@@ -151,7 +152,7 @@ function whereToOpenLink( e, ignoreButton, ignoreAlt )
// ignoreButton allows "middle-click paste" to use function without always opening in a new window.
var middle = !ignoreButton && e.button == 1;
- var middleUsesTabs = getBoolPref("browser.tabs.opentabfor.middleclick", true);
+ var middleUsesTabs = Services.prefs.getBoolPref("browser.tabs.opentabfor.middleclick", true);
// Don't do anything special with right-mouse clicks. They're probably clicks on context menu items.
@@ -162,7 +163,7 @@ function whereToOpenLink( e, ignoreButton, ignoreAlt )
#endif
return shift ? "tabshifted" : "tab";
- if (alt && getBoolPref("browser.altClickSave", false))
+ if (alt && Services.prefs.getBoolPref("browser.altClickSave", false))
return "save";
if (shift || (middle && !middleUsesTabs))
@@ -334,7 +335,7 @@ function openLinkIn(url, where, params) {
if (loadInBackground == null) {
loadInBackground = aFromChrome ?
false :
- getBoolPref("browser.tabs.loadInBackground");
+ Services.prefs.getBoolPref("browser.tabs.loadInBackground");
}
let uriObj;
@@ -515,7 +516,7 @@ function getShellService()
function isBidiEnabled() {
// first check the pref.
- if (getBoolPref("bidi.browser.ui", false))
+ if (Services.prefs.getBoolPref("bidi.browser.ui", false))
return true;
// if the pref isn't set, check for an RTL locale and force the pref to true
@@ -557,7 +558,7 @@ function checkForUpdates()
// If there's an update ready to be applied, show the "Update Downloaded"
// UI instead and let the user know they have to restart the application for
// the changes to be applied.
- if (um.activeUpdate && um.activeUpdate.state == "pending")
+ if (um.activeUpdate && ["pending", "pending-elevate", "applied"].includes(um.activeUpdate.state))
prompter.showUpdateDownloaded(um.activeUpdate);
else
prompter.checkForUpdates();
@@ -583,10 +584,16 @@ function buildHelpMenu()
var checkForUpdates = document.getElementById("checkForUpdates");
var appMenuCheckForUpdates = document.getElementById("appmenu_checkForUpdates");
var canCheckForUpdates = updates.canCheckForUpdates;
+
checkForUpdates.setAttribute("disabled", !canCheckForUpdates);
- appMenuCheckForUpdates.setAttribute("disabled", !canCheckForUpdates);
- if (!canCheckForUpdates)
+
+ if (appMenuCheckForUpdates) {
+ appMenuCheckForUpdates.setAttribute("disabled", !canCheckForUpdates);
+ }
+
+ if (!canCheckForUpdates) {
return;
+ }
var strings = document.getElementById("bundle_browser");
var activeUpdate = um.activeUpdate;
@@ -622,19 +629,31 @@ function buildHelpMenu()
}
checkForUpdates.label = getStringWithUpdateName("updatesItem_" + key);
- appMenuCheckForUpdates.label = getStringWithUpdateName("updatesItem_" + key);
+
+ if (appMenuCheckForUpdates) {
+ appMenuCheckForUpdates.label = getStringWithUpdateName("updatesItem_" + key);
+ }
+
// updatesItem_default.accesskey, updatesItem_downloading.accesskey,
// updatesItem_resume.accesskey or updatesItem_pending.accesskey
checkForUpdates.accessKey = strings.getString("updatesItem_" + key +
".accesskey");
- appMenuCheckForUpdates.accessKey = strings.getString("updatesItem_" + key +
- ".accesskey");
+
+ if (appMenuCheckForUpdates) {
+ appMenuCheckForUpdates.accessKey = strings.getString("updatesItem_" + key +
+ ".accesskey");
+ }
+
if (um.activeUpdate && updates.isDownloading) {
checkForUpdates.setAttribute("loading", "true");
- appMenuCheckForUpdates.setAttribute("loading", "true");
+ if (appMenuCheckForUpdates) {
+ appMenuCheckForUpdates.setAttribute("loading", "true");
+ }
} else {
checkForUpdates.removeAttribute("loading");
- appMenuCheckForUpdates.removeAttribute("loading");
+ if (appMenuCheckForUpdates) {
+ appMenuCheckForUpdates.removeAttribute("loading");
+ }
}
#else
#ifndef XP_MACOSX
@@ -673,7 +692,7 @@ function openAboutDialog() {
function openPreferences(paneID, extraArgs)
{
- var instantApply = getBoolPref("browser.preferences.instantApply", false);
+ var instantApply = Services.prefs.getBoolPref("browser.preferences.instantApply", false);
var features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal");
var win = Services.wm.getMostRecentWindow("Browser:Preferences");
@@ -702,6 +721,18 @@ function openAdvancedPreferences(tabID)
}
/**
+ * Opens the release notes page for this version of the application.
+ */
+function openReleaseNotes()
+{
+ var relnotesURL = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
+ .getService(Components.interfaces.nsIURLFormatter)
+ .formatURLPref("app.releaseNotesURL");
+
+ openUILinkIn(relnotesURL, "tab");
+}
+
+/**
* Opens the troubleshooting information (about:support) page for this version
* of the application.
*/
@@ -854,7 +885,7 @@ function openHelpLink(aHelpTopic, aCalledFromModal) {
function openPrefsHelp() {
// non-instant apply prefwindows are usually modal, so we can't open in the topmost window,
// since its probably behind the window.
- var instantApply = getBoolPref("browser.preferences.instantApply");
+ var instantApply = Services.prefs.getBoolPref("browser.preferences.instantApply");
var helpTopic = document.getElementsByTagName("prefwindow")[0].currentPane.helpTopic;
openHelpLink(helpTopic, !instantApply);
diff --git a/application/palemoon/base/jar.mn b/application/palemoon/base/jar.mn
index 8931c0260..735b6d0cf 100644
--- a/application/palemoon/base/jar.mn
+++ b/application/palemoon/base/jar.mn
@@ -18,9 +18,6 @@ browser.jar:
* content/browser/aboutDialog.xul (content/aboutDialog.xul)
* content/browser/aboutDialog.js (content/aboutDialog.js)
content/browser/aboutDialog.css (content/aboutDialog.css)
- content/browser/aboutRobots.xhtml (content/aboutRobots.xhtml)
- content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
- content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
content/browser/autorecovery.js (content/autorecovery.js)
content/browser/autorecovery.xul (content/autorecovery.xul)
* content/browser/browser.css (content/browser.css)
diff --git a/application/palemoon/branding/official/firefox.ico b/application/palemoon/branding/official/firefox.ico
index 33bb04e99..0f55f0ba5 100644
--- a/application/palemoon/branding/official/firefox.ico
+++ b/application/palemoon/branding/official/firefox.ico
Binary files differ
diff --git a/application/palemoon/branding/shared/pref/preferences.inc b/application/palemoon/branding/shared/pref/preferences.inc
index 8b085c417..12803f285 100644
--- a/application/palemoon/branding/shared/pref/preferences.inc
+++ b/application/palemoon/branding/shared/pref/preferences.inc
@@ -28,10 +28,6 @@ pref("app.update.promptWaitTime", 172800);
// Add-on window fixes
pref("extensions.getMoreThemesURL", "https://addons.palemoon.org/themes/");
-// Extensions Blocklist
-pref("extensions.blocklist.url","http://blocklist.palemoon.org/%VERSION%/blocklist.xml");
-pref("extensions.blocklist.itemURL", "http://blocklist.palemoon.org/info/?id=%blockID%");
-
pref("extensions.update.autoUpdateDefault", true); // Automatically update extensions by default
pref("extensions.getAddons.maxResults", 10);
pref("extensions.getAddons.cache.enabled", false);
diff --git a/application/palemoon/components/BrowserComponents.manifest b/application/palemoon/components/BrowserComponents.manifest
index b7f054eab..0ff14d066 100644
--- a/application/palemoon/components/BrowserComponents.manifest
+++ b/application/palemoon/components/BrowserComponents.manifest
@@ -10,7 +10,6 @@ contract @mozilla.org/network/protocol/about;1?what=palemoon {8cc51368-6aa0-43e8
contract @mozilla.org/network/protocol/about;1?what=permissions {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
contract @mozilla.org/network/protocol/about;1?what=privatebrowsing {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
contract @mozilla.org/network/protocol/about;1?what=rights {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
-contract @mozilla.org/network/protocol/about;1?what=robots {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
contract @mozilla.org/network/protocol/about;1?what=sessionrestore {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
#ifdef MOZ_SERVICES_SYNC
contract @mozilla.org/network/protocol/about;1?what=sync-progress {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
diff --git a/application/palemoon/components/distribution.js b/application/palemoon/components/distribution.js
index d3300604e..121e55b1b 100644
--- a/application/palemoon/components/distribution.js
+++ b/application/palemoon/components/distribution.js
@@ -38,13 +38,7 @@ DistributionCustomizer.prototype = {
},
get _locale() {
- let locale;
- try {
- locale = this._prefs.getCharPref("general.useragent.locale");
- }
- catch (e) {
- locale = "en-US";
- }
+ let locale = this._prefs.getCharPref("general.useragent.locale", "en-US");
this.__defineGetter__("_locale", function() locale);
return this._locale;
},
@@ -221,11 +215,7 @@ DistributionCustomizer.prototype = {
this._ini.getString("Global", "id") + ".bookmarksProcessed";
}
- let bmProcessed = false;
- try {
- bmProcessed = this._prefs.getBoolPref(bmProcessedPref);
- }
- catch (e) {}
+ let bmProcessed = this._prefs.getBoolPref(bmProcessedPref, false);
if (!bmProcessed) {
if (sections["BookmarksMenu"])
diff --git a/application/palemoon/components/feeds/FeedWriter.js b/application/palemoon/components/feeds/FeedWriter.js
index d704835bb..facde5815 100644
--- a/application/palemoon/components/feeds/FeedWriter.js
+++ b/application/palemoon/components/feeds/FeedWriter.js
@@ -18,12 +18,7 @@ function LOG(str) {
var prefB = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
- var shouldLog = false;
- try {
- shouldLog = prefB.getBoolPref("feeds.log");
- }
- catch (ex) {
- }
+ var shouldLog = prefB.getBoolPref("feeds.log", false);
if (shouldLog)
dump("*** Feeds: " + str + "\n");
@@ -874,11 +869,7 @@ FeedWriter.prototype = {
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
- var handler = "bookmarks";
- try {
- handler = prefs.getCharPref(getPrefReaderForType(feedType));
- }
- catch (ex) { }
+ var handler = prefs.getCharPref(getPrefReaderForType(feedType), "bookmarks");
switch (handler) {
case "web": {
@@ -1076,11 +1067,7 @@ FeedWriter.prototype = {
.addEventListener("command", this, false);
// first-run ui
- var showFirstRunUI = true;
- try {
- showFirstRunUI = prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI);
- }
- catch (ex) { }
+ var showFirstRunUI = prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI, true);
if (showFirstRunUI) {
var textfeedinfo1, textfeedinfo2;
switch (feedType) {
diff --git a/application/palemoon/components/feeds/WebContentConverter.js b/application/palemoon/components/feeds/WebContentConverter.js
index 41679b028..42e2edee0 100644
--- a/application/palemoon/components/feeds/WebContentConverter.js
+++ b/application/palemoon/components/feeds/WebContentConverter.js
@@ -436,13 +436,8 @@ WebContentConverterRegistrar.prototype = {
// check if it is in the black list
var pb = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
- var allowed;
- try {
- allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "." + aProtocol);
- }
- catch (e) {
- allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "-default");
- }
+ var allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "." + aProtocol,
+ pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "-default"));
if (!allowed) {
// XXX this should be a "security exception" according to spec
throw("Not allowed to register a protocol handler for " + aProtocol);
diff --git a/application/palemoon/components/fuel/fuelApplication.js b/application/palemoon/components/fuel/fuelApplication.js
index 017813143..bc3a091ea 100644
--- a/application/palemoon/components/fuel/fuelApplication.js
+++ b/application/palemoon/components/fuel/fuelApplication.js
@@ -6,6 +6,8 @@ const Ci = Components.interfaces;
const Cc = Components.classes;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
+ "resource://gre/modules/Deprecated.jsm");
const APPLICATION_CID = Components.ID("fe74cf80-aa2d-11db-abbd-0800200c9a66");
const APPLICATION_CONTRACTID = "@mozilla.org/fuel/application;1";
@@ -734,6 +736,8 @@ var ApplicationFactory = {
//=================================================
// Application constructor
function Application() {
+ Deprecated.warning("FUEL is deprecated, you should use the standard Toolkit API instead.",
+ "https://github.com/MoonchildProductions/UXP/issues/1083");
this.initToolkitHelpers();
}
diff --git a/application/palemoon/components/newtab/grid.js b/application/palemoon/components/newtab/grid.js
index db3d319c3..e63ea54a6 100644
--- a/application/palemoon/components/newtab/grid.js
+++ b/application/palemoon/components/newtab/grid.js
@@ -130,13 +130,9 @@ var gGrid = {
// Create sites.
let numLinks = Math.min(links.length, cells.length);
- let hasHistoryTiles = false;
for (let i = 0; i < numLinks; i++) {
if (links[i]) {
this.createSite(links[i], cells[i]);
- if (links[i].type == "history") {
- hasHistoryTiles = true;
- }
}
}
diff --git a/application/palemoon/components/newtab/page.js b/application/palemoon/components/newtab/page.js
index 7117d4527..34387fd44 100644
--- a/application/palemoon/components/newtab/page.js
+++ b/application/palemoon/components/newtab/page.js
@@ -47,11 +47,6 @@ var gPage = {
let enabled = gAllPages.enabled;
this._updateAttributes(enabled);
- // Update thumbnails to the new enhanced setting
- if (aData == "browser.newtabpage.enhanced") {
- this.update();
- }
-
// Initialize the whole page if we haven't done that, yet.
if (enabled) {
this._init();
@@ -166,16 +161,6 @@ var gPage = {
*/
_handleUnloadEvent: function Page_handleUnloadEvent() {
gAllPages.unregister(this);
- // compute page life-span and send telemetry probe: using milli-seconds will leave
- // many low buckets empty. Instead we use half-second precision to make low end
- // of histogram linear and not lose the change in user attention
- let delta = Math.round((Date.now() - this._firstVisibleTime) / 500);
- if (this._suggestedTilePresent) {
- Services.telemetry.getHistogramById("NEWTAB_PAGE_LIFE_SPAN_SUGGESTED").add(delta);
- }
- else {
- Services.telemetry.getHistogramById("NEWTAB_PAGE_LIFE_SPAN").add(delta);
- }
},
/**
@@ -250,43 +235,10 @@ var gPage = {
},
onPageVisibleAndLoaded() {
- // Send the index of the last visible tile.
- this.reportLastVisibleTileIndex();
- // Maybe tell the user they can undo an initial automigration
- this.maybeShowAutoMigrationUndoNotification();
- },
-
- reportLastVisibleTileIndex() {
- let cwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
-
- let rect = cwu.getBoundsWithoutFlushing(gGrid.node);
- let nodes = cwu.nodesFromRect(rect.left, rect.top, 0, rect.width,
- rect.height, 0, true, false);
-
- let i = -1;
- let lastIndex = -1;
- let sites = gGrid.sites;
-
- for (let node of nodes) {
- if (node.classList && node.classList.contains("newtab-cell")) {
- if (sites[++i]) {
- lastIndex = i;
- if (sites[i].link.targetedSite) {
- // record that suggested tile is shown to use suggested-tiles-histogram
- this._suggestedTilePresent = true;
- }
- }
- }
- }
},
toggleEnabled: function(aEvent) {
gAllPages.enabled = !gAllPages.enabled;
- event.stopPropagation();
- },
-
- maybeShowAutoMigrationUndoNotification() {
- // sendAsyncMessage("NewTab:MaybeShowAutoMigrationUndoNotification");
- },
+ aEvent.stopPropagation();
+ }
};
diff --git a/application/palemoon/components/newtab/sites.js b/application/palemoon/components/newtab/sites.js
index a368146bb..cb5675238 100644
--- a/application/palemoon/components/newtab/sites.js
+++ b/application/palemoon/components/newtab/sites.js
@@ -136,15 +136,6 @@ Site.prototype = {
return str;
},
- _getSuggestedTileExplanation: function() {
- let targetedName = `<strong> ${this.link.targetedName} </strong>`;
- let targetedSite = `<strong> ${this.link.targetedSite} </strong>`;
- if (this.link.explanation) {
- return this._newTabString(this.link.explanation, [targetedName, targetedSite]);
- }
- return newTabString("suggested.button", [targetedName]);
- },
-
/**
* Checks for and modifies link at campaign end time
*/
@@ -155,11 +146,8 @@ Site.prototype = {
this.link.url = Services.io.newURI(this.url, null, null).resolve("/");
// clear supplied images - this triggers thumbnail download for new url
delete this.link.imageURI;
- delete this.link.enhancedImageURI;
// remove endTime to avoid further time checks
delete this.link.endTime;
- // clear enhanced-content image that may still exist in preloaded page
- this._querySelector(".enhanced-content").style.backgroundImage = "";
gPinnedLinks.replace(oldUrl, this.link);
}
},
@@ -337,7 +325,7 @@ Site.prototype = {
}
else if (!pinned && target.classList.contains("newtab-control-pin")) {
if (this.pin()) {
- // suggested link has changed - update rest of the pages
+ // link has changed - update rest of the pages
gAllPages.update(gPage);
}
action = "pin";
diff --git a/application/palemoon/components/nsAboutRedirector.js b/application/palemoon/components/nsAboutRedirector.js
index 9c7d7953f..4d99a78f5 100644
--- a/application/palemoon/components/nsAboutRedirector.js
+++ b/application/palemoon/components/nsAboutRedirector.js
@@ -61,10 +61,6 @@ AboutRedirector.prototype = {
url: "chrome://global/content/aboutRights.xhtml",
flags: (URI_SAFE_FOR_UNTRUSTED_CONTENT | MAKE_LINKABLE | ALLOW_SCRIPT)
},
- "robots": {
- url: "chrome://browser/content/aboutRobots.xhtml",
- flags: (URI_SAFE_FOR_UNTRUSTED_CONTENT | ALLOW_SCRIPT | HIDE_FROM_ABOUTABOUT)
- },
"sessionrestore": {
url: "chrome://browser/content/aboutSessionRestore.xhtml",
flags: ALLOW_SCRIPT
diff --git a/application/palemoon/components/nsBrowserContentHandler.js b/application/palemoon/components/nsBrowserContentHandler.js
index 6a75b40f2..e7f1414c2 100644
--- a/application/palemoon/components/nsBrowserContentHandler.js
+++ b/application/palemoon/components/nsBrowserContentHandler.js
@@ -100,20 +100,14 @@ const OVERRIDE_NEW_BUILD_ID = 3;
* OVERRIDE_NONE otherwise.
*/
function needHomepageOverride(prefb) {
- var savedmstone = null;
- try {
- savedmstone = prefb.getCharPref("browser.startup.homepage_override.mstone");
- } catch (e) {}
+ var savedmstone = prefb.getCharPref("browser.startup.homepage_override.mstone", "");
if (savedmstone == "ignore")
return OVERRIDE_NONE;
var mstone = Services.appinfo.platformVersion;
- var savedBuildID = null;
- try {
- savedBuildID = prefb.getCharPref("browser.startup.homepage_override.buildID");
- } catch (e) {}
+ var savedBuildID = prefb.getCharPref("browser.startup.homepage_override.buildID", "");
var buildID = Services.appinfo.platformBuildID;
@@ -550,10 +544,7 @@ nsBrowserContentHandler.prototype = {
// URL if we do end up showing an overridePage. This makes it possible
// to have the overridePage's content vary depending on the version we're
// upgrading from.
- let old_mstone = "unknown";
- try {
- old_mstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone");
- } catch (ex) {}
+ let old_mstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone", "unknown");
let override = needHomepageOverride(prefb);
if (override != OVERRIDE_NONE) {
switch (override) {
diff --git a/application/palemoon/components/nsBrowserGlue.js b/application/palemoon/components/nsBrowserGlue.js
index ad48dab29..01a133833 100644
--- a/application/palemoon/components/nsBrowserGlue.js
+++ b/application/palemoon/components/nsBrowserGlue.js
@@ -990,14 +990,8 @@ BrowserGlue.prototype = {
// An import operation is about to run.
// Don't try to recreate smart bookmarks if autoExportHTML is true or
// smart bookmarks are disabled.
- var autoExportHTML = false;
- try {
- autoExportHTML = Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML");
- } catch(ex) {}
- var smartBookmarksVersion = 0;
- try {
- smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion");
- } catch(ex) {}
+ var autoExportHTML = Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML", false);
+ var smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion", 0);
if (!autoExportHTML && smartBookmarksVersion != -1)
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
@@ -1556,10 +1550,7 @@ BrowserGlue.prototype = {
const MAX_RESULTS = 10;
// Get current smart bookmarks version. If not set, create them.
- let smartBookmarksCurrentVersion = 0;
- try {
- smartBookmarksCurrentVersion = Services.prefs.getIntPref(SMART_BOOKMARKS_PREF);
- } catch(ex) {}
+ let smartBookmarksCurrentVersion = Services.prefs.getIntPref(SMART_BOOKMARKS_PREF, 0);
// If version is current or smart bookmarks are disabled, just bail out.
if (smartBookmarksCurrentVersion == -1 ||
diff --git a/application/palemoon/components/places/PlacesUIUtils.jsm b/application/palemoon/components/places/PlacesUIUtils.jsm
index 05d79241c..e3a9e1322 100644
--- a/application/palemoon/components/places/PlacesUIUtils.jsm
+++ b/application/palemoon/components/places/PlacesUIUtils.jsm
@@ -1170,11 +1170,8 @@ this.PlacesUIUtils = {
* @return The URL with the fragment at the end
*/
getImageURLForResolution:
- function PUIU_getImageURLForResolution(aWindow, aURL, aWidth = 16, aHeight = 16) {
- let width = Math.round(aWidth * aWindow.devicePixelRatio);
- let height = Math.round(aHeight * aWindow.devicePixelRatio);
- return aURL + (aURL.includes("#") ? "&" : "#") +
- "-moz-resolution=" + width + "," + height;
+ function PUIU_getImageURLForResolution(aWindow, aURL, aWidth, aHeight) {
+ return aURL;
}
};
diff --git a/application/palemoon/components/preferences/newtaburl.js b/application/palemoon/components/preferences/newtaburl.js
index ac0eec1c5..3c82df846 100644
--- a/application/palemoon/components/preferences/newtaburl.js
+++ b/application/palemoon/components/preferences/newtaburl.js
@@ -22,7 +22,11 @@ var gNewtabUrl = {
return;
}
} else {
- newtabUrlChoice = Services.prefs.getIntPref("browser.newtab.choice");
+ if (this.newtabUrlChoiceIsSet) {
+ newtabUrlChoice = Services.prefs.getIntPref("browser.newtab.choice");
+ } else {
+ newtabUrlChoice = this.getNewtabChoice();
+ }
}
if (browserHomepageUrl || browserHomepageUrl == "") {
if (Services.prefs.getBoolPref("browser.preferences.instantApply")) {
@@ -64,5 +68,35 @@ var gNewtabUrl = {
}
Services.prefs.setCharPref("browser.newtab.url",newtabUrlPref);
} catch(e) { console.error(e); }
+ },
+
+ /**
+ * Determines the value of browser.newtab.choice based
+ * on the value of browser.newtab.url
+ *
+ * @returns the value of browser.newtab.choice
+ */
+ getNewtabChoice: function() {
+ let newtabUrlPref = Services.prefs.getCharPref("browser.newtab.url");
+ let browserHomepageUrl = Services.prefs.getComplexValue("browser.startup.homepage",
+ Components.interfaces.nsIPrefLocalizedString).data;
+ let newtabUrlSanitizedPref = browserHomepageUrl.split("|")[0];
+ let defaultStartupHomepage = Services.prefs.getDefaultBranch("browser.")
+ .getComplexValue("startup.homepage",
+ Components.interfaces.nsIPrefLocalizedString).data;
+ switch (newtabUrlPref) {
+ case "about:logopage":
+ return 1;
+ case defaultStartupHomepage:
+ return 2;
+ case newtabUrlSanitizedPref:
+ return 3;
+ case "about:newtab":
+ return 4;
+ default: // Custom URL entered.
+ // We need this to consider instantApply.
+ this.newtabPageCustom = newtabUrlPref;
+ return 0;
+ }
}
};
diff --git a/application/palemoon/components/preferences/preferences.xul b/application/palemoon/components/preferences/preferences.xul
index 2b7fd9ded..a1d9c8cf7 100644
--- a/application/palemoon/components/preferences/preferences.xul
+++ b/application/palemoon/components/preferences/preferences.xul
@@ -56,7 +56,7 @@
#endif
#endif
onunload="if (typeof gSecurityPane != 'undefined') gSecurityPane.syncAddonSecurityLevel();"
- ondialogaccept="if (typeof gTabsPane != 'undefined') gNewtabUrl.writeNewtabUrl();">
+ ondialogaccept="gNewtabUrl.writeNewtabUrl();">
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript" src="chrome://browser/content/preferences/newtaburl.js"/>
diff --git a/application/palemoon/components/preferences/tabs.js b/application/palemoon/components/preferences/tabs.js
index 17084a770..b09cb60df 100644
--- a/application/palemoon/components/preferences/tabs.js
+++ b/application/palemoon/components/preferences/tabs.js
@@ -78,34 +78,13 @@ var gTabsPane = {
/**
* Determines the value of the New Tab display drop-down based
* on the value of browser.newtab.url.
- *
- * @returns the appropriate value of browser.newtab.choice
*/
readNewtabUrl: function() {
- let newtabUrlPref = document.getElementById("browser.newtab.url");
- let newtabUrlSanitizedPref = document.getElementById("browser.newtab.myhome");
let newtabUrlChoice = document.getElementById("browser.newtab.choice");
- let defaultStartupHomepage = Services.prefs.getDefaultBranch("browser.")
- .getComplexValue("startup.homepage",
- Components.interfaces.nsIPrefLocalizedString).data;
- switch (newtabUrlPref.value) {
- case "about:logopage":
- newtabUrlChoice.value = 1;
- break;
- case defaultStartupHomepage:
- newtabUrlChoice.value = 2;
- break;
- case newtabUrlSanitizedPref.value:
- newtabUrlChoice.value = 3;
- break;
- case "about:newtab":
- newtabUrlChoice.value = 4;
- break;
- default: // Custom URL entered.
- document.getElementById("newtabPageCustom").hidden = false;
- newtabUrlChoice.value = 0;
- // We need this to consider instantApply.
- this.newtabPageCustom = newtabUrlPref.value;
+ newtabUrlChoice.value = gNewtabUrl.getNewtabChoice();
+ if (newtabUrlChoice.value == 0) {
+ document.getElementById("newtabPageCustom").hidden = false;
}
+ gNewtabUrl.newtabUrlChoiceIsSet = true;
}
};
diff --git a/application/palemoon/components/search/content/search.xml b/application/palemoon/components/search/content/search.xml
index 4532f5720..0c33b1527 100644
--- a/application/palemoon/components/search/content/search.xml
+++ b/application/palemoon/components/search/content/search.xml
@@ -283,11 +283,6 @@
<parameter name="element"/>
<parameter name="uri"/>
<body><![CDATA[
- if (uri) {
- let size = Math.round(16 * window.devicePixelRatio);
- if (!uri.includes("#"))
- uri += "#-moz-resolution=" + size + "," + size;
- }
element.setAttribute("src", uri);
]]></body>
</method>
diff --git a/application/palemoon/config/version.txt b/application/palemoon/config/version.txt
index dc6d77132..bcbf0fd12 100644
--- a/application/palemoon/config/version.txt
+++ b/application/palemoon/config/version.txt
@@ -1 +1 @@
-28.5.0a1 \ No newline at end of file
+28.6.0a1 \ No newline at end of file
diff --git a/application/palemoon/configure.in b/application/palemoon/configure.in
index 96f63781e..eb02af3c0 100644
--- a/application/palemoon/configure.in
+++ b/application/palemoon/configure.in
@@ -36,7 +36,3 @@ MOZ_ARG_DISABLE_BOOL(sync,
MOZ_SERVICES_SYNC=,
MOZ_SERVICES_SYNC=1)
-if test -z "$MOZ_SERVICES_SYNC"; then
- MOZ_SERVICES_CLOUDSYNC=
-fi
-
diff --git a/application/palemoon/fonts/TwemojiMozilla.ttf b/application/palemoon/fonts/TwemojiMozilla.ttf
index 8139089f1..c47cbbf11 100644
--- a/application/palemoon/fonts/TwemojiMozilla.ttf
+++ b/application/palemoon/fonts/TwemojiMozilla.ttf
Binary files differ
diff --git a/application/palemoon/installer/package-manifest.in b/application/palemoon/installer/package-manifest.in
index 1247d3171..0d80e15f9 100644
--- a/application/palemoon/installer/package-manifest.in
+++ b/application/palemoon/installer/package-manifest.in
@@ -231,6 +231,7 @@
; [Default Preferences]
; All the pref files must be part of base to prevent migration bugs
+@RESPATH@/browser/defaults/permissions
@RESPATH@/browser/@PREF_DIR@/palemoon.js
@RESPATH@/browser/@PREF_DIR@/palemoon-branding.js
@RESPATH@/greprefs.js
@@ -318,13 +319,6 @@
@RESPATH@/chrome/pippki@JAREXT@
@RESPATH@/chrome/pippki.manifest
-; for Solaris SPARC
-#ifdef SOLARIS
-bin/libfreebl_32fpu_3.so
-bin/libfreebl_32int_3.so
-bin/libfreebl_32int64_3.so
-#endif
-
; [Updater]
;
#ifdef MOZ_UPDATER
diff --git a/application/palemoon/installer/windows/nsis/installer.nsi b/application/palemoon/installer/windows/nsis/installer.nsi
index 50bab5586..9216bb6e1 100644
--- a/application/palemoon/installer/windows/nsis/installer.nsi
+++ b/application/palemoon/installer/windows/nsis/installer.nsi
@@ -1080,7 +1080,6 @@ Function .onInit
!insertmacro InitInstallOptionsFile "options.ini"
!insertmacro InitInstallOptionsFile "shortcuts.ini"
- !insertmacro InitInstallOptionsFile "components.ini"
!insertmacro InitInstallOptionsFile "summary.ini"
WriteINIStr "$PLUGINSDIR\options.ini" "Settings" NumFields "5"
@@ -1155,36 +1154,6 @@ Function .onInit
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Bottom "50"
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" State "1"
- ; Don't offer to install the quick launch shortcut on Windows 7
- ${Unless} ${AtLeastWin7}
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Type "checkbox"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Text "$(ICONS_QUICKLAUNCH)"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Left "0"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Right "-1"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Top "60"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Bottom "70"
- WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" State "1"
- ${EndUnless}
-
- ; Setup the components.ini file for the Components Page
- WriteINIStr "$PLUGINSDIR\components.ini" "Settings" NumFields "2"
-
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Type "label"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Text "$(OPTIONAL_COMPONENTS_DESC)"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Left "0"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Right "-1"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Top "5"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Bottom "25"
-
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Type "checkbox"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Text "$(MAINTENANCE_SERVICE_CHECKBOX_DESC)"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Left "0"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Right "-1"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Top "27"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Bottom "37"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" State "1"
- WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Flags "GROUP"
-
; There must always be a core directory.
${GetSize} "$EXEDIR\core\" "/S=0K" $R5 $R7 $R8
SectionSetSize ${APP_IDX} $R5
diff --git a/application/palemoon/locales/en-US/chrome/browser-region/region.properties b/application/palemoon/locales/en-US/chrome/browser-region/region.properties
index ad6c1342f..8782ae46f 100644
--- a/application/palemoon/locales/en-US/chrome/browser-region/region.properties
+++ b/application/palemoon/locales/en-US/chrome/browser-region/region.properties
@@ -14,29 +14,25 @@ browser.search.order.4=Ecosia
# This is the default set of web based feed handlers shown in the reader
# selection UI
browser.contentHandlers.types.0.title=My Yahoo!
-browser.contentHandlers.types.0.uri=http://add.my.yahoo.com/rss?url=%s
+browser.contentHandlers.types.0.uri=https://add.my.yahoo.com/rss?url=%s
# increment this number when anything gets changed in the list below. This will
# cause Firefox to re-read these prefs and inject any new handlers into the
# profile database. Note that "new" is defined as "has a different URL"; this
# means that it's not possible to update the name of existing handler, so
# don't make any spelling errors here.
-goanna.handlerService.defaultHandlersVersion=3
-
-# The default set of protocol handlers for webcal:
-goanna.handlerService.schemes.webcal.0.name=30 Boxes
-goanna.handlerService.schemes.webcal.0.uriTemplate=http://30boxes.com/external/widget?refer=ff&url=%s
+gecko.handlerService.defaultHandlersVersion=5
# The default set of protocol handlers for mailto:
-goanna.handlerService.schemes.mailto.0.name=Yahoo! Mail
-goanna.handlerService.schemes.mailto.0.uriTemplate=https://compose.mail.yahoo.com/?To=%s
-goanna.handlerService.schemes.mailto.1.name=Gmail
-goanna.handlerService.schemes.mailto.1.uriTemplate=https://mail.google.com/mail/?extsrc=mailto&url=%s
+gecko.handlerService.schemes.mailto.0.name=Yahoo! Mail
+gecko.handlerService.schemes.mailto.0.uriTemplate=https://compose.mail.yahoo.com/?To=%s
+gecko.handlerService.schemes.mailto.1.name=Gmail
+gecko.handlerService.schemes.mailto.1.uriTemplate=https://mail.google.com/mail/?extsrc=mailto&url=%s
# The default set of protocol handlers for irc:
-goanna.handlerService.schemes.irc.0.name=Mibbit
-goanna.handlerService.schemes.irc.0.uriTemplate=https://www.mibbit.com/?url=%s
+gecko.handlerService.schemes.irc.0.name=Mibbit
+gecko.handlerService.schemes.irc.0.uriTemplate=https://www.mibbit.com/?url=%s
# The default set of protocol handlers for ircs:
-goanna.handlerService.schemes.ircs.0.name=Mibbit
-goanna.handlerService.schemes.ircs.0.uriTemplate=https://www.mibbit.com/?url=%s
+gecko.handlerService.schemes.ircs.0.name=Mibbit
+gecko.handlerService.schemes.ircs.0.uriTemplate=https://www.mibbit.com/?url=%s
diff --git a/application/palemoon/locales/en-US/chrome/browser/aboutRobots.dtd b/application/palemoon/locales/en-US/chrome/browser/aboutRobots.dtd
deleted file mode 100644
index 139603d8d..000000000
--- a/application/palemoon/locales/en-US/chrome/browser/aboutRobots.dtd
+++ /dev/null
@@ -1,29 +0,0 @@
-<!-- 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/. -->
-
-<!-- These strings are used in the about:robots page, which ties in with the
- robots theme used in the Firefox 3 Beta 2/3 first run pages.
- They're just meant to be fun and whimsical, with references to some geeky
- but well-known robots in movies and books. Be creative with translations! -->
-
-<!-- Nonsense line from the movie "The Day The Earth Stood Still". No translation needed. -->
-<!ENTITY robots.pagetitle "Gort! Klaatu barada nikto!">
-<!-- Movie: Logan's Run... Box (cybog): "Welcome Humans! I am ready for you." -->
-<!ENTITY robots.errorTitleText "Welcome Humans!">
-<!-- Movie: The Day The Earth Stood Still. Spoken by Klaatu. -->
-<!ENTITY robots.errorShortDescText "We have come to visit you in peace and with goodwill!">
-<!-- Various books by Isaac Asimov. http://en.wikipedia.org/wiki/Three_Laws_of_Robotics -->
-<!ENTITY robots.errorLongDesc1 "Robots may not injure a human being or, through inaction, allow a human being to come to harm.">
-<!-- Movie: Blade Runner. Batty: "I've seen things you people wouldn't believe..." -->
-<!ENTITY robots.errorLongDesc2 "Robots have seen things you people wouldn't believe.">
-<!-- Book: Hitchhiker's Guide To The Galaxy. What the Sirius Cybernetics Corporation calls robots. -->
-<!ENTITY robots.errorLongDesc3 "Robots are Your Plastic Pal Who's Fun To Be With.">
-<!-- TV: Futurama. Bender's first line is "Bite my shiny metal ass." -->
-<!ENTITY robots.errorLongDesc4 "Robots have shiny metal posteriors which should not be bitten.">
-<!-- TV: Battlestar Galactica (2004 series). From the opening text. -->
-<!ENTITY robots.errorTrailerDescText "And they have a plan.">
-<!-- TV: Battlestar Galactica (2004 series). Common expletive referring to Cylons. -->
-<!ENTITY robots.imgtitle "Frakkin' Toasters">
-<!-- Book: Hitchhiker's Guide To The Galaxy. Arthur presses a button and it warns him. -->
-<!ENTITY robots.dontpress "Please do not press this button again.">
diff --git a/application/palemoon/locales/en-US/chrome/browser/baseMenuOverlay.dtd b/application/palemoon/locales/en-US/chrome/browser/baseMenuOverlay.dtd
index 27de3797f..dd88a3384 100644
--- a/application/palemoon/locales/en-US/chrome/browser/baseMenuOverlay.dtd
+++ b/application/palemoon/locales/en-US/chrome/browser/baseMenuOverlay.dtd
@@ -15,6 +15,8 @@
<!ENTITY helpMenuWin.label "Help">
<!ENTITY helpMenuWin.accesskey "H">
<!ENTITY updateCmd.label "Check for Updates…">
+<!ENTITY helpReleaseNotes.label "Release Notes">
+<!ENTITY helpReleaseNotes.accesskey "N">
<!ENTITY aboutProduct.label "About &brandShortName;">
<!ENTITY aboutProduct.accesskey "A">
<!ENTITY productHelp.label "&brandShortName; Help">
diff --git a/application/palemoon/locales/en-US/chrome/browser/palemoon.dtd b/application/palemoon/locales/en-US/chrome/browser/palemoon.dtd
index 038d8eb75..4b4fac9ff 100644
--- a/application/palemoon/locales/en-US/chrome/browser/palemoon.dtd
+++ b/application/palemoon/locales/en-US/chrome/browser/palemoon.dtd
@@ -2,13 +2,14 @@
- 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/. -->
-<!ENTITY chronicles.title.55.2
-'The Chronicles of the Pale Moon, 55:2'>
+<!ENTITY chronicles.title.66.1
+'The Chronicles of the Pale Moon, 66:1'>
-<!ENTITY chronicles.quote.55.2
-'And so, our focus was drawn through time and space to the <em>emerging dragon</em> who would not abandon hope.<br/>
-Its resilience, stubbornness and spirit unbroken, and searching for long hours to find those willing to <em>join</em> its cause.<br/>
-The old nest abandoned, the death throes of the Beast ignored, and more determined than ever to find glory in the future.'>
+<!ENTITY chronicles.quote.66.1
+'The <em>landscape changed</em> as time went on: flowing, twisting, corrupting. The dull sheen of <em>tainted metal</em> shining through everywhere.<br/>
+In the trees, roots, animals, and even the <em>mountainous valleys</em> that had always been an <em>oasis of difference</em>.<br/>
+Still, our dragon continued, untainted and resolute, soaring above.<br/>
+There would be a home yet, <em>a sanctuary</em>, a place for all those not given in to this <em>singular</em> invading force that was <em>misshaping</em> the world.'>
-<!ENTITY chronicles.from.55.2
-'from <strong>The Chronicles of the Pale Moon,</strong> 55:2'>
+<!ENTITY chronicles.from.66.1
+'from <strong>The Chronicles of the Pale Moon,</strong> 66:1'>
diff --git a/application/palemoon/locales/jar.mn b/application/palemoon/locales/jar.mn
index 0fc7f2c9b..5fcee246e 100644
--- a/application/palemoon/locales/jar.mn
+++ b/application/palemoon/locales/jar.mn
@@ -9,7 +9,6 @@
locale/browser/aboutCertError.dtd (%chrome/browser/aboutCertError.dtd)
locale/browser/aboutDialog.dtd (%chrome/browser/aboutDialog.dtd)
locale/browser/aboutPrivateBrowsing.dtd (%chrome/browser/aboutPrivateBrowsing.dtd)
- locale/browser/aboutRobots.dtd (%chrome/browser/aboutRobots.dtd)
* locale/browser/aboutHome.dtd (%chrome/browser/aboutHome.dtd)
locale/browser/aboutSessionRestore.dtd (%chrome/browser/aboutSessionRestore.dtd)
#ifdef MOZ_SERVICES_SYNC
diff --git a/application/palemoon/themes/linux/browser.css b/application/palemoon/themes/linux/browser.css
index 933067c2b..4933b4069 100644
--- a/application/palemoon/themes/linux/browser.css
+++ b/application/palemoon/themes/linux/browser.css
@@ -1608,7 +1608,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
}
/* When the tab bar is collapsed, show a 1px border in its place. */
-#TabsToolbar[collapsed="true"] {
+#TabsToolbar[tabsontop="false"][collapsed="true"]:not([customizing="true"]) {
visibility: visible;
height: 1px;
border-bottom-width: 1px;
diff --git a/application/palemoon/themes/osx/browser.css b/application/palemoon/themes/osx/browser.css
index 20e8c5eac..20e453d11 100644
--- a/application/palemoon/themes/osx/browser.css
+++ b/application/palemoon/themes/osx/browser.css
@@ -1631,7 +1631,7 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
}
/* When the tab bar is collapsed, show a 1px border in its place. */
-#TabsToolbar[collapsed="true"] {
+#TabsToolbar[tabsontop="false"][collapsed="true"]:not([customizing="true"]) {
visibility: visible;
height: 1px;
border-bottom-width: 1px;
diff --git a/application/palemoon/themes/windows/browser.css b/application/palemoon/themes/windows/browser.css
index aae36c539..88c3087ae 100644
--- a/application/palemoon/themes/windows/browser.css
+++ b/application/palemoon/themes/windows/browser.css
@@ -1844,7 +1844,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
}
/* When the tab bar is collapsed, show a 1px border in its place. */
-#TabsToolbar[collapsed="true"] {
+#TabsToolbar[tabsontop="false"][collapsed="true"]:not([customizing="true"]) {
visibility: visible;
height: 1px;
border-bottom-width: 1px;