diff --git a/browser/base/content/browser-trackingprotection.js b/browser/base/content/browser-trackingprotection.js new file mode 100644 index 000000000000..bc02c1fbdf99 --- /dev/null +++ b/browser/base/content/browser-trackingprotection.js @@ -0,0 +1,96 @@ +# 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/. + +let TrackingProtection = { + PREF_ENABLED: "privacy.trackingprotection.enabled", + + init() { + let $ = selector => document.querySelector(selector); + this.container = $("#tracking-protection-container"); + this.content = $("#tracking-protection-content"); + + this.updateEnabled(); + Services.prefs.addObserver(this.PREF_ENABLED, this, false); + + this.enabledHistogram.add(this.enabled); + }, + + uninit() { + Services.prefs.removeObserver(this.PREF_ENABLED, this); + }, + + observe() { + this.updateEnabled(); + }, + + updateEnabled() { + this.enabled = Services.prefs.getBoolPref(this.PREF_ENABLED); + this.container.hidden = !this.enabled; + }, + + get enabledHistogram() { + return Services.telemetry.getHistogramById("TRACKING_PROTECTION_ENABLED"); + }, + + get eventsHistogram() { + return Services.telemetry.getHistogramById("TRACKING_PROTECTION_EVENTS"); + }, + + onSecurityChange(state) { + if (!this.enabled) { + return; + } + + let { + STATE_BLOCKED_TRACKING_CONTENT, STATE_LOADED_TRACKING_CONTENT + } = Ci.nsIWebProgressListener; + + if (state & STATE_BLOCKED_TRACKING_CONTENT) { + this.content.setAttribute("block-active", true); + this.content.removeAttribute("block-disabled"); + } else if (state & STATE_LOADED_TRACKING_CONTENT) { + this.content.setAttribute("block-disabled", true); + this.content.removeAttribute("block-active"); + } else { + this.content.removeAttribute("block-disabled"); + this.content.removeAttribute("block-active"); + } + + // Telemetry for state change. + this.eventsHistogram.add(0); + }, + + disableForCurrentPage() { + // Convert document URI into the format used by + // nsChannelClassifier::ShouldEnableTrackingProtection. + // Any scheme turned into https is correct. + let normalizedUrl = Services.io.newURI( + "https://" + gBrowser.selectedBrowser.currentURI.hostPort, + null, null); + + // Add the current host in the 'trackingprotection' consumer of + // the permission manager using a normalized URI. This effectively + // places this host on the tracking protection allowlist. + Services.perms.add(normalizedUrl, + "trackingprotection", Services.perms.ALLOW_ACTION); + + // Telemetry for disable protection. + this.eventsHistogram.add(1); + + BrowserReload(); + }, + + enableForCurrentPage() { + // Remove the current host from the 'trackingprotection' consumer + // of the permission manager. This effectively removes this host + // from the tracking protection allowlist. + Services.perms.remove(gBrowser.selectedBrowser.currentURI.host, + "trackingprotection"); + + // Telemetry for enable protection. + this.eventsHistogram.add(2); + + BrowserReload(); + }, +}; diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 7f4d699cb0a7..0d79962b725e 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -280,6 +280,7 @@ let gInitialPages = [ #include browser-social.js #include browser-tabview.js #include browser-thumbnails.js +#include browser-trackingprotection.js #ifdef MOZ_DATA_REPORTING #include browser-data-submission-info-bar.js @@ -964,6 +965,7 @@ var gBrowserInit = { BrowserOnClick.init(); DevEdition.init(); AboutPrivateBrowsingListener.init(); + TrackingProtection.init(); let mm = window.getGroupMessageManager("browsers"); mm.loadFrameScript("chrome://browser/content/tab-content.js", true); @@ -1446,12 +1448,6 @@ var gBrowserInit = { } }, 5000); - // Telemetry for tracking protection. - let tpEnabled = gPrefService - .getBoolPref("privacy.trackingprotection.enabled"); - Services.telemetry.getHistogramById("TRACKING_PROTECTION_ENABLED") - .add(tpEnabled); - PanicButtonNotifier.init(); }); this.delayedStartupFinished = true; @@ -1534,6 +1530,8 @@ var gBrowserInit = { DevEdition.uninit(); + TrackingProtection.uninit(); + gMenuButtonUpdateBadge.uninit(); ReadingListUI.uninit(); @@ -4383,6 +4381,7 @@ var XULBrowserWindow = { uri = Services.uriFixup.createExposableURI(uri); } catch (e) {} gIdentityHandler.checkIdentity(this._state, uri); + TrackingProtection.onSecurityChange(this._state); }, // simulate all change notifications after switching tabs @@ -6781,7 +6780,7 @@ var gIdentityHandler = { nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT | nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT)) { this.showBadContentDoorhanger(state); - } else if (gPrefService.getBoolPref("privacy.trackingprotection.enabled")) { + } else if (TrackingProtection.enabled) { // We didn't show the shield Services.telemetry.getHistogramById("TRACKING_PROTECTION_SHIELD") .add(0); diff --git a/browser/base/content/test/general/browser_trackingUI_1.js b/browser/base/content/test/general/browser_trackingUI_1.js index 00555c9c549f..9c67f39c9e85 100644 --- a/browser/base/content/test/general/browser_trackingUI_1.js +++ b/browser/base/content/test/general/browser_trackingUI_1.js @@ -2,118 +2,100 @@ * 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/. */ -// Test that the Tracking Protection Doorhanger appears -// and has the correct state when tracking content is blocked (Bug 1043801) +// Test that the Tracking Protection section is visible in the Control Center +// and has the correct state for the cases when: +// * A page with no tracking elements is loaded. +// * A page with tracking elements is loaded and they are blocked. +// * A page with tracking elements is loaded and they are not blocked. +// See also Bugs 1175327 and 1043801. -var PREF = "privacy.trackingprotection.enabled"; -var BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html"; -var TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html"; +let PREF = "privacy.trackingprotection.enabled"; +let BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html"; +let TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html"; +let TrackingProtection = null; -function testBenignPage(gTestBrowser) -{ - // Make sure the doorhanger does NOT appear - var notification = PopupNotifications.getNotification("bad-content", gTestBrowser); - is(notification, null, "Tracking Content Doorhanger did NOT appear when protection was ON and tracking was NOT present"); +registerCleanupFunction(function() { + TrackingProtection = null; + Services.prefs.clearUserPref(PREF); + gBrowser.removeCurrentTab(); +}); + +function hidden(sel) { + let win = gBrowser.ownerGlobal; + let el = win.document.querySelector(sel); + let display = win.getComputedStyle(el).getPropertyValue("display", null); + return display === "none"; } -function* testTrackingPage(gTestBrowser) -{ - // Make sure the doorhanger appears - var notification = PopupNotifications.getNotification("bad-content", gTestBrowser); - isnot(notification, null, "Tracking Content Doorhanger did appear when protection was ON and tracking was present"); - notification.reshow(); - var notificationElement = PopupNotifications.panel.firstChild; +function testBenignPage() { + ok (!TrackingProtection.content.hasAttribute("block-disabled"), "blocking not disabled"); + ok (!TrackingProtection.content.hasAttribute("block-active"), "blocking is not active"); - // Wait for the method to be attached after showing the popup - yield promiseWaitForCondition(() => { - return notificationElement.disableTrackingContentProtection; - }); - - // Make sure the state of the doorhanger includes blocking tracking elements - ok(notificationElement.isTrackingContentBlocked, - "Tracking Content is being blocked"); - - // Make sure the notification has no trackingblockdisabled attribute - ok(!notificationElement.hasAttribute("trackingblockdisabled"), - "Doorhanger must have no trackingblockdisabled attribute"); + // Make sure that the no tracking elements message appears + ok (!hidden("#tracking-not-detected"), "labelNoTracking is visible"); + ok (hidden("#tracking-loaded"), "labelTrackingLoaded is hidden"); + ok (hidden("#tracking-blocked"), "labelTrackingBlocked is hidden"); } -function* testTrackingPageWhitelisted(gTestBrowser) -{ - // Make sure the doorhanger appears - var notification = PopupNotifications.getNotification("bad-content", gTestBrowser); - isnot(notification, null, "Tracking Content Doorhanger did appear when protection was ON and tracking was present but white-listed"); - notification.reshow(); - var notificationElement = PopupNotifications.panel.firstChild; +function testTrackingPage() { + ok (!TrackingProtection.content.hasAttribute("block-disabled"), "blocking not disabled"); + ok (TrackingProtection.content.hasAttribute("block-active"), "blocking is active"); - // Wait for the method to be attached after showing the popup - yield promiseWaitForCondition(() => { - return notificationElement.disableTrackingContentProtection; - }); - - var notificationElement = PopupNotifications.panel.firstChild; - - // Make sure the state of the doorhanger does NOT include blocking tracking elements - ok(!notificationElement.isTrackingContentBlocked, - "Tracking Content is NOT being blocked"); - - // Make sure the notification has the trackingblockdisabled attribute set to true - is(notificationElement.getAttribute("trackingblockdisabled"), "true", - "Doorhanger must have [trackingblockdisabled='true'] attribute"); + // Make sure that the blocked tracking elements message appears + ok (hidden("#tracking-not-detected"), "labelNoTracking is hidden"); + ok (hidden("#tracking-loaded"), "labelTrackingLoaded is hidden"); + ok (!hidden("#tracking-blocked"), "labelTrackingBlocked is visible"); } -function testTrackingPageOFF(gTestBrowser) -{ - // Make sure the doorhanger does NOT appear - var notification = PopupNotifications.getNotification("bad-content", gTestBrowser); - is(notification, null, "Tracking Content Doorhanger did NOT appear when protection was OFF and tracking was present"); -} +function testTrackingPageWhitelisted() { + ok (TrackingProtection.content.hasAttribute("block-disabled"), "blocking is disabled"); + ok (!TrackingProtection.content.hasAttribute("block-active"), "blocking is not active"); -function testBenignPageOFF(gTestBrowser) -{ - // Make sure the doorhanger does NOT appear - var notification = PopupNotifications.getNotification("bad-content", gTestBrowser); - is(notification, null, "Tracking Content Doorhanger did NOT appear when protection was OFF and tracking was NOT present"); + // Make sure that the blocked tracking elements message appears + ok (hidden("#tracking-not-detected"), "labelNoTracking is hidden"); + ok (!hidden("#tracking-loaded"), "labelTrackingLoaded is visible"); + ok (hidden("#tracking-blocked"), "labelTrackingBlocked is hidden"); } add_task(function* () { - registerCleanupFunction(function() { - Services.prefs.clearUserPref(PREF); - gBrowser.removeCurrentTab(); - }); - yield updateTrackingProtectionDatabase(); let tab = gBrowser.selectedTab = gBrowser.addTab(); - // Enable Tracking Protection + TrackingProtection = gBrowser.ownerGlobal.TrackingProtection; + ok (TrackingProtection, "Functionality is attached to the browser window"); + is (TrackingProtection.enabled, Services.prefs.getBoolPref(PREF), + "The initial enabled value is based on the default pref value"); + + info("Enable Tracking Protection"); Services.prefs.setBoolPref(PREF, true); + ok (TrackingProtection.enabled, "Functionality is enabled after setting the pref"); - // Point tab to a test page NOT containing tracking elements + info("Point tab to a test page NOT containing tracking elements"); yield promiseTabLoadEvent(tab, BENIGN_PAGE); - testBenignPage(gBrowser.getBrowserForTab(tab)); + testBenignPage(); - // Point tab to a test page containing tracking elements + info("Point tab to a test page containing tracking elements"); yield promiseTabLoadEvent(tab, TRACKING_PAGE); - // Tracking content must be blocked - yield testTrackingPage(gBrowser.getBrowserForTab(tab)); + info("Tracking content must be blocked"); + testTrackingPage(); - // Disable Tracking Content Protection for the page (which reloads the page) - PopupNotifications.panel.firstChild.disableTrackingContentProtection(); + info("Disable Tracking Content Protection for the page (which reloads the page)"); + TrackingProtection.disableForCurrentPage(); - // Wait for tab to reload following tracking-protection page white-listing + info("Wait for tab to reload following tracking-protection page white-listing"); yield promiseTabLoadEvent(tab); - // Tracking content must be white-listed (NOT blocked) - yield testTrackingPageWhitelisted(gBrowser.getBrowserForTab(tab)); + info("Tracking content must be white-listed (NOT blocked)"); + testTrackingPageWhitelisted(); - // Re-enable Tracking Content Protection for the page (which reloads the page) - PopupNotifications.panel.firstChild.enableTrackingContentProtection(); + info("Re-enable Tracking Content Protection for the page (which reloads the page)"); + TrackingProtection.enableForCurrentPage(); - // Wait for tab to reload following tracking-protection page white-listing + info("Wait for tab to reload following tracking-protection page white-listing"); yield promiseTabLoadEvent(tab); - // Tracking content must be blocked - yield testTrackingPage(gBrowser.getBrowserForTab(tab)); + info("Tracking content must be blocked"); + testTrackingPage(); }); diff --git a/browser/base/content/test/general/browser_trackingUI_2.js b/browser/base/content/test/general/browser_trackingUI_2.js index a466bb9d4c5c..556558c88268 100644 --- a/browser/base/content/test/general/browser_trackingUI_2.js +++ b/browser/base/content/test/general/browser_trackingUI_2.js @@ -2,45 +2,48 @@ * 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/. */ -// Test that the Tracking Protection Doorhanger does not ever appear -// when the feature is off (Bug 1043801) +// Test that the Tracking Protection section is never visible in the +// Control Center when the feature is off. +// See also Bugs 1175327 and 1043801. -var PREF = "privacy.trackingprotection.enabled"; -var BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html"; -var TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html"; +let PREF = "privacy.trackingprotection.enabled"; +let BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html"; +let TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html"; +let TrackingProtection = null; -function testTrackingPageOFF(gTestBrowser) -{ - // Make sure the doorhanger does NOT appear - var notification = PopupNotifications.getNotification("bad-content", gTestBrowser); - is(notification, null, "Tracking Content Doorhanger did NOT appear when protection was OFF and tracking was present"); +registerCleanupFunction(function() { + TrackingProtection = null; + Services.prefs.clearUserPref(PREF); + gBrowser.removeCurrentTab(); +}); + +function testTrackingPageOFF() { + ok (TrackingProtection.container.hidden, "The container is hidden"); } -function testBenignPageOFF(gTestBrowser) -{ - // Make sure the doorhanger does NOT appear - var notification = PopupNotifications.getNotification("bad-content", gTestBrowser); - is(notification, null, "Tracking Content Doorhanger did NOT appear when protection was OFF and tracking was NOT present"); +function testBenignPageOFF() { + ok (TrackingProtection.container.hidden, "The container is hidden"); } add_task(function* () { - registerCleanupFunction(function() { - Services.prefs.clearUserPref(PREF); - gBrowser.removeCurrentTab(); - }); - yield updateTrackingProtectionDatabase(); let tab = gBrowser.selectedTab = gBrowser.addTab(); - // Disable Tracking Protection + TrackingProtection = gBrowser.ownerGlobal.TrackingProtection; + ok (TrackingProtection, "Functionality is attached to the browser window"); + is (TrackingProtection.enabled, Services.prefs.getBoolPref(PREF), + "The initial enabled value is based on the default pref value"); + + info ("Disable Tracking Protection"); Services.prefs.setBoolPref(PREF, false); + ok (!TrackingProtection.enabled, "Functionality is disabled after setting the pref"); - // Point tab to a test page containing tracking elements + info ("Point tab to a test page containing tracking elements"); yield promiseTabLoadEvent(tab, TRACKING_PAGE); - testTrackingPageOFF(gBrowser.getBrowserForTab(tab)); + testTrackingPageOFF(); - // Point tab to a test page NOT containing tracking elements + info ("Point tab to a test page NOT containing tracking elements"); yield promiseTabLoadEvent(tab, BENIGN_PAGE); - testBenignPageOFF(gBrowser.getBrowserForTab(tab)); + testBenignPageOFF(); }); diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index 519101caaafb..b537739befe6 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -2377,10 +2377,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. Services.urlFormatter.formatURLPref("app.support.baseURL") + "tracking-protection"; } - if (Services.prefs.getBoolPref("privacy.trackingprotection.enabled")) { - let histogram = Services.telemetry.getHistogramById("TRACKING_PROTECTION_EVENTS"); - histogram.add(0); - } ]]> @@ -2429,10 +2421,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. // from the tracking protection allowlist. Services.perms.remove(gBrowser.selectedBrowser.currentURI.host, "trackingprotection"); - // Telemetry for enable protection - let histogram = Services.telemetry.getHistogramById( - "TRACKING_PROTECTION_EVENTS"); - histogram.add(2); BrowserReload(); ]]> diff --git a/browser/components/controlcenter/content/panel.inc.xul b/browser/components/controlcenter/content/panel.inc.xul index d91bac14b3e8..c8e97c29aa66 100644 --- a/browser/components/controlcenter/content/panel.inc.xul +++ b/browser/components/controlcenter/content/panel.inc.xul @@ -36,6 +36,42 @@ oncommand="gIdentityHandler.showSubView('security', this)"/> + + + + + + + + + + + + + diff --git a/browser/components/preferences/in-content/tests/browser_privacypane_5.js b/browser/components/preferences/in-content/tests/browser_privacypane_5.js index 1a2b572d2d59..4f549bb3430a 100644 --- a/browser/components/preferences/in-content/tests/browser_privacypane_5.js +++ b/browser/components/preferences/in-content/tests/browser_privacypane_5.js @@ -21,7 +21,7 @@ function test() { ]; if (AppConstants.NIGHTLY_BUILD) - tests.push(test_locbar_suggestion_retention("searches", true)), + tests.push(test_locbar_suggestion_retention("searches", true)); run_test_subset(tests); } diff --git a/browser/components/preferences/tests/browser_privacypane_5.js b/browser/components/preferences/tests/browser_privacypane_5.js index 1a2b572d2d59..4f549bb3430a 100644 --- a/browser/components/preferences/tests/browser_privacypane_5.js +++ b/browser/components/preferences/tests/browser_privacypane_5.js @@ -21,7 +21,7 @@ function test() { ]; if (AppConstants.NIGHTLY_BUILD) - tests.push(test_locbar_suggestion_retention("searches", true)), + tests.push(test_locbar_suggestion_retention("searches", true)); run_test_subset(tests); } diff --git a/browser/devtools/debugger/debugger-controller.js b/browser/devtools/debugger/debugger-controller.js index 54ae20dc2c24..5010eb685941 100644 --- a/browser/devtools/debugger/debugger-controller.js +++ b/browser/devtools/debugger/debugger-controller.js @@ -455,6 +455,7 @@ function Workers() { this._onWorkerListChanged = this._onWorkerListChanged.bind(this); this._onWorkerFreeze = this._onWorkerFreeze.bind(this); this._onWorkerThaw = this._onWorkerThaw.bind(this); + this._onWorkerSelect = this._onWorkerSelect.bind(this); } Workers.prototype = { @@ -476,6 +477,10 @@ Workers.prototype = { }, _updateWorkerList: function () { + if (!this._tabClient.listWorkers) { + return; + } + this._tabClient.listWorkers((response) => { let workerActors = new Set(); for (let worker of response.workers) { @@ -516,6 +521,13 @@ Workers.prototype = { _onWorkerThaw: function (type, packet) { let workerClient = this._workerClients.get(packet.from); DebuggerView.Workers.addWorker(packet.from, workerClient.url); + }, + + _onWorkerSelect: function (workerActor) { + let workerClient = this._workerClients.get(workerActor); + gDevTools.showToolbox(devtools.TargetFactory.forWorker(workerClient), + "jsdebugger", + devtools.Toolbox.HostType.WINDOW); } }; diff --git a/browser/devtools/debugger/views/workers-view.js b/browser/devtools/debugger/views/workers-view.js index 808cac63f719..3b7b9db24d89 100644 --- a/browser/devtools/debugger/views/workers-view.js +++ b/browser/devtools/debugger/views/workers-view.js @@ -3,7 +3,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; -function WorkersView() {} +function WorkersView() { + this._onWorkerSelect = this._onWorkerSelect.bind(this); +} WorkersView.prototype = Heritage.extend(WidgetMethods, { initialize: function () { @@ -17,6 +19,7 @@ WorkersView.prototype = Heritage.extend(WidgetMethods, { showArrows: true, }); this.emptyText = L10N.getStr("noWorkersText"); + this.widget.addEventListener("select", this._onWorkerSelect, false); }, addWorker: function (actor, name) { @@ -30,6 +33,13 @@ WorkersView.prototype = Heritage.extend(WidgetMethods, { removeWorker: function (actor) { this.remove(this.getItemByValue(actor)); + }, + + _onWorkerSelect: function () { + if (this.selectedItem !== null) { + DebuggerController.Workers._onWorkerSelect(this.selectedItem.value); + this.selectedItem = null; + } } }); diff --git a/browser/devtools/framework/target.js b/browser/devtools/framework/target.js index ee9cb1ac0b12..13c9177860d4 100644 --- a/browser/devtools/framework/target.js +++ b/browser/devtools/framework/target.js @@ -60,6 +60,15 @@ exports.TargetFactory = { return targetPromise; }, + forWorker: function TF_forWorker(workerClient) { + let target = targets.get(workerClient); + if (target == null) { + target = new WorkerTarget(workerClient); + targets.set(workerClient, target); + } + return target; + }, + /** * Creating a target for a tab that is being closed is a problem because it * allows a leak as a result of coming after the close event which normally @@ -799,3 +808,64 @@ WindowTarget.prototype = { return 'WindowTarget:' + this.window; }, }; + +function WorkerTarget(workerClient) { + EventEmitter.decorate(this); + this._workerClient = workerClient; +} + +/** + * A WorkerTarget represents a worker. Unlike TabTarget, which can represent + * either a local or remote tab, WorkerTarget always represents a remote worker. + * Moreover, unlike TabTarget, which is constructed with a placeholder object + * for remote tabs (from which a TabClient can then be lazily obtained), + * WorkerTarget is constructed with a WorkerClient directly. + * + * The reason for this is that in order to get notifications when a worker + * closes/freezes/thaws, the UI needs to attach to each worker anyway, so by + * the time a WorkerTarget for a given worker is created, a WorkerClient for + * that worker will already be available. Consequently, there is no need to + * obtain a WorkerClient lazily. + * + * WorkerClient is designed to mimic the interface of TabClient as closely as + * possible. This allows us to debug workers as if they were ordinary tabs, + * requiring only minimal changes to the rest of the frontend. + */ +WorkerTarget.prototype = { + get isRemote() { + return true; + }, + + get isTabActor() { + return true; + }, + + get form() { + return { + from: this._workerClient.actor, + type: "attached", + isFrozen: this._workerClient.isFrozen, + url: this._workerClient.url + }; + }, + + get activeTab() { + return this._workerClient; + }, + + get client() { + return this._workerClient.client; + }, + + destroy: function () {}, + + hasActor: function (name) { + return false; + }, + + getTrait: function (name) { + return undefined; + }, + + makeRemote: function () {} +}; diff --git a/browser/locales/en-US/chrome/browser/browser.dtd b/browser/locales/en-US/chrome/browser/browser.dtd index d34cc4a4caac..2c8089b2711a 100644 --- a/browser/locales/en-US/chrome/browser/browser.dtd +++ b/browser/locales/en-US/chrome/browser/browser.dtd @@ -768,6 +768,15 @@ you can use these alternative items. Otherwise, their values should be empty. - + + + + + + + + + diff --git a/browser/modules/NewTabURL.jsm b/browser/modules/NewTabURL.jsm index 9e78efaae095..f673bbc48564 100644 --- a/browser/modules/NewTabURL.jsm +++ b/browser/modules/NewTabURL.jsm @@ -10,6 +10,8 @@ let Cu = Components.utils; this.EXPORTED_SYMBOLS = [ "NewTabURL" ]; +Components.utils.import("resource://gre/modules/Services.jsm"); + this.NewTabURL = { _url: "about:newtab", _overridden: false, @@ -25,10 +27,12 @@ this.NewTabURL = { override: function(newURL) { this._url = newURL; this._overridden = true; + Services.obs.notifyObservers(null, "newtab-url-changed", this._url); }, reset: function() { this._url = "about:newtab"; this._overridden = false; + Services.obs.notifyObservers(null, "newtab-url-changed", this._url); } }; diff --git a/browser/modules/test/xpcshell/test_NewTabURL.js b/browser/modules/test/xpcshell/test_NewTabURL.js index e5ccd9ecfc79..aad233729d1d 100644 --- a/browser/modules/test/xpcshell/test_NewTabURL.js +++ b/browser/modules/test/xpcshell/test_NewTabURL.js @@ -4,14 +4,30 @@ "use strict"; Components.utils.import("resource:///modules/NewTabURL.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); -function run_test() { +add_task(function* () { Assert.equal(NewTabURL.get(), "about:newtab", "Default newtab URL should be about:newtab"); let url = "http://example.com/"; + let notificationPromise = promiseNewtabURLNotification(url); NewTabURL.override(url); + yield notificationPromise; Assert.ok(NewTabURL.overridden, "Newtab URL should be overridden"); Assert.equal(NewTabURL.get(), url, "Newtab URL should be the custom URL"); + + notificationPromise = promiseNewtabURLNotification("about:newtab"); NewTabURL.reset(); + yield notificationPromise; Assert.ok(!NewTabURL.overridden, "Newtab URL should not be overridden"); Assert.equal(NewTabURL.get(), "about:newtab", "Newtab URL should be the about:newtab"); +}); + +function promiseNewtabURLNotification(aNewURL) { + return new Promise(resolve => { + Services.obs.addObserver(function observer(aSubject, aTopic, aData) { + Services.obs.removeObserver(observer, aTopic); + Assert.equal(aData, aNewURL, "Data for newtab-url-changed notification should be new URL."); + resolve(); + }, "newtab-url-changed", false); + }); } diff --git a/browser/themes/linux/jar.mn b/browser/themes/linux/jar.mn index 6c09a4b34905..b4a65d5e91a3 100644 --- a/browser/themes/linux/jar.mn +++ b/browser/themes/linux/jar.mn @@ -150,6 +150,8 @@ browser.jar: skin/classic/browser/controlcenter/conn-secure-dv.svg (../shared/controlcenter/conn-secure-dv.svg) skin/classic/browser/controlcenter/conn-secure-ev.svg (../shared/controlcenter/conn-secure-ev.svg) skin/classic/browser/controlcenter/permissions.svg (../shared/controlcenter/permissions.svg) + skin/classic/browser/controlcenter/tracking-protection.svg (../shared/controlcenter/tracking-protection.svg) + skin/classic/browser/controlcenter/tracking-protection-disabled.svg (../shared/controlcenter/tracking-protection-disabled.svg) skin/classic/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png) skin/classic/browser/customizableui/customize-illustration.png (../shared/customizableui/customize-illustration.png) skin/classic/browser/customizableui/customize-illustration-rtl.png (../shared/customizableui/customize-illustration-rtl.png) diff --git a/browser/themes/osx/jar.mn b/browser/themes/osx/jar.mn index e5c7749c10e8..5d4d0389c1f9 100644 --- a/browser/themes/osx/jar.mn +++ b/browser/themes/osx/jar.mn @@ -194,6 +194,8 @@ browser.jar: skin/classic/browser/controlcenter/conn-secure-dv.svg (../shared/controlcenter/conn-secure-dv.svg) skin/classic/browser/controlcenter/conn-secure-ev.svg (../shared/controlcenter/conn-secure-ev.svg) skin/classic/browser/controlcenter/permissions.svg (../shared/controlcenter/permissions.svg) + skin/classic/browser/controlcenter/tracking-protection.svg (../shared/controlcenter/tracking-protection.svg) + skin/classic/browser/controlcenter/tracking-protection-disabled.svg (../shared/controlcenter/tracking-protection-disabled.svg) skin/classic/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png) skin/classic/browser/customizableui/customize-titleBar-toggle.png (customizableui/customize-titleBar-toggle.png) skin/classic/browser/customizableui/customize-titleBar-toggle@2x.png (customizableui/customize-titleBar-toggle@2x.png) diff --git a/browser/themes/shared/controlcenter/panel.inc.css b/browser/themes/shared/controlcenter/panel.inc.css index ca456a1e3846..371b6bdbec46 100644 --- a/browser/themes/shared/controlcenter/panel.inc.css +++ b/browser/themes/shared/controlcenter/panel.inc.css @@ -55,7 +55,8 @@ #identity-popup-securityView, #identity-popup-security-content, -#identity-popup-permissions-content { +#identity-popup-permissions-content, +#tracking-protection-content { padding: 0.75em 0 1em; -moz-padding-start: calc(2em + 24px); -moz-padding-end: 1em; @@ -66,7 +67,8 @@ #identity-popup-securityView:-moz-locale-dir(rtl), #identity-popup-security-content:-moz-locale-dir(rtl), -#identity-popup-permissions-content:-moz-locale-dir(rtl) { +#identity-popup-permissions-content:-moz-locale-dir(rtl), +#tracking-protection-content:-moz-locale-dir(rtl) { background-position: calc(100% - 1em) 1em; } @@ -199,6 +201,30 @@ margin-top: 1em; } +/* TRACKING PROTECTION */ + +#tracking-protection-content { + background-image: url("chrome://browser/skin/controlcenter/tracking-protection.svg"); +} + +#tracking-protection-content[block-disabled] { + background-image: url("chrome://browser/skin/controlcenter/tracking-protection-disabled.svg"); +} + +#tracking-actions { + margin: 1em 0 0; +} + +#tracking-protection-content[block-active] > #tracking-not-detected, +#tracking-protection-content[block-disabled] > #tracking-not-detected, +#tracking-protection-content:not([block-active]) > #tracking-blocked, +#tracking-protection-content:not([block-active]) #tracking-action-unblock, +#tracking-protection-content:not([block-disabled]) > #tracking-loaded, +#tracking-protection-content:not([block-disabled]) #tracking-action-block, +#tracking-protection-content:not([block-active]):not([block-disabled]) > #tracking-actions { + display: none; +} + /* PERMISSIONS */ #identity-popup-permissions-content { diff --git a/browser/themes/shared/controlcenter/tracking-protection-disabled.svg b/browser/themes/shared/controlcenter/tracking-protection-disabled.svg new file mode 100644 index 000000000000..955dfe23d0c3 --- /dev/null +++ b/browser/themes/shared/controlcenter/tracking-protection-disabled.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/browser/themes/shared/controlcenter/tracking-protection.svg b/browser/themes/shared/controlcenter/tracking-protection.svg new file mode 100644 index 000000000000..bf3f7806967f --- /dev/null +++ b/browser/themes/shared/controlcenter/tracking-protection.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/browser/themes/windows/jar.mn b/browser/themes/windows/jar.mn index df3b34dcd658..31abf45210e1 100644 --- a/browser/themes/windows/jar.mn +++ b/browser/themes/windows/jar.mn @@ -197,6 +197,8 @@ browser.jar: skin/classic/browser/controlcenter/conn-secure-dv.svg (../shared/controlcenter/conn-secure-dv.svg) skin/classic/browser/controlcenter/conn-secure-ev.svg (../shared/controlcenter/conn-secure-ev.svg) skin/classic/browser/controlcenter/permissions.svg (../shared/controlcenter/permissions.svg) + skin/classic/browser/controlcenter/tracking-protection.svg (../shared/controlcenter/tracking-protection.svg) + skin/classic/browser/controlcenter/tracking-protection-disabled.svg (../shared/controlcenter/tracking-protection-disabled.svg) skin/classic/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png) skin/classic/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico) skin/classic/browser/customizableui/customize-illustration.png (../shared/customizableui/customize-illustration.png) diff --git a/mobile/android/base/android-services.mozbuild b/mobile/android/base/android-services.mozbuild index ac6af72c16d5..bec1fac3b0e3 100644 --- a/mobile/android/base/android-services.mozbuild +++ b/mobile/android/base/android-services.mozbuild @@ -863,6 +863,7 @@ sync_java_files = [ 'fxa/activities/FxAccountStatusFragment.java', 'fxa/activities/FxAccountUpdateCredentialsActivity.java', 'fxa/activities/FxAccountVerifiedAccountActivity.java', + 'fxa/activities/PicassoPreferenceIconTarget.java', 'fxa/authenticator/AccountPickler.java', 'fxa/authenticator/AndroidFxAccount.java', 'fxa/authenticator/FxAccountAuthenticator.java', diff --git a/mobile/android/base/fxa/FxAccountConstants.java b/mobile/android/base/fxa/FxAccountConstants.java index c3e3d063741c..b5aed319cb77 100644 --- a/mobile/android/base/fxa/FxAccountConstants.java +++ b/mobile/android/base/fxa/FxAccountConstants.java @@ -24,7 +24,7 @@ public class FxAccountConstants { public static final String STAGE_PROFILE_SERVER_ENDPOINT = "https://latest.dev.lcip.org/profile/v1"; // Action to update on cached profile information. - public static final String ACCOUNT_PROFILE_AVATAR_UPDATED_ACTION = "org.mozilla.gecko.fxa.profile.cached"; + public static final String ACCOUNT_PROFILE_JSON_UPDATED_ACTION = "org.mozilla.gecko.fxa.profile.JSON.updated"; // You must be at least 13 years old, on the day of creation, to create a Firefox Account. public static final int MINIMUM_AGE_TO_CREATE_AN_ACCOUNT = 13; diff --git a/mobile/android/base/fxa/activities/FxAccountStatusFragment.java b/mobile/android/base/fxa/activities/FxAccountStatusFragment.java index e90766a99aac..709163cbb2b3 100644 --- a/mobile/android/base/fxa/activities/FxAccountStatusFragment.java +++ b/mobile/android/base/fxa/activities/FxAccountStatusFragment.java @@ -50,6 +50,8 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.widget.Toast; +import com.squareup.picasso.Picasso; +import com.squareup.picasso.Target; /** * A fragment that displays the status of an AndroidFxAccount. @@ -140,13 +142,11 @@ public class FxAccountStatusFragment // Runnable to update last synced time. protected Runnable lastSyncedTimeUpdateRunnable; - // Runnable to retry fetching profile information. - protected Runnable profileFetchRunnable; - // Broadcast Receiver to update profile Information. protected FxAccountProfileInformationReceiver accountProfileInformationReceiver; protected final InnerSyncStatusDelegate syncStatusDelegate = new InnerSyncStatusDelegate(); + private Target profileAvatarTarget; protected Preference ensureFindPreference(String key) { Preference preference = findPreference(key); @@ -485,6 +485,18 @@ public class FxAccountStatusFragment // register/unregister calls. FxAccountSyncStatusHelper.getInstance().startObserving(syncStatusDelegate); + if (AppConstants.MOZ_ANDROID_FIREFOX_ACCOUNT_PROFILES) { + // Register a local broadcast receiver to get profile cached notification. + final IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(FxAccountConstants.ACCOUNT_PROFILE_JSON_UPDATED_ACTION); + accountProfileInformationReceiver = new FxAccountProfileInformationReceiver(); + LocalBroadcastManager.getInstance(getActivity()).registerReceiver(accountProfileInformationReceiver, intentFilter); + + // profilePreference is set during onCreate, so it's definitely not null here. + final float cornerRadius = getResources().getDimension(R.dimen.fxaccount_profile_image_width) / 2; + profileAvatarTarget = new PicassoPreferenceIconTarget(getResources(), profilePreference, cornerRadius); + } + refresh(); } @@ -498,14 +510,15 @@ public class FxAccountStatusFragment handler.removeCallbacks(lastSyncedTimeUpdateRunnable); } - if (profileFetchRunnable != null) { - handler.removeCallbacks(profileFetchRunnable); - } - // Focus lost, unregister broadcast receiver. if (accountProfileInformationReceiver != null) { LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(accountProfileInformationReceiver); } + + if (profileAvatarTarget != null) { + Picasso.with(getActivity()).cancelRequest(profileAvatarTarget); + profileAvatarTarget = null; + } } protected void hardRefresh() { @@ -606,53 +619,60 @@ public class FxAccountStatusFragment return; } - final ExtendedJSONObject cachedProfileJSON = fxAccount.getCachedProfileJSON(); - if (cachedProfileJSON != null) { - // Update profile information from the cached Json. - updateProfileInformation(cachedProfileJSON); + final ExtendedJSONObject profileJSON = fxAccount.getProfileJSON(); + if (profileJSON == null) { + // Update the profile title with email as the fallback. + // Profile icon by default use the default avatar as the fallback. + profilePreference.setTitle(fxAccount.getEmail()); return; } - // Update the profile title with email as the fallback. - // Profile icon by default use the default avatar as the fallback. - profilePreference.setTitle(fxAccount.getEmail()); - - // Register a local broadcast receiver to get profile cached notification. - final IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(FxAccountConstants.ACCOUNT_PROFILE_AVATAR_UPDATED_ACTION); - accountProfileInformationReceiver = new FxAccountProfileInformationReceiver(); - LocalBroadcastManager.getInstance(getActivity()).registerReceiver(accountProfileInformationReceiver, intentFilter); - - // Fetch the profile from the server. - fxAccount.maybeUpdateProfileJSON(false); - - // Schedule an runnable to retry fetching profile. - profileFetchRunnable = new ProfileFetchUpdateRunnable(); - handler.postDelayed(profileFetchRunnable, PROFILE_FETCH_RETRY_INTERVAL_IN_MILLISECONDS); + updateProfileInformation(profileJSON); } /** * Update profile information from json on UI thread. * - * @param profileJson json fetched from server. + * @param profileJSON json fetched from server. */ - protected void updateProfileInformation(final ExtendedJSONObject profileJson) { - // Remove the scheduled runnable for fetching the profile information. - if (profileFetchRunnable != null) { - handler.removeCallbacks(profileFetchRunnable); + protected void updateProfileInformation(final ExtendedJSONObject profileJSON) { + // View changes must always be done on UI thread. + ThreadUtils.assertOnUiThread(); + + FxAccountUtils.pii(LOG_TAG, "Profile JSON is: " + profileJSON.toJSONString()); + + final String userName = profileJSON.getString(FxAccountConstants.KEY_PROFILE_JSON_USERNAME); + // Update the profile username and email if available. + if (!TextUtils.isEmpty(userName)) { + profilePreference.setTitle(userName); + profilePreference.setSummary(fxAccount.getEmail()); + } else { + profilePreference.setTitle(fxAccount.getEmail()); } - // Read the profile information from json and Update the UI elements. - ThreadUtils.postToUiThread(new Runnable() { - @Override - public void run() { - // Icon update from java is not supported prior to API 11, skip the avatar update for older device. - if (AppConstants.Versions.feature11Plus) { - profilePreference.setIcon(getResources().getDrawable(R.drawable.sync_avatar_default)); - } - profilePreference.setTitle(fxAccount.getAndroidAccount().name); - } - }); + // Icon update from java is not supported prior to API 11, skip the avatar image fetch and update for older device. + if (!AppConstants.Versions.feature11Plus) { + Logger.info(LOG_TAG, "Skipping profile image fetch for older pre-API 11 devices."); + return; + } + + // Avatar URI empty, skip profile image fetch. + final String avatarURI = profileJSON.getString(FxAccountConstants.KEY_PROFILE_JSON_AVATAR); + if (TextUtils.isEmpty(avatarURI)) { + Logger.info(LOG_TAG, "AvatarURI is empty, skipping profile image fetch."); + return; + } + + // Using noPlaceholder would avoid a pop of the default image, but it's not available in the version of Picasso + // we ship in the tree. + Picasso + .with(getActivity()) + .load(avatarURI) + .centerInside() + .resizeDimen(R.dimen.fxaccount_profile_image_width, R.dimen.fxaccount_profile_image_height) + .placeholder(R.drawable.sync_avatar_default) + .error(R.drawable.sync_avatar_default) + .into(profileAvatarTarget); } private void scheduleAndUpdateLastSyncedTime() { @@ -830,26 +850,24 @@ public class FxAccountStatusFragment } } - /** - * The Runnable that schedules a future to fetch profile information. - */ - protected class ProfileFetchUpdateRunnable implements Runnable { - @Override - public void run() { - updateProfileInformation(); - } - } - /** * Broadcast receiver to receive updates for the cached profile action. */ public class FxAccountProfileInformationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(FxAccountConstants.ACCOUNT_PROFILE_AVATAR_UPDATED_ACTION)) { - // We should have a cached profile json here. - updateProfileInformation(fxAccount.getCachedProfileJSON()); + if (!intent.getAction().equals(FxAccountConstants.ACCOUNT_PROFILE_JSON_UPDATED_ACTION)) { + return; } + + Logger.info(LOG_TAG, "Profile avatar cache update action broadcast received."); + // Update the UI from cached profile json on the main thread. + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + updateProfileInformation(); + } + }); } } diff --git a/mobile/android/base/fxa/activities/PicassoPreferenceIconTarget.java b/mobile/android/base/fxa/activities/PicassoPreferenceIconTarget.java new file mode 100644 index 000000000000..bc15f085ae8e --- /dev/null +++ b/mobile/android/base/fxa/activities/PicassoPreferenceIconTarget.java @@ -0,0 +1,76 @@ +/* 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/. */ + +package org.mozilla.gecko.fxa.activities; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.preference.Preference; +import android.support.v4.graphics.drawable.RoundedBitmapDrawable; +import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; +import com.squareup.picasso.Picasso; +import com.squareup.picasso.Target; +import org.mozilla.gecko.AppConstants; + +/** + * A Picasso Target that updates a preference icon. + * + * Nota bene: Android grew support for updating preference icons programatically + * only in API 11. This class silently ignores requests before API 11. + */ +public class PicassoPreferenceIconTarget implements Target { + private final Preference preference; + private final Resources resources; + private final float cornerRadius; + + public PicassoPreferenceIconTarget(Resources resources, Preference preference) { + this(resources, preference, 0); + } + + public PicassoPreferenceIconTarget(Resources resources, Preference preference, float cornerRadius) { + this.resources = resources; + this.preference = preference; + this.cornerRadius = cornerRadius; + } + + @Override + public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { + // Updating icons from Java is not supported prior to API 11. + if (!AppConstants.Versions.feature11Plus) { + return; + } + + final Drawable drawable; + if (cornerRadius > 0) { + final RoundedBitmapDrawable roundedBitmapDrawable; + roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(resources, bitmap); + roundedBitmapDrawable.setCornerRadius(cornerRadius); + roundedBitmapDrawable.setAntiAlias(true); + drawable = roundedBitmapDrawable; + } else { + drawable = new BitmapDrawable(resources, bitmap); + } + preference.setIcon(drawable); + } + + @Override + public void onBitmapFailed(Drawable errorDrawable) { + // Updating icons from Java is not supported prior to API 11. + if (!AppConstants.Versions.feature11Plus) { + return; + } + preference.setIcon(errorDrawable); + } + + @Override + public void onPrepareLoad(Drawable placeHolderDrawable) { + // Updating icons from Java is not supported prior to API 11. + if (!AppConstants.Versions.feature11Plus) { + return; + } + preference.setIcon(placeHolderDrawable); + } +} diff --git a/mobile/android/base/fxa/authenticator/AndroidFxAccount.java b/mobile/android/base/fxa/authenticator/AndroidFxAccount.java index c056f211ed57..5232b7676ecf 100644 --- a/mobile/android/base/fxa/authenticator/AndroidFxAccount.java +++ b/mobile/android/base/fxa/authenticator/AndroidFxAccount.java @@ -69,12 +69,12 @@ public class AndroidFxAccount { public static final String ACCOUNT_KEY_TOKEN_SERVER = "tokenServerURI"; // Sync-specific. public static final String ACCOUNT_KEY_DESCRIPTOR = "descriptor"; - public static final String ACCOUNT_KEY_PROFILE_AVATAR = "avatar"; public static final int CURRENT_BUNDLE_VERSION = 2; public static final String BUNDLE_KEY_BUNDLE_VERSION = "version"; public static final String BUNDLE_KEY_STATE_LABEL = "stateLabel"; public static final String BUNDLE_KEY_STATE = "state"; + public static final String BUNDLE_KEY_PROFILE_JSON = "profile"; // Account authentication token type for fetching account profile. public static final String PROFILE_OAUTH_TOKEN_TYPE = "oauth::profile"; @@ -105,13 +105,6 @@ public class AndroidFxAccount { } private static final String PREF_KEY_LAST_SYNCED_TIMESTAMP = "lastSyncedTimestamp"; - public static final String PREF_KEY_LAST_PROFILE_FETCH_TIME = "lastProfilefetchTime"; - public static final String PREF_KEY_NUMBER_OF_PROFILE_FETCH = "numProfileFetch"; - - // Max wait time between successful profile avatar network fetch. - public static final long PROFILE_FETCH_RETRY_BACKOFF_DELTA_IN_MILLISECONDS = 24 * 60 * 60 * 1000; - // Max attempts allowed for retrying profile avatar network fetch. - public static final int MAX_PROFILE_FETCH_RETRIES = 5; protected final Context context; protected final AccountManager accountManager; @@ -127,7 +120,6 @@ public class AndroidFxAccount { */ protected static final ConcurrentHashMap perAccountBundleCache = new ConcurrentHashMap<>(); - private ExtendedJSONObject profileJson; public static void invalidateCaches() { perAccountBundleCache.clear(); @@ -667,39 +659,17 @@ public class AndroidFxAccount { return intent; } - private void setLastProfileFetchTimestampAndAttempts(long now, int attempts) { - try { - getSyncPrefs().edit().putLong(PREF_KEY_LAST_PROFILE_FETCH_TIME, now).commit(); - getSyncPrefs().edit().putInt(PREF_KEY_NUMBER_OF_PROFILE_FETCH, attempts); - } catch (Exception e) { - Logger.warn(LOG_TAG, "Got exception setting last profile fetch time & attempts; ignoring.", e); - } - } - - private long getLastProfileFetchTimestamp() { - final long neverFetched = -1L; - try { - return getSyncPrefs().getLong(PREF_KEY_LAST_PROFILE_FETCH_TIME, neverFetched); - } catch (Exception e) { - Logger.warn(LOG_TAG, "Got exception getting last profile fetch time; ignoring.", e); - return neverFetched; - } - } - - private int getNumberOfProfileFetch() { - final int neverFetched = 0; - try { - return getSyncPrefs().getInt(PREF_KEY_NUMBER_OF_PROFILE_FETCH, neverFetched); - } catch (Exception e) { - Logger.warn(LOG_TAG, "Got exception getting number of profile fetch; ignoring.", e); - return neverFetched; - } - } - - private boolean canScheduleProfileFetch() { - final int attempts = getNumberOfProfileFetch(); - final long delta = System.currentTimeMillis() - getLastProfileFetchTimestamp(); - return delta > PROFILE_FETCH_RETRY_BACKOFF_DELTA_IN_MILLISECONDS || attempts < MAX_PROFILE_FETCH_RETRIES; + /** + * Create an intent announcing that the profile JSON attached to this Firefox Account has been updated. + *

+ * It is not guaranteed that the profile JSON has changed. + * + * @return Intent to broadcast. + */ + private Intent makeProfileJSONUpdatedIntent() { + final Intent intent = new Intent(); + intent.setAction(FxAccountConstants.ACCOUNT_PROFILE_JSON_UPDATED_ACTION); + return intent; } public void setLastSyncedTimestamp(long now) { @@ -755,60 +725,31 @@ public class AndroidFxAccount { ContentResolver.setIsSyncable(account, BrowserContract.READING_LIST_AUTHORITY, 1); } - // Helper function to create intent for profile avatar updated event. - private Intent getProfileAvatarUpdatedIntent() { - final Intent profileCachedIntent = new Intent(); - profileCachedIntent.setAction(FxAccountConstants.ACCOUNT_PROFILE_AVATAR_UPDATED_ACTION); - return profileCachedIntent; - } - /** - * Returns the cached profile JSON object if available or null. + * Returns the current profile JSON if available, or null. * - * @return profile JSON Object. + * @return profile JSON object. */ - public ExtendedJSONObject getCachedProfileJSON() { - if (profileJson == null) { - // Try to retrieve and parse the json string from account manager. - final String profileJsonString = accountManager.getUserData(account, ACCOUNT_KEY_PROFILE_AVATAR); - if (profileJsonString != null) { - Logger.info(LOG_TAG, "Cached Profile information retrieved from AccountManager."); - try { - profileJson = ExtendedJSONObject.parseJSONObject(profileJsonString); - } catch (Exception e) { - Logger.error(LOG_TAG, "Failed to parse profile json; ignoring.", e); - } - } + public ExtendedJSONObject getProfileJSON() { + final String profileString = getBundleData(BUNDLE_KEY_PROFILE_JSON); + if (profileString == null) { + return null; } - return profileJson; + + try { + return new ExtendedJSONObject(profileString); + } catch (Exception e) { + Logger.error(LOG_TAG, "Failed to parse profile JSON; ignoring and returning null.", e); + } + return null; } /** - * Fetches the profile json from the server and updates the local cache. - * + * Fetch the profile JSON associated to the underlying Firefox Account from the server and update the local store. *

- * On successful fetch and cache, LocalBroadcastManager is used to notify the receivers asynchronously. - *

- * - * @param isForceFetch boolean to isForceFetch fetch from the server. + * The LocalBroadcastManager is used to notify the receivers asynchronously after a successful fetch. */ - public void maybeUpdateProfileJSON(final boolean isForceFetch) { - final ExtendedJSONObject profileJson = getCachedProfileJSON(); - final Intent profileAvatarUpdatedIntent = getProfileAvatarUpdatedIntent(); - - if (!isForceFetch && profileJson != null && !profileJson.keySet().isEmpty()) { - // Second line of defense, cache may have been updated in between. - Logger.info(LOG_TAG, "Profile already cached."); - LocalBroadcastManager.getInstance(context).sendBroadcast(profileAvatarUpdatedIntent); - return; - } - - if (!isForceFetch && !canScheduleProfileFetch()) { - // Rate limiting repeated attempts to fetch the profile information. - Logger.info(LOG_TAG, "Too many attempts to fetch the profile information."); - return; - } - + public void fetchProfileJSON() { ThreadUtils.postToBackgroundThread(new Runnable() { @Override public void run() { @@ -828,24 +769,15 @@ public class AndroidFxAccount { final Intent intent = new Intent(context, FxAccountProfileService.class); intent.putExtra(FxAccountProfileService.KEY_AUTH_TOKEN, authToken); intent.putExtra(FxAccountProfileService.KEY_PROFILE_SERVER_URI, getProfileServerURI()); - intent.putExtra(FxAccountProfileService.KEY_RESULT_RECEIVER, new ProfileResultReceiver(profileAvatarUpdatedIntent)); + intent.putExtra(FxAccountProfileService.KEY_RESULT_RECEIVER, new ProfileResultReceiver(new Handler())); context.startService(intent); - - // Update the profile fetch time and attempts, resetting the attempts if last fetch was over a day old. - final int attempts = getNumberOfProfileFetch(); - final long now = System.currentTimeMillis(); - final long delta = now - getLastProfileFetchTimestamp(); - setLastProfileFetchTimestampAndAttempts(now, delta < PROFILE_FETCH_RETRY_BACKOFF_DELTA_IN_MILLISECONDS ? attempts + 1 : 1); } }); } private class ProfileResultReceiver extends ResultReceiver { - private final Intent profileAvatarUpdatedIntent; - - public ProfileResultReceiver(Intent broadcastIntent) { - super(new Handler()); - this.profileAvatarUpdatedIntent = broadcastIntent; + public ProfileResultReceiver(Handler handler) { + super(handler); } @Override @@ -853,21 +785,17 @@ public class AndroidFxAccount { super.onReceiveResult(resultCode, bundle); switch (resultCode) { case Activity.RESULT_OK: - try { - final String resultData = bundle.getString(FxAccountProfileService.KEY_RESULT_STRING); - profileJson = ExtendedJSONObject.parseJSONObject(resultData); - accountManager.setUserData(account, ACCOUNT_KEY_PROFILE_AVATAR, resultData); - Logger.pii(LOG_TAG, "Profile fetch successful." + resultData); - LocalBroadcastManager.getInstance(context).sendBroadcast(profileAvatarUpdatedIntent); - } catch (Exception e) { - Logger.error(LOG_TAG, "Failed to parse profile json; ignoring.", e); - } + final String resultData = bundle.getString(FxAccountProfileService.KEY_RESULT_STRING); + updateBundleValues(BUNDLE_KEY_PROFILE_JSON, resultData); + Logger.info(LOG_TAG, "Profile JSON fetch succeeeded!"); + FxAccountUtils.pii(LOG_TAG, "Profile JSON fetch returned: " + resultData); + LocalBroadcastManager.getInstance(context).sendBroadcast(makeDeletedAccountIntent()); break; case Activity.RESULT_CANCELED: - Logger.warn(LOG_TAG, "Failed to fetch profile; ignoring."); + Logger.warn(LOG_TAG, "Failed to fetch profile JSON; ignoring."); break; default: - Logger.warn(LOG_TAG, "Invalid Result code received; ignoring."); + Logger.warn(LOG_TAG, "Invalid result code received; ignoring."); break; } } diff --git a/mobile/android/base/fxa/sync/FxAccountProfileService.java b/mobile/android/base/fxa/sync/FxAccountProfileService.java index 723b08219bef..1548c3ff0c9b 100644 --- a/mobile/android/base/fxa/sync/FxAccountProfileService.java +++ b/mobile/android/base/fxa/sync/FxAccountProfileService.java @@ -11,6 +11,7 @@ import android.os.Bundle; import android.os.ResultReceiver; import org.mozilla.gecko.background.common.log.Logger; +import org.mozilla.gecko.background.fxa.FxAccountUtils; import org.mozilla.gecko.background.fxa.oauth.FxAccountAbstractClient; import org.mozilla.gecko.background.fxa.oauth.FxAccountAbstractClientException; import org.mozilla.gecko.background.fxa.profile.FxAccountProfileClient10; @@ -37,6 +38,11 @@ public class FxAccountProfileService extends IntentService { final String profileServerURI = intent.getStringExtra(KEY_PROFILE_SERVER_URI); final ResultReceiver resultReceiver = intent.getParcelableExtra(KEY_RESULT_RECEIVER); + if (resultReceiver == null) { + Logger.warn(LOG_TAG, "Result receiver must not be null; ignoring intent."); + return; + } + if (authToken == null || authToken.length() == 0) { Logger.warn(LOG_TAG, "Invalid Auth Token"); sendResult("Invalid Auth Token", resultReceiver, Activity.RESULT_CANCELED); @@ -66,7 +72,7 @@ public class FxAccountProfileService extends IntentService { @Override public void handleSuccess(ExtendedJSONObject result) { if (result != null){ - Logger.pii(LOG_TAG, "Profile Server response : " + result.toJSONString()); + FxAccountUtils.pii(LOG_TAG, "Profile server return profile: " + result.toJSONString()); sendResult(result.toJSONString(), resultReceiver, Activity.RESULT_OK); } } diff --git a/mobile/android/base/fxa/sync/FxAccountSyncAdapter.java b/mobile/android/base/fxa/sync/FxAccountSyncAdapter.java index fef11a114ec0..c6ac45fd892d 100644 --- a/mobile/android/base/fxa/sync/FxAccountSyncAdapter.java +++ b/mobile/android/base/fxa/sync/FxAccountSyncAdapter.java @@ -14,6 +14,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; +import org.mozilla.gecko.AppConstants; import org.mozilla.gecko.background.common.log.Logger; import org.mozilla.gecko.background.fxa.FxAccountUtils; import org.mozilla.gecko.background.fxa.SkewHandler; @@ -532,6 +533,12 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter { final KeyBundle syncKeyBundle = married.getSyncKeyBundle(); final String clientState = married.getClientState(); syncWithAssertion(audience, assertion, tokenServerEndpointURI, tokenBackoffHandler, sharedPrefs, syncKeyBundle, clientState, sessionCallback, extras, fxAccount); + + if (AppConstants.MOZ_ANDROID_FIREFOX_ACCOUNT_PROFILES) { + // Force fetch the profile avatar information. + Logger.info(LOG_TAG, "Fetching profile avatar information."); + fxAccount.fetchProfileJSON(); + } } catch (Exception e) { syncDelegate.handleError(e); return; diff --git a/mobile/android/base/locales/en-US/android_strings.dtd b/mobile/android/base/locales/en-US/android_strings.dtd index d803c4660286..0e696e7d64cb 100644 --- a/mobile/android/base/locales/en-US/android_strings.dtd +++ b/mobile/android/base/locales/en-US/android_strings.dtd @@ -426,9 +426,9 @@ size. --> - - + diff --git a/mobile/android/base/resources/values/fxaccount_dimens.xml b/mobile/android/base/resources/values/fxaccount_dimens.xml index 0298be25065e..f355141b4d47 100644 --- a/mobile/android/base/resources/values/fxaccount_dimens.xml +++ b/mobile/android/base/resources/values/fxaccount_dimens.xml @@ -25,4 +25,9 @@ 16dp 0x02000000 + + + 48dp + + 48dp diff --git a/mobile/android/base/strings.xml.in b/mobile/android/base/strings.xml.in index 36de7c036a2c..cbb6eaadbed9 100644 --- a/mobile/android/base/strings.xml.in +++ b/mobile/android/base/strings.xml.in @@ -326,7 +326,7 @@ &site_settings_clear; &site_settings_no_settings; - &reading_list_added2; + &reading_list_added3; &reading_list_removed; &reading_list_remove; &reading_list_duplicate; diff --git a/mobile/android/modules/HomeProvider.jsm b/mobile/android/modules/HomeProvider.jsm index 7d3022742029..77e15aad977c 100644 --- a/mobile/android/modules/HomeProvider.jsm +++ b/mobile/android/modules/HomeProvider.jsm @@ -5,8 +5,6 @@ "use strict"; -/*globals gSyncCheckIntervalSecs, gUpdateTimerManager, Sqlite, DB_PATH */ - this.EXPORTED_SYMBOLS = [ "HomeProvider" ]; const { utils: Cu, classes: Cc, interfaces: Ci } = Components; @@ -127,18 +125,18 @@ function syncTimerCallback(timer) { } } -let HomeStorage = function(datasetId) { +this.HomeStorage = function(datasetId) { this.datasetId = datasetId; }; -let ValidationError = function(message) { +this.ValidationError = function(message) { this.name = "ValidationError"; this.message = message; }; ValidationError.prototype = new Error(); ValidationError.prototype.constructor = ValidationError; -let HomeProvider = Object.freeze({ +this.HomeProvider = Object.freeze({ ValidationError: ValidationError, /** diff --git a/mobile/locales/en-US/searchplugins/amazondotcom.xml b/mobile/locales/en-US/searchplugins/amazondotcom.xml index d52ff8633ff5..479abc36d93e 100644 --- a/mobile/locales/en-US/searchplugins/amazondotcom.xml +++ b/mobile/locales/en-US/searchplugins/amazondotcom.xml @@ -5,7 +5,7 @@ Amazon.com ISO-8859-1 -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZJREFUeNrEV01IFGEYfndXNzq0QdalJOoUbQiBUuopD2k/GFSG/Vxyq0OHbCUjwn7AEooUzUNRkdkhS1o9JBVaUDctKqhoRQi0WjtlxG6XVtfpfb6Z2caZ2ZnZXZdeeJxvx+973+f9+775XJIkkUaWMcoYG5TxfMpvxlvGMGM8+RYEFOxn/JJyLzOMiwwv7LqUCNQwHjpxIxKJ0Gg4LABZUVhIfr+f1jLSlNuMwyCwEHoZS6xmvxoZoc6Oq+JpJoVMpOncWdpcWZkOiRIQ2MKDp1az+kIhOtV40pHG6zdvpEOixc1/VtqFvKX5gmOX0pkL2yDgsZpxt+sORaPROe8Q6ncf3tPAk8eG3Ks14lA8brsZYZ2yukBAwOfzCeMHA3WGNXrCVpLnJKeqRyhAfX5RfNmILQF4urG0VIzxBBkU5aQI9agIeU4JqNLZ0UH9ob6sDWZE4MDefSn7P1txO/FcbxypQG18nhinew/u5zYC3dyG+qLL1qjjCKDg9C21q2a3oe9zRsCsn2PR2JzfKEy9PB96Nj8E0IJm54IaGZwPZsWJOU4jY1kD2OlAQhsJjKu3bSe7yPUzifpgMPsuOBY8brtR1evmyFt0IL0IzH4fJtcCH7kK1hn2/hh71G1yKKEdz/DBBIOTkUkRemzVl1uvCGKzE4OMIaFbiv1LSX51L7mXl4kxvgeO8vMaJk0PHiHvjl4DCTWs2lMOX0L6cwD/Bxlp6hNNv2gUT9MjsLiB8koaMOxJRgCMgPijWsqvaCP3qqqUZ4JVzUASYyFyL/WTqyggPxWH4qGtBlJzagCGIYjEzJv2zHe38vOUt6mNPGv20OyPMMV7yuVwL5IjBlLmRej1UX7VLdmLt+2CMVKTiSDn0wO1NPPyBOtdLL+MyzWkTbGhC5AGsBdKkEtWAjglgjUwCq/FGjhV0ZosdOhXI5FyH0DoIIK9slB0CS8UCgr8AlpvpamwqHpttcO4WtSqA57ioKENE05IqIYSY46uD4Is0qmGG2s9RYeS7adI3Paz3K6lTMmzIdFmXp/d1Gb1YvLF7i4IzxMfu1ITYWOe1VWix7U5tlKpXkzwYycONqfVLcW+cU7lQ0jePf360DqRS4zT/+Ny+ofRxPBoL6fa6zmu5uvtbkwZyE/lev6a8VV9+VeAAQADg36zc4GRNAAAAABJRU5ErkJggg== +data:image/png;base64,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 diff --git a/mobile/locales/en-US/searchplugins/bing.xml b/mobile/locales/en-US/searchplugins/bing.xml index e503048b1769..f90bf97da216 100644 --- a/mobile/locales/en-US/searchplugins/bing.xml +++ b/mobile/locales/en-US/searchplugins/bing.xml @@ -4,7 +4,7 @@ Bing -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjMzMkQxN0Y5NkYxMDExRTNCRERGREFGNkIwOTFENDc1IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjMzMkQxN0ZBNkYxMDExRTNCRERGREFGNkIwOTFENDc1Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MzMyRDE3Rjc2RjEwMTFFM0JEREZEQUY2QjA5MUQ0NzUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzMyRDE3Rjg2RjEwMTFFM0JEREZEQUY2QjA5MUQ0NzUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4iSWmdAAACDElEQVR42mIMCAhgoCVgYqAxGPoWMGtoaGCKzo7ZKcH37c9fpjdfOf//Z6TEAhasoiI837107gHR15+sZx9JzDum8/E7O02CiJv9t53qYyHuH6OpiCBgZPxPWwv4OX71BB+INL2uJPKBCqkIE3z4zv7gLV+Y8U0gev2F8+R9qRP3Ja8/F/5HKBGzEO+WTZdUnDUeARmiPN99dO8C0acfbKcfSJ68L3nhiejvv8yUWvDoHd+Fx2IGsq/gInwcv5w1HgLRjz/M5x6Jd+8yozQVbbioglWcg+WvldIzKiTTS0/EmrdZXn4qQv1IhgBgUgUGBRDpSr+u9DjJyfqHyhaASkemf25aD8KNbxJjOlEW/PnH9O0nKyivMTBYKj+NMbsmyf+VakH07RdLx07zl5+5dKTexFtcVRF7j8sRGy6okGwBMJk3b7X6/Zepxuu4sdxLXMouPhGdfUT/6Qce0ix4+5Vzwl5jYJXgoP4IV2Z9/40DWFUcuSNDchA9/8hz6alInfdxVua/WBUAS4itl5VWnNEEhiE5cfDoHa+71gNcem6+FJpxSP/BW37y6+Sjd2V+/GbRkX7DhFpKf/7BNveo3uzD+h++c1CUiv6DS4VLT0WLXE5LC3yBiOy5Lr/4pDbQDiq0KuBxuO+GPD/nL6A/Onea77iq9OsPM3VaFXAALCanHTQYbToObQsAAgwAOOjO/za44IcAAAAASUVORK5CYII= +data:image/png;base64,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 diff --git a/mobile/locales/en-US/searchplugins/duckduckgo.xml b/mobile/locales/en-US/searchplugins/duckduckgo.xml index 97ca332799bd..9e96ae21a005 100644 --- a/mobile/locales/en-US/searchplugins/duckduckgo.xml +++ b/mobile/locales/en-US/searchplugins/duckduckgo.xml @@ -5,7 +5,7 @@ DuckDuckGo UTF-8 -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowMTgwMTE3NDA3MjA2ODExQTUzMUNFODI2QjhFRURFRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4REU3ODU4OUE4OTMxMUUzODAxMUE0MzZGQUQ1RTAwNyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4REU3ODU4OEE4OTMxMUUzODAxMUE0MzZGQUQ1RTAwNyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgTWFjaW50b3NoIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDg4MDExNzQwNzIwNjgxMUE1MzFDRTgyNkI4RUVERUQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMUE1MzFDRTgyNkI4RUVERUQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5AWogMAAAGb0lEQVR42pxXbUyTVxQ+7WpboJCKCiggxcmXjKZuyXRbFtv4hXFq69yyZHHYbGa/FiDuxz5+OJIl+4nbjy3zh4w5f7gfUjBGHX6URY3iFju+pDCgCmUgH5ZiKVjad+e8733btx9Q4knu+3Hf+57nueece+65MlihuA8XafFmxrYDm4E1qThYa8Nmy73Q71mJXlmyASOWIiPeqnDkMUm3h4FJhQhpw28c2PD6fV5Tv/2FCAxbirT4sR4fRWAXKaTZoVLXEmR1zErV2HSs+xcOoDa/KbFFEhIYNhcZ8EsTU0JgVlRgZ/2iG3QSEBdrbTTzfFu/Y1iwXENYBwcW6k9K4DGBANxk5jy10dZfi32k7CQ24wpDhsxeh//a8V+yYg1zm2ljDIkoAo8QXBYBt6LpbOSGhf2fHMvfLmAvPhmBhe528N+7BiGfNxkR3vwywS1kDQ++mwokJMIEHh3io3xIBCdfM0sYUo+fhLX7P4zSTOBTP3zBE0kiBGYCCQlshQXNQky8JI6qKV3zE7LZTmZHlj8TuIwtNc+YGyYvnQO/3w+yvM2gUqlAplRB2tv7QZ6WAUHPJISwLSE5qK8S71+iPjW5Ed9zTjmnm8MWcB0sNrLZOnQtfVvxvUES/aAsLIV1X/0IiqzcJadJ1nh2vWlZd6BuK+p+wJasCd/tPIGhg8VNzEQmNvim+FcgPRM2nLJB2trspJE39vVRmO9qX26IVL+tsKXPIh88UCyuXQd22DmOj/awBN56hwe/3zEGjb93woPOsTitF670w4m66zBY/t6yBEk3YbC4MBO2gh7wA0kjdhh4H3GRn4I5wlJ39EzA8Q8qEio+XFnENz5l3zsDz4ceLsXBSBiov5G5wSxHrB0Mz4b3Ko7PopEG7COBjz7xQu/QRELN1d+1wP2uEdDstECsjphWxbDoeYccrwZsnk0X+1zsOWp0YDEQBjlS+xs03+hOSOLGvQH+m7KwDJIwMDAsHk/BCanSziYbu8PBs4nx8HNp4ToE6YGjB16NI3D19MfCw3gvjyNXhyB1i59v8pQQeG+nw1xPirhp0RhK3UYFcNIokexmTFSTo+D1eiEjIwPOfJs4yLj5DlifNgPw/BEE1bdgw2djoFwfiBozP6iGuW6egBYkrlVE48dL6ui/YQJxgoChkU+B8/0ZlduV61m2nJfDs7/TYOa2BhafKqJJg0iAi1omnqg9nZRNuGF6ehry8vLi8INDlTwJYYaqyNJFMDK3T5hxrHgYlkCAEiEX2VYdsTuefMEPc250l16/5PqmmY6ezkr4TbF6MXb2DmYBHVrLRS7gk4JzX7GOS0CAZGGA1vXBOOXygvMQGtyLATcDudVj6OPU8Df1pnlQbQjwwTh5UYtuSA8TICyqE2i3JRe0sUxoBCFB1MQCpbgHeDdkZmZGFxNqPYz+ugtkwTbQlPsh/TUfP2NR/OiW2b/SwItxIJFGhkXSpmDbLhUN1aWX+7b27it2SSodIQ4m3XwgxhIQhXy9hL9jxYUYDsRoYO82OXa40Aq0BxgeVhZTGq6lAJE29YiwEhJJSsU2iB2/TKtlGJSO7YQtZ3rqWKKqL7vSR2nSFpvAZp0dwrY7Pw7Opx1hApo3dobHDOeroflQFnSXaxIlQRvTXc8WQJ24CgA/2Hv2lpArzHj/BodbgZPppLV/8PEABAIBuDPaCi2DZ2FNSjZsz94NGqUG7ryfIxSz+WoheS2EYEuXLzryZZyV183xOm1lV532MAG2LKxsBZxEcBfbu2+KJMgNs7OzkQLEPw7nOs+CNh0XEwMWZSYjKsEKJRknM7PC1sNKPmEliQ/lV50eScHQgD4SCxSbkJBGYWpqKgpIuSpp0NG/JqZLDDwTw4omwEg4cLCVZSkiUYN9FrxbVk24XbQU89M3RY5C696ELEUF6LW74cT4TthzeQpe7p+DzX1zFNgW9m8N00VBaCWMpAeTrj0lBi5SnjvQnrUVrU773bt3jTllmVV3/ms17il4V7dGHSnTgrMzrodHtlEZ3/jKH05H5+4SI2qvZy70YL+J+ld8NEMFWmY2s3jYQFKNZedvHVKsXivuF1pJoNp9He1tg59/5JIJRYdR4gYrTmDlRzOpdNBMYk5FafrXhRjIyQVltlAp+wd6wfdPOwQjhxX+dKRvdb7Y4TSOyK4SvnjlIsdzXWyWI3fJ2PFcf83pWone/wUYANRs/BQLVeSGAAAAAElFTkSuQmCC +data:image/png;base64,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 diff --git a/mobile/locales/en-US/searchplugins/google.xml b/mobile/locales/en-US/searchplugins/google.xml index 63a14176e54b..f563a69b4379 100644 --- a/mobile/locales/en-US/searchplugins/google.xml +++ b/mobile/locales/en-US/searchplugins/google.xml @@ -5,7 +5,7 @@ Google UTF-8 -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACv0lEQVR42sWX208TURDG958x8M+It5CoDxojGn0wPvCg8UljYhRjBCpqJBQbL6lgI5JyERpFRLAiF7GiqI0QbUCIlm1pQ6XM556z7dQNbTl1l/olkzTd0zO/THe+OUfbXk8ithnhM0I3Alscusxl5tRE8gojokagzBEVubUMDUqJ4x6CNwhMfQOiCSCVRl6tpYFHY8DeGwX38mkllF1u9OwDkEwB90cIZx4SrvQSpiNgEYC218DFLsKR1k33jGuqyfcZyWeXgPQ6UOu1PtvZSBj6BJaeBI7eVttXGWDkC4REorzPq5sIS3GwQt/hHMDpdkJWd4YLr3MPEv7WibsOAfgnwbo1UHjdwWYrwLWAQwDjc2D53hQv7fwyWC2DDgGMzYI1HSkKIFqTVdftEED7KFhEwGH35gCpNWD/TfsAbDxEYAXe56/CLheJFpTyDDnchg+CsKixf+Mab2ZN11ugqt5ZALGhdL+1dM7xhj+bIK4AYWIOUq0v+DeOAnDUuEmWd3AGCIaBnytgie/kOvsA6rEYA8vzksoPoCfBWtCBQy1lBuiZgkW/EsCptq0D4Ol3zEM495ik263TxnNAXbdzANzj9X3SlqXJrBoxM29Ox9538rNFAup8p0MAtV7p8Txmz3YIIOuaHQ3SByyGlViFOEfYApBl/m32vvy/qxqKr7/UxV6R8QUbANVN/JbLft/tUvu7rj4hZW/QVDd6/hEoxTUX9OwJygZA5wRYA6oAPBXZnP4ZQHp/VstJYI9LvQI/YuYBtsZtA+DkPQIhp76Q2pS73EOAeTy334Yd47BITD0BVsigrj8lpNLSG0RrKgHoxcspp58wH4siUfMN90+a8SoM2TFLcXEpUX5X4spXswPNJHt69CvkBEymcpeQ8CLQHwIu+NmgVIKvZpX/8XJamb2eV2QqEStD4pjMZebU/gD3oidE+JhxZwAAAABJRU5ErkJggg== +data:image/png;base64,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 diff --git a/mobile/locales/en-US/searchplugins/twitter.xml b/mobile/locales/en-US/searchplugins/twitter.xml index da5eb759054c..1334c4726f65 100644 --- a/mobile/locales/en-US/searchplugins/twitter.xml +++ b/mobile/locales/en-US/searchplugins/twitter.xml @@ -4,7 +4,7 @@ Twitter - data:image/png;base64,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 + data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAACW5JREFUeAHtXGmMFEUUft07x87sAS6ngILKYkTDoaLiFeSIKP4wGggmxoSsaOIRE3+q0R8aNeKtMUZB/WEMh5JIFGMEMYiCyC2Xigi4wCKw7DJ7zOwx7ft6aZ0duuesqt7Beklv73R1V736vjpevX7VBp0Ry7KMucub65JW8n4yaCxZVOWk6bMABAyKMaa7TcNcuPiufosMw7CQq4E/s79sGUrtnR8TWdPwW4tsBIzVFAneu2xWZYOJlq/Blw14ev7c0LnBA3tjzvKm+VYy+V76Lfq3fAR4OJpvMvh18ovSJbghgPnWtCdct1R9TT4CbOyY2tqRj7NnCWxpmp6JOkEJApoAJTB7F6IJ8MZGSYomQAnM3oVoAryxUZKiCVACs3chmgBvbJSkaAKUwOxdiCbAGxslKZoAJTB7F6IJ8MZGSYomQAnM3oVoAryxUZKiCVACs3chmgBvbJSkaAKUwOxdSMA76dxICXDcx/DqMjqv3KDqsEmxjiQ1tlt0NNZN/K/vcs4SMGFIgKaMDNOEoUGKBs/GOdFFtLWhk9b91UEbj3SefYPLlZqIQV1M2umEHdLjckf+l6QRgLHNjwZ2Ibf2eRMidPmgzFULc/J1I4L28XtjN324rY32nep2RXBw1KQ7Ly2ncUzqY1+fdr2n0IuZtSww1xru7g9eVUELfmyhLnGNJas2k4cH6eFJFRQqy3prrxtqa8rouVuqaOHWNlr1Z4edVhUyaMKQIF09LEjX8FHGLeqTnXHqFlwfKQRMvzhME4cG6CEG482Nrb0qK+vHtFEhJj1acPYmzxUPXBmlKwYFaVCFSZecV0a45sih5iR98Vvc+SnsLJwAKD39orCt4I0XBKmlI0IfbGsXprBbRpcNDFDdxMLBT83zetY5XeI8X7z9c6uU3izcDB3Crac/D0GOzLwkTI9OilLZf5ecJCHnINfgUe5pAeE16VGvg6eFF39ooQPNPfND/zCGJnHtVlxOZ+AEAely04Uh2wR8ZX0Lxd3nufRHcv592+gwDYzKYbehJUlvccuHxTSVh7jJI0L20PTUd7Gc9ct2o3ACBle4z4DjudW8MLWaXuc54eCZ1pRNuWzpgP2O2vJstxWc3s1m3DM3V/07qVs8Ab+0vpWOxMTZd2c314LV7Xkw01AzvNqk59nauJUnaREC6yV1uBORZ2oe0DfVolqyO06bj+a2ZkjNJ9P/wgk43pa5dQS5g9RNjNDTN1XSiCID82AmqhC0/I9/aafle8VbQcIJ+Ls1MwEOYFcMDtCC6dU0b3yEKoKFjeEDXeYbJ39RZ0zCr//USit+S4jKslc+wueAIy3dbHpaVMkLmWyCxQ0m0VtGhWn1nwlauS9B2XpQap415cLbT2r29uT73LoY/XpSsOWQUorwGsBXsvZgz2oypZyM/5ZzM5hVG6a3ZlbT49dW0CReecK8zCYoS6Y0J5JSwYfuwnsAMl3Frfl2BjRfwSLO8c9g8YMJDw6zfY1ddIRNwnQ50X72tfR7ivltGtl7cTH541kpBNSzmbZqfwdNvzhUsH7oFTfwqhQHBMPaH+wsO8ZENMbhUk5SFL5miRJX4MiSQgAw+WhHG41lj+SwIi0dB1/MKVhL0BDnivyzCgJyGGnzq6hj0cB6eHVDKzXFBbsP81OnqLvbOuXrLpwA+M2x2JoyMmQPFU+sidFfp+WO1UWhnOHhXE3qDFlkTRI+BMFyGM0r1NE1Pd7JGL89ahL4BilrjQTe0NAqz/x01BROwGF+15oqVew9xFGKItLn41V/4UPQ7uNd9ntTrwJL6TrMX9kinIAEdwDRDivZILjlD1e0iqFTOAGozOe/indauYEk89reE/JbP/SXQgCiC9YdEuu2lQm2W96bBLud3crANSkEIOOFHOZxok2+HY2yRAvcINvYBaJCpBGARcyz38foFEehlZpsYfBVRc1JIwCgH+WJ7Jm1MTrQ1Ns07euErNovx/fvVm+pBKBAWBNYDeNtErp2X5d6XrXvZFNalQhfiLkpDr/94l1x+uL3BCGA6qrzQzRmQO/AJ7fn/Li2cp9aC046AdW8Cn7k6gp2yiXtSDNETSB0pS+ujeH7+e5Afi+Tim0k0glAJDGCpqZwy+/rspSjHhS8AugFg/Q5AKWhYn1dYCh8f0ht6wcmSgjYe7LLfkPWV0lAANa7m9v442HqRQkBqBYWZhvq1Sxu8oVxBUc97/fJVFZGQJKb1xsclrgpx90o+YJY6P0Yepbt8W+IVEYAAMLmhlc5yOkrjv8BIX4LXhYt4FhP2eEtmeqplAAogsp+uL2dnuTF2cbDnb4RgQbwGjeGfALBMgFZaJox+9NGX9sigmvHDQ4SAm0HREzeWdOzHajQCuXyHMB/Z1MbrfXB6knXT3kPSFcAURMA4kteJUc5RhThijIFgbbvbekb4KOe0hdi2cDEihjxofdcHiHsXJQpMDff54143ype7Waqk+QqexeNuHvs472dwRcVvOVdGlErR9bBAPjlb3WOtkz6OGlKCUBrH9mvjK7j7aQzeJOGqmgJeDhf3tAidGeLA2CxZ2EE9GOnW4LtTLicsUsGTjh8GgDXh1aW8fbPAGFPQC5h68VWynkeky08sEt2tVMnDz99UYQRgAl0Pm8Vxcbm1P21flUaC6xFvPqWGdsvom7CzdAxbE7eNy5q+/tFKJhvHngBBOcfvgFRCiKcAKfSiGTGzpdJ5/NmC/eNk86tQs57OIwEIfE/1ncI/5yAEAU9MhE2BKXnv/1YF+FAtPSNF4Ts9wHY/i9SEPS7lcNH1hxM0GGBW0dF6pgtL2k9wK1gfACjtiZAGKbGDAhwAG+AsBEjF4EZCZDrOfYUQVM7jnVy9LWvi/hc1M56T47Vz5pPTjfEGESEfOCAwCytYFJgGYGcqpBp/4/Vaju/mrIPDm/BbhgVYYK2Uor/KCUgvW5ov9h6hKPBTiyt8JX0+hTyW7LnpRCV/l/PaAJ85lsToAnwGQGfi9c9QBPgMwI+F697gCbAZwR8Ll73AE2Azwj4XLzuAZoAnxHwuXjdAzQBPiPgc/G6B2gCfEbA5+KxW07ch5B9rkzJFc/Ym7wvZ3fJKX6uKMzYm6ZhLjxX6lNq9QD2hmVZxpzPmr4hsqaVWgVKW19j9dK7+8/gb5MaFkWC93KMwurSrlApac9YM+bAHpEhtqAnzF3eXJe0kvfzxDyW54YqJ02fBSAAYwdjPg87i+/qt8hu+JztP8DF2aE2lt4MAAAAAElFTkSuQmCC diff --git a/mobile/locales/en-US/searchplugins/wikipedia.xml b/mobile/locales/en-US/searchplugins/wikipedia.xml index bd22b1ea3c66..85753c0227ee 100644 --- a/mobile/locales/en-US/searchplugins/wikipedia.xml +++ b/mobile/locales/en-US/searchplugins/wikipedia.xml @@ -5,7 +5,7 @@ Wikipedia UTF-8 -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAACXBIWXMAAAsTAAALEwEAmpwYAAADGGlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjaY2BgnuDo4uTKJMDAUFBUUuQe5BgZERmlwH6egY2BmYGBgYGBITG5uMAxIMCHgYGBIS8/L5UBFTAyMHy7xsDIwMDAcFnX0cXJlYE0wJpcUFTCwMBwgIGBwSgltTiZgYHhCwMDQ3p5SUEJAwNjDAMDg0hSdkEJAwNjAQMDg0h2SJAzAwNjCwMDE09JakUJAwMDg3N+QWVRZnpGiYKhpaWlgmNKflKqQnBlcUlqbrGCZ15yflFBflFiSWoKAwMD1A4GBgYGXpf8EgX3xMw8BSMDVQYqg4jIKAUICxE+CDEESC4tKoMHJQODAIMCgwGDA0MAQyJDPcMChqMMbxjFGV0YSxlXMN5jEmMKYprAdIFZmDmSeSHzGxZLlg6WW6x6rK2s99gs2aaxfWMPZ9/NocTRxfGFM5HzApcj1xZuTe4FPFI8U3mFeCfxCfNN45fhXyygI7BD0FXwilCq0A/hXhEVkb2i4aJfxCaJG4lfkaiQlJM8JpUvLS19QqZMVl32llyfvIv8H4WtioVKekpvldeqFKiaqP5UO6jepRGqqaT5QeuA9iSdVF0rPUG9V/pHDBYY1hrFGNuayJsym740u2C+02KJ5QSrOutcmzjbQDtXe2sHY0cdJzVnJRcFV3k3BXdlD3VPXS8Tbxsfd99gvwT//ID6wIlBS4N3hVwMfRnOFCEXaRUVEV0RMzN2T9yDBLZE3aSw5IaUNak30zkyLDIzs+ZmX8xlz7PPryjYVPiuWLskq3RV2ZsK/cqSql01jLVedVPrHzbqNdU0n22VaytsP9op3VXUfbpXta+x/+5Em0mzJ/+dGj/t8AyNmf2zvs9JmHt6vvmCpYtEFrcu+bYsc/m9lSGrTq9xWbtvveWGbZtMNm/ZarJt+w6rnft3u+45uy9s/4ODOYd+Hmk/Jn58xUnrU+fOJJ/9dX7SRe1LR68kXv13fc5Nm1t379TfU75/4mHeY7En+59lvhB5efB1/lv5dxc+NH0y/fzq64Lv4T8Ffp360/rP8f9/AA0ADzT6lvFdAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAHqSURBVHjapJUxb9NQFIW/JAip2xNS1/J+goeqUqeajdGVmFgwI1OcmYEgITFG7EgJQ+b2HzgbElJF+QU2iBl7YAFRnQ5+fnFcB0J8Jp/r53vPu+f6vYEA4JBTTjhkN/zkio9kAAihpyr1v/ijN7ovEHqiffFeDHTAdx6wL46HnPX4HM6HHNEHR0NGvRKMhvRE7wT3ACYssBggpyThIRMCAFaEzHhOiQWumfGFBQGQY0kB9EKSCsVCyKpQxUMhdOEMj4Vi91wIGX2uyNJtwTDHAgbjOUBJ/T50ETDAzCn0CiRpLkSd2VW1rqZR6uOpzHoWl40EkmkIlTIhNJc0bUSlSNNtCaZCKGtpyDZimXB92uhBhTEAHzx/BuQ8Isb62Dti16c7PahrNnbovFhXLGQaau4oqDSULDx/BcCl55cEDTUdCqqagWcXbjpqWD8ZWxRUGq5ZOTYhAXLHV0DU/qCtQLJCkZuM0PHQGThvL152JJh5M61SP2CpMpmmgdsTFDJCiaaubq0haQ7Q3xLUZq4NqzS0DNzWxNq8ksgbFmGgwf95oFgijJuB6v9L3Fx2HSg3XeExZxv1xuSEXQt/o8fqg9cDHfB15zuxjRuOETrfu/5b9bhcf+mlRmLgr/cTgp1vqR9c8YlvALcDAPr5jIx+4LKcAAAAAElFTkSuQmCC +data:image/png;base64,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 diff --git a/mobile/locales/en-US/searchplugins/yahoo.xml b/mobile/locales/en-US/searchplugins/yahoo.xml index cceee8748034..6fa29bf2018d 100644 --- a/mobile/locales/en-US/searchplugins/yahoo.xml +++ b/mobile/locales/en-US/searchplugins/yahoo.xml @@ -5,7 +5,7 @@ Yahoo UTF-8 -data:image/png;base64,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 +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAACJ5JREFUeAHtXWlsVFUUPm9mOt2gLWKXIFtLKRZIGoIS/CEJa7ASEExdECPYVhYjiAlq0CAgIJBIABUFWkqKEaGiEKRAoAIKBEGBmNJCW2ihQGnL0oW2dJmO9wyly3DPw/bN2+SehPS9c+bee873vbvf95CgSZzglOIgPZ7dJjgB+rO/nR/YxF+PIFApAWSxnJLSIDZZAonBDMB0AHFwKMwJNd8zEkbivRB1EWDgZ0jgOyUNht+w4JMvwFcXcPfc8UFvwlySXob0RADnBvcfiXv1EWDNT6JFAie2+0L0QSCBNUGuDlef4h/zUhF7C8NAjHb0exA6IwFCdERAEKAj+Fi0IEAQoDMCOhcvaoAgQGcEdC5e1ABBgM4I6Fy8qAGCAJ0R0Ll4UQN0JsCmdvmDYoMh8tlAuH6hCipK61xbQE9084GQcF8IjfCDAxsK4cKxO2q7wc1/8LgQwH/Fl6qhtKAaHA1OsNkt4O1vheCevvBPxk3I/l1d31Qn4OKpcpidGgOdu9q5IPSOCYAPBx+FRgfXrJrS5m2B+K/6Q0hvP24ZJYyQX1Zc5No8qVS9CcKnPnXeedJnJGBUYk/SrpZh7Lu9SPCxzOTZWVBX3ahW8c35qk4AlnQo5SpkHr7VXKj7xWufR4F/F9UrY3OxASF2iFsQ2XzvfnFyVzH8vbvEXa3KvSYEoOfrp2dCfS2/nQl40g6vLIxSJUBepm980Q/8A714JqitdsCm2ee4NjWUmhFQlFMFO5bRberYWT2he/9OasTYJs/IIYEwYlr3NrrWN2mLc+HmlXutVapea0YARrFz+UW4dv4uNyCrzQLTVkdzbZ5SSizahK8HgCS5TuM8lG1hViXsXpX/kF5NhaYENNQ5Yf2MTDKemNHB8Mz4ENKu1DDi7R5sSBxEZrNhZiY46l3npcjfeNqgKQHofNaR23BkyzUyjqmrogGHiJ4W7OSx7afkcOpV1cf8vLI9HymvFDdd6rxsqCqvd9Pevw3r4w8T5oVzbUqUk5f1A+zseXL3Tr3sUJmXxlM6XQgoL66DrZ/kkDFMmh8Jwb19SXt7Ddjxjn6Hnmv8MP8CVJSwWboOogsBGOf+by/DpdPl3JC9fa2sQ8bzwcoFO97EdQPBwo6g8ST3ZBlbDrnCM2mi040AJ5tkbpyVCU4nv9MbMiEUcB1JqYyZ0RP6DA7kZuNwOAE7XvRFL9GNAAw4989yOJhUSMYev7Y/ePl03MWAYDtMXkp3vPvXXYb80xVk+VoYOh6dh7zDvqC6gu6QX/ooosMlTVnBZrxB/Blvxc06+HEB3Q91uNB2JtSdAFys+2lJHun2xI/7QEhE+zvkqOeCYPhUesa79dMLUF3WQJarlUF3AjDQ9DUFUJRXxY3Z7mOF+LUDuDZKabGyGe839Iw3/2wFHNxIN31UvmroDUEAzpA3f5BNxjf4xRAYMjGUtLsbxszsBRGD+B0v/nbTnHO6dryt/TUEAegQLv+e2Vfa2rc219gh+3Rij/YjJCjMDq8voVdWj20v0mXGS7ltGALQwZT3s6Chnj8m7NrdF15d1JeKo1n/1pfR9FJzjQO2sFm4kcRQBOC+cfraAhKf2Dnh0CuGfp1h4Iiu8Pzkp8j0u1Ze0nSpmXSklcFQBKBfaYvzoKy4tpWLLZdWqwTTvxvY9G5nix6vrF6Sa6m5rbbl7mZhDexcSe9HtPxS2yvDEVBT0QC4NkNJ1NAu3OHluLnh0D2a3tDBfWkt9ngpvym94QhAR39je8h5p8oon13Lyn6BLXvIXXv4yO7xZv1xG45vKyLz09NgSAKALQ/hqQRKgkK94c2VTzebceHOx7+FkGYDu2hsdELKHDqv1r/V49qYBDAkck+UwYmfb5CYjErsAdHDurgW7IZOCiN/l5FcCPln9F3vIZ1jBvai9h7+cqRcKo1suASxJmsYeHnzx//Xc+6yztcCoeH8w1W46fNe3yP3T+Rp5HN7izFsDcBASi7VwK+rC8iYukV1IsHHRGmLcg0NPvpoaALQwR1L6WEp2inB2rH368uU2TB6wxNwr9IhOyylkMS1Ja1POFC+yOkNTwA6f2jzVXL7khfc2f2lcHoPva7ES6OXzhQE4Jbhpv84lHQ0NELKXOMOO92JNgUB6PT5o3fgeNqjJ1P71l2Ba9n8vQX34I1wbxoCEKxtn+W4JlYUcJW36mD7Qv23GSn/eHpTEYBP9il2dJwSPPxbdUf/bUbKP57eVARgAJmH6PcMSvKreTEaWmc6Aupr+Rs2iLKFLVebTUxHAHXCDYG32gQBqj+AeNSQEkEAhYwH9RJxxhOLsIga4EGkiaxsbOuREnzLxmxiOo99OvM3XhB4PJBlNjEdAXLtvKgBGjx+ckNN0QfoTIBc7dDAtQ4V8b9qguRqR4fQ0SCR6QiQA5l620YDHDtchOkIwBNwlIhOmELGg3rq/A8WYbPT5HjQBY9mZboagB9TosTGjqiYTUznsUXGY7nmyajEyIRjTJeJt1pdzuIhLbOJ6TyWW4wTfYAGj5/cMFT0ARoQILsaKjNE1cC1DhVhuibIzr4jQYnoAyhkPKi3+9EE4Dc/zSam89hL5mNOcs2TUYkxHQFyK55mnAfQ20tGfWSa/MJPzdRWNbhe0MBagaclzDgKMh0By8f/BfeqHFDJvnbS/J0ftgQUFOYN3jL9g1GfJ9MRUJJf8zCW7CWrsiL+u8UP/9hYGtP1AcaCT7k3ggDlGCrKQRCgCD7liQUByjFUlIMgQBF8yhMLApRjqCgHQYAi+JQnFgQox1BRDoIARfApTywIUI6hohyQgEpFOYjEShCoxPdNzPNauZJQDZgWsccakGRA3x4Xl5IkJzilONh7gP0d+bhEbYQ4JZAy0uCF0awJkpwS+E5BhREcexx8QKybMGfYN8n9mpAez24T2PI6/vcV9BdSHyQSf9uDQGVTf5uUBrHJ+OBj4n8BJ5EPp7ErQgIAAAAASUVORK5CYII= diff --git a/python/mozbuild/mozbuild/artifacts.py b/python/mozbuild/mozbuild/artifacts.py index fb0e2bce8c51..49b6612f2327 100644 --- a/python/mozbuild/mozbuild/artifacts.py +++ b/python/mozbuild/mozbuild/artifacts.py @@ -325,7 +325,6 @@ class Artifacts(object): n = os.path.join(distdir, 'bin', os.path.basename(info.filename)) fh = FileAvoidWrite(n, mode='r') shutil.copyfileobj(zf.open(info), fh) - fh.write(zf.open(info).read()) file_existed, file_updated = fh.close() self.log(logging.INFO, 'artifact', {'updating': 'Updating' if file_updated else 'Not updating', 'filename': n}, diff --git a/toolkit/devtools/client/dbg-client.jsm b/toolkit/devtools/client/dbg-client.jsm index 4c36ae72daa5..52693e79b5eb 100644 --- a/toolkit/devtools/client/dbg-client.jsm +++ b/toolkit/devtools/client/dbg-client.jsm @@ -511,7 +511,8 @@ DebuggerClient.prototype = { executeSoon(() => aOnResponse({ from: workerClient.actor, type: "attached", - isFrozen: workerClient.isFrozen + isFrozen: workerClient.isFrozen, + url: workerClient.url }, workerClient)); return; } @@ -1379,6 +1380,8 @@ function WorkerClient(aClient, aForm) { this.addListener("close", this._onClose); this.addListener("freeze", this._onFreeze); this.addListener("thaw", this._onThaw); + + this.traits = {}; } WorkerClient.prototype = { @@ -1454,6 +1457,10 @@ WorkerClient.prototype = { this._isFrozen = false; }, + reconfigure: function () { + return Promise.resolve(); + }, + events: ["close", "freeze", "thaw"] };