diff --git a/Makefile.in b/Makefile.in index f1cd311f80b2..af730e544771 100644 --- a/Makefile.in +++ b/Makefile.in @@ -3,7 +3,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/. -ifndef .PYMAKE ifeq (,$(MAKE_VERSION)) $(error GNU Make is required) endif @@ -11,7 +10,6 @@ make_min_ver := 3.81 ifneq ($(make_min_ver),$(firstword $(sort $(make_min_ver) $(MAKE_VERSION)))) $(error GNU Make $(make_min_ver) or higher is required) endif -endif export TOPLEVEL_BUILD := 1 diff --git a/b2g/gaia/Makefile.in b/b2g/gaia/Makefile.in index 368e83e66d71..68ec5709d4f9 100644 --- a/b2g/gaia/Makefile.in +++ b/b2g/gaia/Makefile.in @@ -4,13 +4,6 @@ GAIA_PATH := gaia/profile -ifdef .PYMAKE -# For use of GNU make in pymake builds. -GAIA_MAKE=$(GMAKE) -else -GAIA_MAKE=$(MAKE) -endif - # This is needed to avoid making run-b2g depend on mozglue WRAP_LDFLAGS := @@ -19,6 +12,6 @@ GENERATED_DIRS += $(DIST)/bin/$(GAIA_PATH) include $(topsrcdir)/config/rules.mk libs:: - +$(GAIA_MAKE) -j1 -C $(GAIADIR) clean - +$(GAIA_MAKE) -j1 -C $(GAIADIR) profile + +$(MAKE) -j1 -C $(GAIADIR) clean + +$(MAKE) -j1 -C $(GAIADIR) profile (cd $(GAIADIR)/profile && tar $(TAR_CREATE_FLAGS) - .) | (cd $(abspath $(DIST))/bin/$(GAIA_PATH) && tar -xf -) diff --git a/browser/base/content/browser-social.js b/browser/base/content/browser-social.js index 78e3688e3710..4388a4ef66be 100644 --- a/browser/base/content/browser-social.js +++ b/browser/base/content/browser-social.js @@ -90,6 +90,7 @@ SocialUI = { if (!this._initialized) { return; } + SocialSidebar.saveWindowState(); Services.obs.removeObserver(this, "social:ambient-notification-changed"); Services.obs.removeObserver(this, "social:profile-changed"); @@ -710,6 +711,11 @@ SocialSidebar = { }, restoreWindowState: function() { + // Window state is used to allow different sidebar providers in each window. + // We also store the provider used in a pref as the default sidebar to + // maintain that state for users who do not restore window state. The + // existence of social.sidebar.provider means the sidebar is open with that + // provider. this._initialized = true; if (!this.canShow) return; @@ -737,13 +743,22 @@ SocialSidebar = { let data = SessionStore.getWindowValue(window, "socialSidebar"); // if this window doesn't have it's own state, use the state from the opener if (!data && window.opener && !window.opener.closed) { - data = SessionStore.getWindowValue(window.opener, "socialSidebar"); + try { + data = SessionStore.getWindowValue(window.opener, "socialSidebar"); + } catch(e) { + // Window is not tracked, which happens on osx if the window is opened + // from the hidden window. That happens when you close the last window + // without quiting firefox, then open a new window. + } } if (data) { data = JSON.parse(data); document.getElementById("social-sidebar-browser").setAttribute("origin", data.origin); if (!data.hidden) this.show(data.origin); + } else if (Services.prefs.prefHasUserValue("social.sidebar.provider")) { + // no window state, use the global state if it is available + this.show(Services.prefs.getCharPref("social.sidebar.provider")); } }, @@ -754,7 +769,18 @@ SocialSidebar = { "hidden": broadcaster.hidden, "origin": sidebarOrigin }; - SessionStore.setWindowValue(window, "socialSidebar", JSON.stringify(data)); + + // Save a global state for users who do not restore state. + if (broadcaster.hidden) + Services.prefs.clearUserPref("social.sidebar.provider"); + else + Services.prefs.setCharPref("social.sidebar.provider", sidebarOrigin); + + try { + SessionStore.setWindowValue(window, "socialSidebar", JSON.stringify(data)); + } catch(e) { + // window not tracked during uninit + } }, setSidebarVisibilityState: function(aEnabled) { diff --git a/browser/base/content/test/general/browser_urlbar_search_healthreport.js b/browser/base/content/test/general/browser_urlbar_search_healthreport.js index 785ecbe24bd2..cc5d2451a8fc 100644 --- a/browser/base/content/test/general/browser_urlbar_search_healthreport.js +++ b/browser/base/content/test/general/browser_urlbar_search_healthreport.js @@ -3,15 +3,13 @@ "use strict"; -function test() { - waitForExplicitFinish(); +add_task(function* test_healthreport_search_recording() { try { let cm = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); cm.getCategoryEntry("healthreport-js-provider-default", "SearchesProvider"); } catch (ex) { // Health Report disabled, or no SearchesProvider. ok(true, "Firefox Health Report is not enabled."); - finish(); return; } @@ -20,72 +18,63 @@ function test() { .wrappedJSObject .healthReporter; ok(reporter, "Health Reporter available."); - reporter.onInit().then(function onInit() { - let provider = reporter.getProvider("org.mozilla.searches"); - ok(provider, "Searches provider is available."); - let m = provider.getMeasurement("counts", 3); + yield reporter.onInit(); + let provider = reporter.getProvider("org.mozilla.searches"); + ok(provider, "Searches provider is available."); + let m = provider.getMeasurement("counts", 3); - m.getValues().then(function onData(data) { - let now = new Date(); - let oldCount = 0; + let data = yield m.getValues(); + let now = new Date(); + let oldCount = 0; - // This will to be need changed if default search engine is not Google. - let field = "google.urlbar"; + // This will to be need changed if default search engine is not Google. + let field = "google.urlbar"; - if (data.days.hasDay(now)) { - let day = data.days.getDay(now); - if (day.has(field)) { - oldCount = day.get(field); - } - } + if (data.days.hasDay(now)) { + let day = data.days.getDay(now); + if (day.has(field)) { + oldCount = day.get(field); + } + } - let tab = gBrowser.addTab(); - gBrowser.selectedTab = tab; + let tab = gBrowser.addTab(); + gBrowser.selectedTab = tab; - let searchStr = "firefox health report"; - let expectedURL = Services.search.currentEngine. - getSubmission(searchStr, "", "keyword").uri.spec; + let searchStr = "firefox health report"; + let expectedURL = Services.search.currentEngine. + getSubmission(searchStr, "", "keyword").uri.spec; - // Expect the search URL to load but stop it as soon as it starts. - let loadPromise = waitForDocLoadAndStopIt(expectedURL); + // Expect the search URL to load but stop it as soon as it starts. + let docLoadPromise = waitForDocLoadAndStopIt(expectedURL); - // Meanwhile, poll for the new measurement. - let count = 0; - let measurementDeferred = Promise.defer(); - function getNewMeasurement() { - if (count++ >= 10) { - ok(false, "Timed out waiting for new measurement"); - measurementDeferred.resolve(); - return; - } - m.getValues().then(function onData(data) { - if (data.days.hasDay(now)) { - let day = data.days.getDay(now); - if (day.has(field)) { - let newCount = day.get(field); - if (newCount > oldCount) { - is(newCount, oldCount + 1, - "Exactly one search has been recorded."); - measurementDeferred.resolve(); - return; - } - } - } - executeSoon(getNewMeasurement); - }); - } - executeSoon(getNewMeasurement); + // Trigger the search. + gURLBar.value = searchStr; + gURLBar.handleCommand(); - // Trigger the search. - gURLBar.value = searchStr; - gURLBar.handleCommand(); + yield docLoadPromise; - // Wait for the page load and new measurement. - Promise.all([loadPromise, measurementDeferred.promise]).then(() => { - gBrowser.removeTab(tab); - finish(); - }); - }); - }); -} + data = yield m.getValues(); + ok(data.days.hasDay(now), "We have a search measurement for today."); + let day = data.days.getDay(now); + ok(day.has(field), "Have a search count for the urlbar."); + let newCount = day.get(field); + is(newCount, oldCount + 1, "We recorded one new search."); + // We should record the default search engine if Telemetry is enabled. + let oldTelemetry = Services.prefs.getBoolPref("toolkit.telemetry.enabled"); + Services.prefs.setBoolPref("toolkit.telemetry.enabled", true); + + m = provider.getMeasurement("engines", 1); + yield provider.collectDailyData(); + data = yield m.getValues(); + + ok(data.days.hasDay(now), "Have engines data when Telemetry is enabled."); + day = data.days.getDay(now); + ok(day.has("default"), "We have default engine data."); + is(day.get("default"), "google", "The default engine is reported properly."); + + // Restore. + Services.prefs.setBoolPref("toolkit.telemetry.enabled", oldTelemetry); + + gBrowser.removeTab(tab); +}); diff --git a/browser/base/content/test/social/browser_social_window.js b/browser/base/content/test/social/browser_social_window.js index e93069ebc5c6..1978a6a906d0 100644 --- a/browser/base/content/test/social/browser_social_window.js +++ b/browser/base/content/test/social/browser_social_window.js @@ -30,17 +30,20 @@ function openWindowAndWaitForInit(parentWin, callback) { }, topic, false); } +function closeWindow(w, cb) { + waitForNotification("domwindowclosed", cb); + w.close(); +} + function closeOneWindow(cb) { let w = createdWindows.pop(); - if (!w) { + if (!w || w.closed) { cb(); return; } - waitForCondition(function() w.closed, - function() { - info("window closed, " + createdWindows.length + " windows left"); - closeOneWindow(cb); - }, "window did not close"); + closeWindow(w, function() { + closeOneWindow(cb); + }); w.close(); } @@ -126,6 +129,51 @@ let tests = { }, cbnext); }, + testGlobalState: function(cbnext) { + setManifestPref("social.manifest.test", manifest); + ok(!SocialSidebar.opened, "sidebar is closed initially"); + ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "global state unset"); + // mimick no session state in opener so we exercise the global state via pref + SessionStore.deleteWindowValue(window, "socialSidebar"); + ok(!SessionStore.getWindowValue(window, "socialSidebar"), "window state unset"); + SocialService.addProvider(manifest, function() { + openWindowAndWaitForInit(window, function(w1) { + w1.SocialSidebar.show(); + waitForCondition(function() w1.SocialSidebar.opened, + function() { + ok(Services.prefs.prefHasUserValue("social.sidebar.provider"), "global state set"); + ok(!SocialSidebar.opened, "1. main sidebar is still closed"); + ok(w1.SocialSidebar.opened, "1. window sidebar is open"); + closeWindow(w1, function() { + // this time, the global state should cause the sidebar to be opened + // in the new window + openWindowAndWaitForInit(window, function(w1) { + ok(!SocialSidebar.opened, "2. main sidebar is still closed"); + ok(w1.SocialSidebar.opened, "2. window sidebar is open"); + w1.SocialSidebar.hide(); + ok(!w1.SocialSidebar.opened, "2. window sidebar is closed"); + ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "2. global state unset"); + // global state should now be no sidebar gets opened on new window + closeWindow(w1, function() { + ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "3. global state unset"); + ok(!SocialSidebar.opened, "3. main sidebar is still closed"); + openWindowAndWaitForInit(window, function(w1) { + ok(!Services.prefs.prefHasUserValue("social.sidebar.provider"), "4. global state unset"); + ok(!SocialSidebar.opened, "4. main sidebar is still closed"); + ok(!w1.SocialSidebar.opened, "4. window sidebar is closed"); + SocialService.removeProvider(manifest.origin, function() { + Services.prefs.clearUserPref("social.manifest.test"); + cbnext(); + }); + }); + }); + }); + }); + }); + }); + }); + }, + // Check per window sidebar functionality, including migration from using // prefs to using session state, and state inheritance of windows (new windows // inherit state from the opener). diff --git a/browser/experiments/Experiments.jsm b/browser/experiments/Experiments.jsm index 8a8afac6f410..288814df1ea1 100644 --- a/browser/experiments/Experiments.jsm +++ b/browser/experiments/Experiments.jsm @@ -597,6 +597,7 @@ Experiments.Experiments.prototype = { active: experiment.enabled, endDate: experiment.endDate.getTime(), detailURL: experiment._homepageURL, + branch: experiment.branch, }); } @@ -628,6 +629,54 @@ Experiments.Experiments.prototype = { return info; }, + /** + * Experiment "branch" support. If an experiment has multiple branches, it + * can record the branch with the experiment system and it will + * automatically be included in data reporting (FHR/telemetry payloads). + */ + + /** + * Set the experiment branch for the specified experiment ID. + * @returns Promise<> + */ + setExperimentBranch: Task.async(function*(id, branchstr) { + yield this._loadTask; + let e = this._experiments.get(id); + if (!e) { + throw new Error("Experiment not found"); + } + e.branch = String(branchstr); + this._dirty = true; + Services.obs.notifyObservers(null, EXPERIMENTS_CHANGED_TOPIC, null); + yield this._run(); + }), + /** + * Get the branch of the specified experiment. If the experiment is unknown, + * throws an error. + * + * @param id The ID of the experiment. Pass null for the currently running + * experiment. + * @returns Promise + * @throws Error if the specified experiment ID is unknown, or if there is no + * current experiment. + */ + getExperimentBranch: Task.async(function*(id=null) { + yield this._loadTask; + let e; + if (id) { + e = this._experiments.get(id); + if (!e) { + throw new Error("Experiment not found"); + } + } else { + e = this._getActiveExperiment(); + if (e === null) { + throw new Error("No active experiment"); + } + } + return e.branch; + }), + /** * Determine whether another date has the same UTC day as now(). */ @@ -1013,6 +1062,17 @@ Experiments.Experiments.prototype = { return e.id; }, + getActiveExperimentBranch: function() { + if (!this._experiments) { + return null; + } + let e = this._getActiveExperiment(); + if (!e) { + return null; + } + return e.branch; + }, + _getActiveExperiment: function () { let enabled = [experiment for ([,experiment] of this._experiments) if (experiment._enabled)]; @@ -1258,6 +1318,8 @@ Experiments.ExperimentEntry = function (policy) { this._lastChangedDate = null; // Has this experiment failed to activate before? this._failedStart = false; + // The experiment branch + this._branch = null; // We grab these from the addon after download. this._name = null; @@ -1306,6 +1368,7 @@ Experiments.ExperimentEntry.prototype = { "_addonId", "_startDate", "_endDate", + "_branch", ]), DATE_KEYS: new Set([ @@ -1313,6 +1376,10 @@ Experiments.ExperimentEntry.prototype = { "_endDate", ]), + UPGRADE_KEYS: new Map([ + ["_branch", null], + ]), + ADDON_CHANGE_NONE: 0, ADDON_CHANGE_INSTALL: 1, ADDON_CHANGE_UNINSTALL: 2, @@ -1344,6 +1411,14 @@ Experiments.ExperimentEntry.prototype = { return this._manifestData.id; }, + get branch() { + return this._branch; + }, + + set branch(v) { + this._branch = v; + }, + get startDate() { return this._startDate; }, @@ -1376,6 +1451,12 @@ Experiments.ExperimentEntry.prototype = { * @return boolean Whether initialization succeeded. */ initFromCacheData: function (data) { + for (let [key, dval] of this.UPGRADE_KEYS) { + if (!(key in data)) { + data.set(key, dval); + } + } + for (let key of this.SERIALIZE_KEYS) { if (!(key in data) && !this.DATE_KEYS.has(key)) { this._log.error("initFromCacheData() - missing required key " + key); @@ -1970,6 +2051,9 @@ let stripDateToMidnight = function (d) { function ExperimentsLastActiveMeasurement1() { Metrics.Measurement.call(this); } +function ExperimentsLastActiveMeasurement2() { + Metrics.Measurement.call(this); +} const FIELD_DAILY_LAST_TEXT = {type: Metrics.Storage.FIELD_DAILY_LAST_TEXT}; @@ -1983,6 +2067,17 @@ ExperimentsLastActiveMeasurement1.prototype = Object.freeze({ lastActive: FIELD_DAILY_LAST_TEXT, } }); +ExperimentsLastActiveMeasurement2.prototype = Object.freeze({ + __proto__: Metrics.Measurement.prototype, + + name: "info", + version: 2, + + fields: { + lastActive: FIELD_DAILY_LAST_TEXT, + lastActiveBranch: FIELD_DAILY_LAST_TEXT, + } +}); this.ExperimentsProvider = function () { Metrics.Provider.call(this); @@ -1997,6 +2092,7 @@ ExperimentsProvider.prototype = Object.freeze({ measurementTypes: [ ExperimentsLastActiveMeasurement1, + ExperimentsLastActiveMeasurement2, ], _OBSERVERS: [ @@ -2040,8 +2136,8 @@ ExperimentsProvider.prototype = Object.freeze({ this._experiments = Experiments.instance(); } - let m = this.getMeasurement(ExperimentsLastActiveMeasurement1.prototype.name, - ExperimentsLastActiveMeasurement1.prototype.version); + let m = this.getMeasurement(ExperimentsLastActiveMeasurement2.prototype.name, + ExperimentsLastActiveMeasurement2.prototype.version); return this.enqueueStorageOperation(() => { return Task.spawn(function* recordTask() { @@ -2055,6 +2151,11 @@ ExperimentsProvider.prototype = Object.freeze({ this._log.info("Recording last active experiment: " + todayActive.id); yield m.setDailyLastText("lastActive", todayActive.id, this._experiments._policy.now()); + let branch = todayActive.branch; + if (branch) { + yield m.setDailyLastText("lastActiveBranch", branch, + this._experiments._policy.now()); + } }.bind(this)); }); }, diff --git a/browser/experiments/test/xpcshell/head.js b/browser/experiments/test/xpcshell/head.js index a45020303ee3..86df15e4fdfc 100644 --- a/browser/experiments/test/xpcshell/head.js +++ b/browser/experiments/test/xpcshell/head.js @@ -76,6 +76,7 @@ const FAKE_EXPERIMENTS_1 = [ description: "experiment 1", active: true, detailUrl: "https://dummy/experiment1", + branch: "foo", }, ]; @@ -87,6 +88,7 @@ const FAKE_EXPERIMENTS_2 = [ active: false, endDate: new Date(2014, 2, 11, 2, 4, 35, 42).getTime(), detailUrl: "https://dummy/experiment2", + branch: null, }, { id: "id1", @@ -95,6 +97,7 @@ const FAKE_EXPERIMENTS_2 = [ active: false, endDate: new Date(2014, 2, 10, 0, 0, 0, 0).getTime(), detailURL: "https://dummy/experiment1", + branch: null, }, ]; diff --git a/browser/experiments/test/xpcshell/test_api.js b/browser/experiments/test/xpcshell/test_api.js index 3a5304ce7837..ab0be9d3a400 100644 --- a/browser/experiments/test/xpcshell/test_api.js +++ b/browser/experiments/test/xpcshell/test_api.js @@ -171,6 +171,14 @@ add_task(function* test_getExperiments() { let addons = yield getExperimentAddons(); Assert.equal(addons.length, 0, "Precondition: No experiment add-ons are installed."); + try { + let b = yield experiments.getExperimentBranch(); + Assert.ok(false, "getExperimentBranch should fail with no experiment"); + } + catch (e) { + Assert.ok(true, "getExperimentBranch correctly threw"); + } + // Trigger update, clock set for experiment 1 to start. now = futureDate(startDate1, 5 * MS_IN_ONE_DAY); @@ -196,6 +204,19 @@ add_task(function* test_getExperiments() { "Property " + k + " should match reference data."); } + let b = yield experiments.getExperimentBranch(); + Assert.strictEqual(b, null, "getExperimentBranch should return null by default"); + + b = yield experiments.getExperimentBranch(EXPERIMENT1_ID); + Assert.strictEqual(b, null, "getExperimentsBranch should return null (with id)"); + + yield experiments.setExperimentBranch(EXPERIMENT1_ID, "foo"); + b = yield experiments.getExperimentBranch(); + Assert.strictEqual(b, "foo", "getExperimentsBranch should return the set value"); + + Assert.equal(observerFireCount, ++expectedObserverFireCount, + "Experiments observer should have been called."); + Assert.equal(gTimerScheduleOffset, 10 * MS_IN_ONE_DAY, "Experiment re-evaluation should have been scheduled correctly."); diff --git a/browser/experiments/test/xpcshell/test_cache.js b/browser/experiments/test/xpcshell/test_cache.js index cba484bf1953..2de87ba993b3 100644 --- a/browser/experiments/test/xpcshell/test_cache.js +++ b/browser/experiments/test/xpcshell/test_cache.js @@ -190,6 +190,13 @@ add_task(function* test_cache() { checkExperimentListsEqual(experimentListData.slice(1), list); checkExperimentSerializations(experiments._experiments.values()); + let branch = yield experiments.getExperimentBranch(EXPERIMENT1_ID); + Assert.strictEqual(branch, null); + + yield experiments.setExperimentBranch(EXPERIMENT1_ID, "testbranch"); + branch = yield experiments.getExperimentBranch(EXPERIMENT1_ID); + Assert.strictEqual(branch, "testbranch"); + // Re-init, clock set for experiment 1 to stop. now = futureDate(now, 20 * MS_IN_ONE_DAY); @@ -207,6 +214,9 @@ add_task(function* test_cache() { checkExperimentListsEqual(experimentListData.slice(1), list); checkExperimentSerializations(experiments._experiments.values()); + branch = yield experiments.getExperimentBranch(EXPERIMENT1_ID); + Assert.strictEqual(branch, "testbranch"); + // Re-init, clock set for experiment 2 to start. now = futureDate(startDates[1], 20 * MS_IN_ONE_DAY); diff --git a/browser/experiments/test/xpcshell/test_healthreport.js b/browser/experiments/test/xpcshell/test_healthreport.js index 965348af9b54..f4e9bcbd2f85 100644 --- a/browser/experiments/test/xpcshell/test_healthreport.js +++ b/browser/experiments/test/xpcshell/test_healthreport.js @@ -9,6 +9,8 @@ Cu.import("resource:///modules/experiments/Experiments.jsm"); Cu.import("resource://testing-common/services/healthreport/utils.jsm"); Cu.import("resource://testing-common/services-common/logging.js"); +const kMeasurementVersion = 2; + function getStorageAndProvider(name) { return Task.spawn(function* get() { let storage = yield Metrics.Storage(name); @@ -53,7 +55,7 @@ add_task(function* test_collect() { // Initial state should not report anything. yield provider.collectDailyData(); - let m = provider.getMeasurement("info", 1); + let m = provider.getMeasurement("info", kMeasurementVersion); let values = yield m.getValues(); Assert.equal(values.days.size, 0, "Have no data if no experiments known."); @@ -69,6 +71,8 @@ add_task(function* test_collect() { let day = values.days.getDay(now); Assert.ok(day.has("lastActive"), "Has lastActive field."); Assert.equal(day.get("lastActive"), "id2", "Last active ID is sane."); + Assert.strictEqual(day.get("lastActiveBranch"), undefined, + "no branch should be set yet"); // Making an experiment active replaces the lastActive value. replaceExperiments(provider._experiments, FAKE_EXPERIMENTS_1); @@ -76,6 +80,8 @@ add_task(function* test_collect() { values = yield m.getValues(); day = values.days.getDay(now); Assert.equal(day.get("lastActive"), "id1", "Last active ID is the active experiment."); + Assert.equal(day.get("lastActiveBranch"), "foo", + "Experiment branch should be visible"); // And make sure the observer works. replaceExperiments(provider._experiments, FAKE_EXPERIMENTS_2); diff --git a/browser/locales/en-US/searchplugins/eBay.xml b/browser/locales/en-US/searchplugins/eBay.xml index c6eb7734e2bc..d26245928538 100644 --- a/browser/locales/en-US/searchplugins/eBay.xml +++ b/browser/locales/en-US/searchplugins/eBay.xml @@ -7,6 +7,8 @@ eBay - Online auctions ISO-8859-1 data:image/x-icon;base64,AAABAAIAEBAAAAAAAAB6AQAAJgAAACAgAAAAAAAAQgMAAKABAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAFBSURBVDjLtZPdK0MBGIf3J5Babhx3rinFBWuipaUskX9DYvkopqgV90q5UJpyp0OKrUWM2VrRsS9D0zZKHGaOnW1nj4vtypVtPPe/533r9746QAAOAJXfo5Yzgg44pHrcugon/6Sgo0b+XuAOZ2iZiVQmyPoDpIwmUkYTzqM7GsdDdC7F6Lbf8pzOkfWOouzqeZem2b+2AqAV8zjD8yVBqqcf2b7C66yNiMGMfixIQSvi8Mp0LEbR5ADq1QSKWM+Gx0RC9nOZ2GLzwlIWdPWiuNzk4w/EpThNkyEAXKEP2ud8KGId2sspilhPMrmNwzfCuqePr/xbSfC5I/I0MMSj2YJ3z49gDdO2cEOrLUowJpE9G0QRG1ClKbR0EIdvmOPYcnUtnN+vsnZiQC1k/qnGagQ1n3LNzySUJZVskitnmr8BlQG7T2hvgxsAAAAASUVORK5CYIKJUE5HDQoaCgAAAA1JSERSAAAAIAAAACAIBgAAAHN6evQAAAMJSURBVFjD7ZddSFNhGMeHXXQTZFFCWfR1pRhUECQlBdWVToo+6KYu1KigtDASG5qUfZgFZvahEDosECPDktKZS1FL+1DRnEvdUptjug91X2dnZzv/3vO6OZbWnR4v9sADL+fs7P97/s/znu2VAJD4UkpSSdKG+QubTyPBr+sXz8XCR64fIAHihVTis0SsUAoAVhEBrBKIHCGAEMB/ARi3F5LkbpS2WMRzYEEBXC2tsD6T03R9agsCGLNyqPw6CXmrBT06JvhbPHZwmkdwtR0B138PPKOHgzXD5jLAy3tmibo4K9weZwDAazJj/FQKRnfugfHMeRiTz0K3Ixam1HQKcPC+Fisu9NK1P08Uj4DleHgMdXC+WQ7nu3UEOhFMfTQcVUvQ1H4IN2sj8H2k7K+2TqCc3GseyA8AmDOzMBq7D9bS8sAr6nEJdNt3UbHVF1XQGtmZew8bTPT6tWoD3KpsUvlR8NxUoEICMvl6KQo+xqCwcRs4T8Ax5c8bFExjbAgAjO7aS8VsLypgq3g5nWStjztAhWRVhqAqeB6IuKTClkw1eNYEbrCQQBwD8yGGOsAooogLYejQPKBi7UPF9DkH+ezd+o141ZkUPAOC+L9SAMivNc7q46YMNSLTe4n1kaQF4XD3ZIDTPgU3XEYciKcAHrsGJS1xKFBGgyVzouiT4VbdGhjt/cEA5isyKsaz7jl3we7bg7Rqf6j0LoSldON4wWcqJDgQNGTN++l13vELA+MK6kKd6iryFOvxtidt9i5gO7owdjKJQliflNAU1pas6xQgnAzg1ux+lJEdILixNr0Pq9JUUA8NwVG9DM73G0jlcnh+V4BpjIWzJmIGQIjnXw5TiDuKSEwxurm3ITc8DNO51BnrLbIcsrW0dNA6RxgUKU1UdGVqLy5X6qGzTLvlnewiBZyGs3Yz6X8UeaYI3olvZDhzwLumZ+eHvooCCC0Q5VUsb4unwycM4YIDqA01tPqmgbzQr2EIYPECiPm33LYoDiZSsY9moh9O/Znoa4d9HkXtPg2pX/cPKCoRQ+ocZa4AAAAASUVORK5CYII= +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAAaCAYAAADovjFxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjQ0MDYxRTZDQjUyNTExRTNCNzdEOTU4N0NCMjI3MEFDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjQ0MDYxRTZEQjUyNTExRTNCNzdEOTU4N0NCMjI3MEFDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NDQwNjFFNkFCNTI1MTFFM0I3N0Q5NTg3Q0IyMjcwQUMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NDQwNjFFNkJCNTI1MTFFM0I3N0Q5NTg3Q0IyMjcwQUMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7+A48PAAAMr0lEQVR42txYaZBV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 +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAA0CAYAAABGkOCVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkE4OUIxMDhEQjUyNjExRTNCNzdEOTU4N0NCMjI3MEFDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkE4OUIxMDhFQjUyNjExRTNCNzdEOTU4N0NCMjI3MEFDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTg5QjEwOEJCNTI2MTFFM0I3N0Q5NTg3Q0IyMjcwQUMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTg5QjEwOENCNTI2MTFFM0I3N0Q5NTg3Q0IyMjcwQUMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7A0O4yAAAeb0lEQVR42uxdCZRd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 diff --git a/browser/locales/en-US/searchplugins/google.xml b/browser/locales/en-US/searchplugins/google.xml index 7af19a82fe70..95588cc4bf6c 100644 --- a/browser/locales/en-US/searchplugins/google.xml +++ b/browser/locales/en-US/searchplugins/google.xml @@ -7,6 +7,8 @@ Google Search UTF-8 data:image/x-icon;base64,AAABAAIAEBAAAAAAAAB9AQAAJgAAACAgAAAAAAAA8gIAAKMBAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAFESURBVDjLpZNJSwNBEIXnt4lE4kHxovgT9BDwJHqPy0HEEOJBiAuCRg+KUdC4QS4KrpC4gCBGE3NQ48JsnZ6eZ3UOM6gjaePhQU93v6+qq2q0pqgeJj2S8EdJT1hr0OxBtKCD5iEd8QxDYpvhvOBAuMDKURX9C9aPu4GA1GEVkzvMg10UBfYveWAWgYAP00V01fa+R9M2bA51wJvhIn3qR+ybt3D3JNQBE5sMjCIOLFpoHzOwdsLRO22qA6R6kiZiWwxUvy/PUQZIhYZ1vFM9cvcOOsYNdcBgysISdSJBnZjJMlR0Fw8vAp0xoz5gao/h+NZBy4i/10XGwrPA+hmvDyhVRG2Avu/LwcrkFADZa16L1h330w1RNgc3DiJzCpPYRm1bpveXX11clQR28xwblHpk1vq1iP/5mcoS0CoXDZiL0vsJ+dzfl+3T/VYAAAAASUVORK5CYIKJUE5HDQoaCgAAAA1JSERSAAAAIAAAACAIBgAAAHN6evQAAAK5SURBVFjDxVfrSxRRFJ9/Jta/oyWjF5XQm6D6EkHRgygIIgjUTcueVgqVWSRRkppEUQYWWB8ye1iGWilWlo/Ude489s7M6Zw7D9dlt53dmd29cFiWvXvO77x+51xpaaUsoSxBaUWZQ4ECy5xji2xKZDyCMlMEw6lCNiOSgwZKJK1SkcKeSealfP64t0mBjl4Ow39MkDUL0p2RSROOtqhZdeUEYM1pBl39XCg/fEeFtWcY7G9W4csvUxjlBkCsQ4Nt9QyWVfvT6RsAKXw3aoDGATZeYIt+W1kjw7cJG0RctWDTRebbKd8A6h5pwsDb70ba3w/eUr3wt/cmwgfw6Yft4TNMQaY7o1P2ncm4FT4ANQH/jQBJ2xv7kqIXEADDql8eS3+n8bku7oxNm+EDIM/dU92upb3T/NJGeaNbDx/AsbsLRUY5Xn92caWXY5d8RV6gWllxSg4fAEnTC90DQW13BLlgXR2D3dcUeDVkwOthA1bXspxILWcm3HdThcfvufB26LcJpkOEAz9NKI/lzqpSEC7feol5EWnpSeSlIxCALUkApmULdjUqxQVAQnl3D/X/yQda4QBEq2TYc12By091MQ17Bg3R88nHKlQbVmHvj89awNBLYrwT9zXY2aBAxTkGFdiSxP/Jp6FLDw+AS7GfsdJTJ2EqSO5khD43nGfBARy/ZxOQgZHe7GPM1jzUvChUtmnBAXQPcKGMJp3fdFGq6NByEhiAO4b/YptFfQJwNyQ/bZkVQGcf90Ja25ndIyrKBOa/f8wIpwi3X1G8UcxNu7ozUS7tiH0jBswwS3RIaF1w6LYKU/ML2+8sGnjygQswtKrVIy/Qd9qQP6LnO64q4fPAKpxyZIymHo1jWk6p1ag2BsdNwQMHcC+M5kHFJX+YlPxpVlbCx2mZ5DzPI04k4kUwHHdskU3pH76iftG8yWlkAAAAAElFTkSuQmCC +data:image/png;base64,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 +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAA0CAYAAABGkOCVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjMwQjQ3MEVGRjQxMTExRTM5RkNCRjhFNDM0QjY3OEQ1IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjMwQjQ3MEYwRjQxMTExRTM5RkNCRjhFNDM0QjY3OEQ1Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MzBCNDcwRURGNDExMTFFMzlGQ0JGOEU0MzRCNjc4RDUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzBCNDcwRUVGNDExMTFFMzlGQ0JGOEU0MzRCNjc4RDUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5U94CwAAArpElEQVR42ux9B5hU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 diff --git a/browser/locales/en-US/searchplugins/yahoo.xml b/browser/locales/en-US/searchplugins/yahoo.xml index 3d9f58821bd8..a21ccc2d20ba 100644 --- a/browser/locales/en-US/searchplugins/yahoo.xml +++ b/browser/locales/en-US/searchplugins/yahoo.xml @@ -7,6 +7,7 @@ Yahoo Search UTF-8 data:image/x-icon;base64,AAABAAIAEBAAAAEACAA8DQAAJgAAACAgAAABAAgAowsAAGINAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAAJcEhZcwAACxMAAAsTAQCanBgAAApPaUNDUFBob3Rvc2hvcCBJQ0MgcHJvZmlsZQAAeNqdU2dUU+kWPffe9EJLiICUS29SFQggUkKLgBSRJiohCRBKiCGh2RVRwRFFRQQbyKCIA46OgIwVUSwMigrYB+Qhoo6Do4iKyvvhe6Nr1rz35s3+tdc+56zznbPPB8AIDJZIM1E1gAypQh4R4IPHxMbh5C5AgQokcAAQCLNkIXP9IwEA+H48PCsiwAe+AAF40wsIAMBNm8AwHIf/D+pCmVwBgIQBwHSROEsIgBQAQHqOQqYAQEYBgJ2YJlMAoAQAYMtjYuMAUC0AYCd/5tMAgJ34mXsBAFuUIRUBoJEAIBNliEQAaDsArM9WikUAWDAAFGZLxDkA2C0AMElXZkgAsLcAwM4QC7IACAwAMFGIhSkABHsAYMgjI3gAhJkAFEbyVzzxK64Q5yoAAHiZsjy5JDlFgVsILXEHV1cuHijOSRcrFDZhAmGaQC7CeZkZMoE0D+DzzAAAoJEVEeCD8/14zg6uzs42jrYOXy3qvwb/ImJi4/7lz6twQAAA4XR+0f4sL7MagDsGgG3+oiXuBGheC6B194tmsg9AtQCg6dpX83D4fjw8RaGQudnZ5eTk2ErEQlthyld9/mfCX8BX/Wz5fjz89/XgvuIkgTJdgUcE+ODCzPRMpRzPkgmEYtzmj0f8twv//B3TIsRJYrlYKhTjURJxjkSajPMypSKJQpIpxSXS/2Ti3yz7Az7fNQCwaj4Be5EtqF1jA/ZLJxBYdMDi9wAA8rtvwdQoCAOAaIPhz3f/7z/9R6AlAIBmSZJxAABeRCQuVMqzP8cIAABEoIEqsEEb9MEYLMAGHMEF3MEL/GA2hEIkxMJCEEIKZIAccmAprIJCKIbNsB0qYC/UQB00wFFohpNwDi7CVbgOPXAP+mEInsEovIEJBEHICBNhIdqIAWKKWCOOCBeZhfghwUgEEoskIMmIFFEiS5E1SDFSilQgVUgd8j1yAjmHXEa6kTvIADKC/Ia8RzGUgbJRPdQMtUO5qDcahEaiC9BkdDGajxagm9BytBo9jDah59CraA/ajz5DxzDA6BgHM8RsMC7Gw0KxOCwJk2PLsSKsDKvGGrBWrAO7ifVjz7F3BBKBRcAJNgR3QiBhHkFIWExYTthIqCAcJDQR2gk3CQOEUcInIpOoS7QmuhH5xBhiMjGHWEgsI9YSjxMvEHuIQ8Q3JBKJQzInuZACSbGkVNIS0kbSblIj6SypmzRIGiOTydpka7IHOZQsICvIheSd5MPkM+Qb5CHyWwqdYkBxpPhT4ihSympKGeUQ5TTlBmWYMkFVo5pS3aihVBE1j1pCraG2Uq9Rh6gTNHWaOc2DFklLpa2ildMaaBdo92mv6HS6Ed2VHk6X0FfSy+lH6JfoA/R3DA2GFYPHiGcoGZsYBxhnGXcYr5hMphnTixnHVDA3MeuY55kPmW9VWCq2KnwVkcoKlUqVJpUbKi9Uqaqmqt6qC1XzVctUj6leU32uRlUzU+OpCdSWq1WqnVDrUxtTZ6k7qIeqZ6hvVD+kfln9iQZZw0zDT0OkUaCxX+O8xiALYxmzeCwhaw2rhnWBNcQmsc3ZfHYqu5j9HbuLPaqpoTlDM0ozV7NS85RmPwfjmHH4nHROCecop5fzforeFO8p4ikbpjRMuTFlXGuqlpeWWKtIq1GrR+u9Nq7tp52mvUW7WfuBDkHHSidcJ0dnj84FnedT2VPdpwqnFk09OvWuLqprpRuhu0R3v26n7pievl6Ankxvp955vef6HH0v/VT9bfqn9UcMWAazDCQG2wzOGDzFNXFvPB0vx9vxUUNdw0BDpWGVYZfhhJG50Tyj1UaNRg+MacZc4yTjbcZtxqMmBiYhJktN6k3umlJNuaYppjtMO0zHzczNos3WmTWbPTHXMueb55vXm9+3YFp4Wiy2qLa4ZUmy5FqmWe62vG6FWjlZpVhVWl2zRq2drSXWu627pxGnuU6TTque1mfDsPG2ybaptxmw5dgG2662bbZ9YWdiF2e3xa7D7pO9k326fY39PQcNh9kOqx1aHX5ztHIUOlY63prOnO4/fcX0lukvZ1jPEM/YM+O2E8spxGmdU5vTR2cXZ7lzg/OIi4lLgssulz4umxvG3ci95Ep09XFd4XrS9Z2bs5vC7ajbr+427mnuh9yfzDSfKZ5ZM3PQw8hD4FHl0T8Ln5Uwa9+sfk9DT4FntecjL2MvkVet17C3pXeq92HvFz72PnKf4z7jPDfeMt5ZX8w3wLfIt8tPw2+eX4XfQ38j/2T/ev/RAKeAJQFnA4mBQYFbAvv4enwhv44/Ottl9rLZ7UGMoLlBFUGPgq2C5cGtIWjI7JCtIffnmM6RzmkOhVB+6NbQB2HmYYvDfgwnhYeFV4Y/jnCIWBrRMZc1d9HcQ3PfRPpElkTem2cxTzmvLUo1Kj6qLmo82je6NLo/xi5mWczVWJ1YSWxLHDkuKq42bmy+3/zt84fineIL43sXmC/IXXB5oc7C9IWnFqkuEiw6lkBMiE44lPBBECqoFowl8hN3JY4KecIdwmciL9E20YjYQ1wqHk7ySCpNepLskbw1eSTFM6Us5bmEJ6mQvEwNTN2bOp4WmnYgbTI9Or0xg5KRkHFCqiFNk7Zn6mfmZnbLrGWFsv7Fbou3Lx6VB8lrs5CsBVktCrZCpuhUWijXKgeyZ2VXZr/Nico5lqueK83tzLPK25A3nO+f/+0SwhLhkralhktXLR1Y5r2sajmyPHF52wrjFQUrhlYGrDy4irYqbdVPq+1Xl65+vSZ6TWuBXsHKgsG1AWvrC1UK5YV969zX7V1PWC9Z37Vh+oadGz4ViYquFNsXlxV/2CjceOUbh2/Kv5nclLSpq8S5ZM9m0mbp5t4tnlsOlqqX5pcObg3Z2rQN31a07fX2Rdsvl80o27uDtkO5o788uLxlp8nOzTs/VKRU9FT6VDbu0t21Ydf4btHuG3u89jTs1dtbvPf9Psm+21UBVU3VZtVl+0n7s/c/romq6fiW+21drU5tce3HA9ID/QcjDrbXudTVHdI9VFKP1ivrRw7HH77+ne93LQ02DVWNnMbiI3BEeeTp9wnf9x4NOtp2jHus4QfTH3YdZx0vakKa8ppGm1Oa+1tiW7pPzD7R1ureevxH2x8PnDQ8WXlK81TJadrpgtOTZ/LPjJ2VnX1+LvncYNuitnvnY87fag9v77oQdOHSRf+L5zu8O85c8rh08rLb5RNXuFearzpfbep06jz+k9NPx7ucu5quuVxrue56vbV7ZvfpG543zt30vXnxFv/W1Z45Pd2983pv98X39d8W3X5yJ/3Oy7vZdyfurbxPvF/0QO1B2UPdh9U/W/7c2O/cf2rAd6Dz0dxH9waFg8/+kfWPD0MFj5mPy4YNhuueOD45OeI/cv3p/KdDz2TPJp4X/qL+y64XFi9++NXr187RmNGhl/KXk79tfKX96sDrGa/bxsLGHr7JeDMxXvRW++3Bd9x3He+j3w9P5Hwgfyj/aPmx9VPQp/uTGZOT/wQDmPP8YzMt2wAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAACZ0lEQVR42mzSP4icZRTF4ee+38xOkp2sG5cQxVJIIaaKkICxTkqJjQhpJFYiop2F1YKFQqoUVpEoCBYSS7dfOxVFWGIsokUE/0TEye7OzPe977XYNWk83b0cDoffvXHWGxkKYjt0N1fi+FaJIzNIFSJ0kDXn0z5nF1O9Sp5PzaizamLD2NELo5W4sOwXqqX/04o1R2wg9PYs/GXUmTjqpGNxwvWdFzz19Akvjj+XUkYTggylFLfml93due+tZ7+y577BrkJnbNWke8yHmzvgi/4lq+WU1XjCsThl2p1ya3GZ4KNrt03KuhXH0SkkkbTOL5+u2PnuZ/D8axtGMTaKsbOvrINP3v/W3Y9XhCJjQCrUWRedVpaq3nvn7oHXrz8jD8PfvnEGbL0716LXytIoxqizkups4R/VwhB7hpi7sXkbXNo86bkrazK5sXnbEHND7BvMLcykOotz3vlxvZw+faRb08VEiVC64rPdSw/pZ/Ly9EutNi3TkHOLOvN3u3OnHNx7MFio5qq5Ifdce/WHhwEfXPnekPuq/UPPQhrAKOV0MFdyRFQFRefr7Z9wRrb0zfYd1aCpGmr2BvtSTkcp1wZLnX0tx4oQjeHX+UF97P75QGspM7VMqTfopVwb0aY1F4ZWlFK1SCVDHQKUEvphj0ztkEdrvZoLtOkoNS2XlkHJIlroIky7Jw8atDSJdQ/aPTUdtJBaLqVmlJpqQataCZKhY/L4HwcEI/Qbv1v8tivbIdVG1UtNnPVmFmPEoT9l/Dc9Ujp42Mx4uGl6I5pmgdjGzaLbopsdJqZHWZnqtKkXcZU8D/8OAPAMQ4kD8KK1AAAAAElFTkSuQmCCiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEJGlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XtShal6dgqJOQ6N4mpGwfb6baqT3uBNwb8AUDZAw9IPCENBmJ72fbAtElThyqqSUh76MQPISbtBVXhu3ZiJ1PEXPX6yznfOec7517bRD1fabWaGVWIlquunc8klZOnFpSeTYrSs9RLA9Sr6U4tkcvNEi7BFffO6+EdigjL7ZHu/k72I796i9zRiSJPwG4VHX0Z+AxRzNRrtksUvwf7+Gm3BtzzHPDTNgQCqwKXfZwSeNHHJz1OIT8JjtAq6xWtCLwGPLzYZi+3YV8DGMiT4VVuG7oiZpGzrZJhcs/hL49xtzH/Dy6bdfTsXYNY+5yluWO4D4neK/ZUvok/17X0HPBLsF+vuUlhfwX4j/rSfAJ4H1H0qZJ9dN7nR19frRTeBt4Fe9FwpwtN+2p1MXscGLHR9SXrmMgjONd1ZxKzpBeA71b4tNhj6JGoyFNp4GHgwUp9qplfmnFW5oTdy7NamcwCI49kv6fN5IAHgD+0rbyoBc3SOjczohbyS1drbq6pQdqumllRC/0ymTtej8gpbbuVwpQfyw66dqEZyxZKxtHpJn+tZnpnEdrYBbueF9qQn93S7HQGGHnYP7w6L+YGHNtd1FJitqPAR+hERCNOFi1i1alKO6RQnjKUxL1GNjwlMsiEhcPLYTEiT9ISbN15OY/jx4SMshe9LaJRpTvHr3C/ybFYP1PZAfwfYrPsMBtnE6SwN9ib7AhLwTrBDgUKcm06FSrTfSj187xPdVQWOk5Q8vxAfSiIUc7Z7xr6zY/+hpqwSyv0I0/QMTRb7RMgBxNodTfSPqdraz/sDjzKBrv4zu2+a2t0/HHzjd2Lbcc2sG7GtsL42K+xLfxtUgI7YHqKlqHK8HbCCXgjHT1cAdMlDetv4FnQ2lLasaOl6vmB0CMmwT/IPszSueHQqv6i/qluqF+oF9TfO2qEGTumJH0qfSv9KH0nfS/9TIp0Wboi/SRdlb6RLgU5u++9nyXYe69fYRPdil1o1WufNSdTTsp75BfllPy8/LI8G7AUuV8ek6fkvfDsCfbNDP0dvRh0CrNqTbV7LfEEGDQPJQadBtfGVMWEq3QWWdufk6ZSNsjG2PQjp3ZcnOWWing6noonSInvi0/Ex+IzAreevPhe+CawpgP1/pMTMDo64G0sTCXIM+KdOnFWRfQKdJvQzV1+Bt8OokmrdtY2yhVX2a+qrykJfMq4Ml3VR4cVzTQVz+UoNne4vcKLoyS+gyKO6EHe+75Fdt0Mbe5bRIf/wjvrVmhbqBN97RD1vxrahvBOfOYzoosH9bq94uejSOQGkVM6sN/7HelL4t10t9F4gPdVzydEOx83Gv+uNxo7XyL/FtFl8z9ZAHF4bBsrEwAAAAlwSFlzAAALEwAACxMBAJqcGAAAByVJREFUWAm1l1uIldcVx9d3ruMZZzRaay+pCjFJH6LSRqxQqA1NH0pBiH3Qp774kEAg4EOkxKdQSCjUFvpm6YsNVNoSaGjFtmga2yZgCIIawdv04g2kM7Uz6lzO+c758v/t/9lzTB/61Oxhn7332muv9V+3vb8pnooDVRkzZ4oY/LmK6mQZa05frX6yFJ9Ae7x4qd2IuV1FFM9WMfhaI9Z+pQBAL+aiEZ0QgNBm2YuZmxHF9VZMXqmivFaLweUyuteWYvHGVPWr2f+F7YvF/ola9DZGVJsHUXs8YvBEK1ZrXt9URDwqxY1BdGMQvWjGqkgA+iLUtazHuADUoowHYugKTilaR7SIpZjWqOMRfY090RbasS4JglpFtzWIcqwZa+pSqnWVcLLXijXpZCFpvbgb/VhMe8huMLPylWkci8/oSD8xJq7hj4WUWvXrlbqVrUyKtBYdpX3Bh9YbzsdErwRgbZKyFP+KdqxPssu4l2hDAOOxIj6bCHigKWRNCcpMCHHHB4TJLc+TXxKHnC51Ct+Qgxl/TZ0qE5Be/EdWTwjqQuJJAPIB8qAZk4kZoXJnvHH+27Hq0+0YX12PH+w7E3/8zbWkitN2M8pS7kCKZ761OV55c2fcm+nG7J1e7N/+e3m2nbyKQcAhnHWZLC86B1rxiFRvSIkIgJHFVWzZ+qk4fG5HEr4wV8buVb+Vuv5QeVZsi/HeW//eHZ1HbNfLT5+Jc2dndBav9KXugfqc+pLsv6Xxvk6kVheumnpDnXlTVMZWfHh+Li6cdOKvmGzEC69+WTskzwr1SfUJ9ZWp7z/0pWXlF9+ejQtnUdCWnAxQ+al5Tdz80lIVEP8x9eZQWCQwOTAhNc34Re+rUW8U0S+r2Ns8nWzBKgONBOeX3V3RaCpPRN7XeFcO7yYl+InML2U3VdBVHszHzbSXYLBJkuTSQzBuphoYZ7X/u8O30gFAHHxzi+Yop8ETcfDXW5JyKMd/fFuO9l3mYuwLAl5gbMg8QuKdYQg4Zjcxo7HikMeIn37vcizes9Ide9bGhs9NLPN9YX0ndnzHpbZ4vx9HXr6kc6Sobo2hIkuzOnIh0xMFRlvc0waWL+p3UePCQ/Myjjx/JSnl59CJbUkJgl75g+ZD/D978Yrc7EuMPe4ESo6OYsaasiiX7tADAyny5cGtyMHsDxzFnP0Tx6Z0SfsW27B1PHZ+c13seGZdbNo2Lo6Iu7e7cfznfxc/8ggNQBhZI9dSs2c5k+rFaHBXmZhd32xTGdlZPvzDvefj9XddlgeObYVpuf1o3zkpyrEnCJwBDjlmr9i7XP3jgrYkDamhEqRA8UOBxZ53tcOtBbgyzr53M65f8DU6sVZ1o067cfFBvP+XGzrDOa5s+JkTShIc+dBtlLOLlRpqAUDc+yqQMnViNq81edDVnPixno/vP/dXjn2svbbnPa1RiqXEHVkYQ06RWygnFEtpbZDLAJws2X1OHgfCv+hiRkZU8Y+pmbjwzjTE1D48PR1TV+5IMErgsjex2A8TJrqCHH9Cw6U0BGBkPUWrKTZnPq4L9WqIOFvEO8ml+vbRvyUB/Jw6OiUa9GydM58qQl6lTrNHyiENrwyTkOvXLziVkMlOOsesVKyIFtZB1zfDAGvdyj4xtkD7yHQ8Ynn4hCrwvYA+DOJCSlXAZl3MjNQobNzVPK7gJm0AiPsQyEg0c6s1cbEB5X08AmDz1TTLucApzHHyJgADvUqVysJMKOSicLRQl+emOIvbnaw+ot2pSTzl5zzJVjPaZ6ix7zCSN4E1shOAWnqbyYH8bOqd1h9AGJ0qtl6LRBubcBKxbo6xh60kWlbLjgG4NJ2ETkwqbl7SeUXVSCq+BF1C2bWEgEO4CxBGvOydGmu3ooXv7AEogLFqn2JtWKO8yc9xAmDxjhGiWMOQXe63zCvHtIjOpGOIwvGJlhRQepyzaiu0MQ4MnFhuT7CiJQC+sUg4jtOYO+1IH9OdCwgBSmOkP2r60CarHeXMjxw3PGyvOBnN670EgOPOc1yEYgDYCxbqTPDXki1srChi4R6lpQ+uDmVFDtkA5GH1qJEvQFgacqCFT37pyP+Y+DMJs0Y54NgbiIVn61jhEUrNARuNIi3vOQf8iUeQuNzILe4b/jFZ7RDYJhTbVRaJTxyWh8PgO93hQJCBsSa2GQyyoLlBzWDxgnm9l0JgADgNgVxElCH22xs4NCsaieSUyzWXaSTLDAPlGQB0Kt6JaqpzYjkJQT9id60aNwqZjVqlz9Kqp+JcfDjOAqhirNoCI6MelpVPAjZ/CbFv45Y9YNcicqDMKm/Xo/FPJdMlqZ9SIK7qSrrci9mbl6q3/DGQ5f7XuK347rgKeuMgiicEfLPmT0rGY1K5SdI/ryritlMbJrr/PZ8+I8qf9PF8qhMrT39QHfHLkhj/fz/bi+eb83F/VxX1b6jWvt6KdTs/AvvCmqXE235jAAAAAElFTkSuQmCC +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAAaCAYAAADovjFxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjcwNUUyRjFGQjUyNTExRTNCNzdEOTU4N0NCMjI3MEFDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjcwNUUyRjIwQjUyNTExRTNCNzdEOTU4N0NCMjI3MEFDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NzA1RTJGMURCNTI1MTFFM0I3N0Q5NTg3Q0IyMjcwQUMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NzA1RTJGMUVCNTI1MTFFM0I3N0Q5NTg3Q0IyMjcwQUMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4qMBarAAAI8ElEQVR42uxZeVRT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 data:image/png;base64,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 diff --git a/build/autoconf/compiler-opts.m4 b/build/autoconf/compiler-opts.m4 index 216edeb9a0f7..05e5632d0d60 100644 --- a/build/autoconf/compiler-opts.m4 +++ b/build/autoconf/compiler-opts.m4 @@ -185,9 +185,7 @@ dnl A high level macro for selecting compiler options. AC_DEFUN([MOZ_COMPILER_OPTS], [ if test "${MOZ_PSEUDO_DERECURSE-unset}" = unset; then - dnl Don't enable on pymake, because of bug 918652. Bug 912979 is an annoyance - dnl with pymake, too. - MOZ_PSEUDO_DERECURSE=no-pymake + MOZ_PSEUDO_DERECURSE=1 fi MOZ_DEBUGGING_OPTS @@ -246,6 +244,13 @@ if test "$GNU_CC" -a -n "$MOZ_FORCE_GOLD"; then fi fi fi +if test "$GNU_CC"; then + if $CC $LDFLAGS -Wl,--version 2>&1 | grep -q "GNU ld"; then + LD_IS_BFD=1 + fi +fi + +AC_SUBST([LD_IS_BFD]) if test "$GNU_CC"; then if test -z "$DEVELOPER_OPTIONS"; then diff --git a/build/docs/slow.rst b/build/docs/slow.rst index 018652d9b834..546fe26ce230 100644 --- a/build/docs/slow.rst +++ b/build/docs/slow.rst @@ -88,22 +88,9 @@ GB is likely entering the point of diminishing returns. This cause impacts both clobber and incremental builds. -You are building with pymake -============================ - -Pymake is slower than GNU make. One reason is Python is generally slower -than C. The build system maintainers are consistently looking at -optimizing pymake. However, it is death by a thousand cuts. - -This cause impacts both clobber and incremental builds. - You are building on Windows =========================== -Builds on Windows are slow for a few reasons. First, Windows builds use -pymake, not GNU make (because of compatibility issues with GNU make). -But, there are other sources of slowness. - New processes on Windows are about a magnitude slower to spawn than on UNIX-y systems such as Linux. This is because Windows has optimized new threads while the \*NIX platforms typically optimize new processes. diff --git a/build/win32/autobinscope.py b/build/win32/autobinscope.py index 4899e731ab46..8bb455990bfd 100644 --- a/build/win32/autobinscope.py +++ b/build/win32/autobinscope.py @@ -46,8 +46,7 @@ except KeyError: try: proc = subprocess.Popen([binscope_path, "/target", binary_path, "/output", log_file_path, "/sympath", symbol_path, - "/c", "ATLVersionCheck", "/c", "ATLVulnCheck", "/c", "FunctionPointersCheck", - "/c", "SharedSectionCheck", "/c", "APTCACheck", "/c", "NXCheck", + "/c", "ATLVersionCheck", "/c", "ATLVulnCheck", "/c", "SharedSectionCheck", "/c", "APTCACheck", "/c", "NXCheck", "/c", "GSCheck", "/c", "GSFunctionSafeBuffersCheck", "/c", "GSFriendlyInitCheck", "/c", "CompilerVersionCheck", "/c", "SafeSEHCheck", "/c", "SNCheck", "/c", "DBCheck"], stdout=subprocess.PIPE) diff --git a/client.mk b/client.mk index 8785d07c47e3..7fd04c5d5db9 100644 --- a/client.mk +++ b/client.mk @@ -145,13 +145,6 @@ endif ifndef MOZ_OBJDIR MOZ_OBJDIR = obj-$(CONFIG_GUESS) -else -# On Windows Pymake builds check MOZ_OBJDIR doesn't start with "/" - ifneq (,$(findstring mingw,$(CONFIG_GUESS))) - ifeq (1_a,$(.PYMAKE)_$(firstword a$(subst /, ,$(MOZ_OBJDIR)))) - $(error For Windows Pymake builds, MOZ_OBJDIR must be a Windows [and not MSYS] style path.) - endif - endif endif ifdef MOZ_BUILD_PROJECTS diff --git a/config/config.mk b/config/config.mk index b6df7a93b5ad..c1c41964e86e 100644 --- a/config/config.mk +++ b/config/config.mk @@ -194,16 +194,6 @@ endif CONFIG_TOOLS = $(MOZ_BUILD_ROOT)/config AUTOCONF_TOOLS = $(topsrcdir)/build/autoconf -# Disable MOZ_PSEUDO_DERECURSE when it contains no-pymake and we're running -# pymake. This can be removed when no-pymake is removed from the default in -# build/autoconf/compiler-opts.m4. -ifdef .PYMAKE -comma = , -ifneq (,$(filter no-pymake,$(subst $(comma), ,$(MOZ_PSEUDO_DERECURSE)))) -MOZ_PSEUDO_DERECURSE := -endif -endif - # Disable MOZ_PSEUDO_DERECURSE on PGO builds until it's fixed. ifneq (,$(MOZ_PROFILE_USE)$(MOZ_PROFILE_GENERATE)) MOZ_PSEUDO_DERECURSE := @@ -238,10 +228,6 @@ MKDIR ?= mkdir SLEEP ?= sleep TOUCH ?= touch -ifdef .PYMAKE -PYCOMMANDPATH += $(PYTHON_SITE_PACKAGES) -endif - PYTHON_PATH = $(PYTHON) $(topsrcdir)/config/pythonpath.py # determine debug-related options @@ -720,9 +706,6 @@ endif # NSINSTALL_BIN ifeq (,$(CROSS_COMPILE)$(filter-out WINNT, $(OS_ARCH))) INSTALL = $(NSINSTALL) -t -ifdef .PYMAKE -install_cmd = $(NSINSTALL_NATIVECMD) -t $(1) -endif # .PYMAKE else @@ -839,6 +822,7 @@ endif define CHECK_BINARY $(call CHECK_STDCXX,$(1)) $(call CHECK_TEXTREL,$(1)) +$(call LOCAL_CHECKS,$(1)) endef # autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including diff --git a/config/makefiles/functions.mk b/config/makefiles/functions.mk index d97b604f9944..ac3632b486f9 100644 --- a/config/makefiles/functions.mk +++ b/config/makefiles/functions.mk @@ -27,8 +27,4 @@ core_winabspath = $(error core_winabspath is unsupported) # # libs:: # $(call py_action,purge_manifests,_build_manifests/purge/foo.manifest) -ifdef .PYMAKE -py_action = %mozbuild.action.$(1) main $(2) -else py_action = $(PYTHON) -m mozbuild.action.$(1) $(2) -endif diff --git a/config/rules.mk b/config/rules.mk index b958cccefe71..dff696a68589 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -35,23 +35,8 @@ endif USE_AUTOTARGETS_MK = 1 include $(topsrcdir)/config/makefiles/makeutils.mk -# Only build with Pymake (not GNU make) on Windows. -ifeq ($(HOST_OS_ARCH),WINNT) -ifndef L10NBASEDIR -ifndef .PYMAKE -$(error Pymake is required to build on Windows. Run |./mach build| to \ -automatically use pymake or invoke pymake directly via \ -|python build/pymake/make.py|.) -endif -endif -endif - ifdef REBUILD_CHECK -ifdef .PYMAKE -REPORT_BUILD = @%rebuild_check rebuild_check $@ $^ -else REPORT_BUILD = $(info $(shell $(PYTHON) $(MOZILLA_DIR)/config/rebuild_check.py $@ $^)) -endif else REPORT_BUILD = $(info $(notdir $@)) endif @@ -66,15 +51,11 @@ endif # ELOG prints out failed command when building silently (gmake -s). Pymake # prints out failed commands anyway, so ELOG just makes things worse by # forcing shell invocations. -ifndef .PYMAKE ifneq (,$(findstring s, $(filter-out --%, $(MAKEFLAGS)))) ELOG := $(EXEC) sh $(BUILD_TOOLS)/print-failed-commands.sh else ELOG := endif # -s -else - ELOG := -endif # ifndef .PYMAKE _VPATH_SRCS = $(abspath $<) @@ -238,7 +219,7 @@ endif COMPILE_CFLAGS += $(COMPILE_PDB_FLAG) COMPILE_CXXFLAGS += $(COMPILE_PDB_FLAG) -LINK_PDBFILE = $(basename $(@F)).pdb +LINK_PDBFILE ?= $(basename $(@F)).pdb ifdef MOZ_DEBUG CODFILE=$(basename $(@F)).cod endif @@ -1142,9 +1123,7 @@ else endif # Cancel GNU make built-in implicit rules -ifndef .PYMAKE MAKEFLAGS += -r -endif ifneq (,$(filter WINNT,$(OS_ARCH))) SEP := ; diff --git a/config/tests/makefiles/autodeps/Makefile.in b/config/tests/makefiles/autodeps/Makefile.in index b588c33be94a..ea21c5a8e404 100644 --- a/config/tests/makefiles/autodeps/Makefile.in +++ b/config/tests/makefiles/autodeps/Makefile.in @@ -22,7 +22,6 @@ tgts =\ $(NULL) export MAKE -export .PYMAKE ##------------------_## ##---] TARGETS [---## diff --git a/intl/icu/Makefile.in b/intl/icu/Makefile.in index ed17efa12769..6ccb772e6055 100644 --- a/intl/icu/Makefile.in +++ b/intl/icu/Makefile.in @@ -44,32 +44,24 @@ include $(topsrcdir)/config/rules.mk ifdef ENABLE_INTL_API ifndef MOZ_NATIVE_ICU -ifdef .PYMAKE -ICU_MAKE = $(GMAKE) -else -ICU_MAKE = $(MAKE) -endif - default:: buildicu -# - ICU requires GNU make according to its readme.html. pymake can't be used -# because it doesn't support order only dependencies. # - Force ICU to use the standard suffix for object files because expandlibs # will discard all files with a non-standard suffix (bug 857450). # - Options for genrb: -k strict parsing; -R omit collation tailoring rules. buildicu:: # ICU's build system is full of races, so force non-parallel build. ifdef CROSS_COMPILE - +$(ICU_MAKE) -j1 -C host STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-k -R -C' + +$(MAKE) -j1 -C host STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-k -R -C' endif - +$(ICU_MAKE) -j1 -C target STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-k -R' + +$(MAKE) -j1 -C target STATIC_O=$(OBJ_SUFFIX) GENRBOPTS='-k -R' $(ICU_LIB_RENAME) distclean clean:: ifdef CROSS_COMPILE - +$(ICU_MAKE) -C host $@ STATIC_O=$(OBJ_SUFFIX) + +$(MAKE) -C host $@ STATIC_O=$(OBJ_SUFFIX) endif - +$(ICU_MAKE) -C target $@ STATIC_O=$(OBJ_SUFFIX) + +$(MAKE) -C target $@ STATIC_O=$(OBJ_SUFFIX) endif endif diff --git a/js/src/Makefile.in b/js/src/Makefile.in index f52bd6229264..5e9f5f24e377 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -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/. -ifndef .PYMAKE ifeq (,$(MAKE_VERSION)) $(error GNU Make is required) endif @@ -12,7 +11,6 @@ make_min_ver := 3.81 ifneq ($(make_min_ver),$(firstword $(sort $(make_min_ver) $(MAKE_VERSION)))) $(error GNU Make $(make_min_ver) or higher is required) endif -endif TOPLEVEL_BUILD := 1 diff --git a/mobile/android/base/ActionModeCompat.java b/mobile/android/base/ActionModeCompat.java index 245c6f18f66c..67b6a7768514 100644 --- a/mobile/android/base/ActionModeCompat.java +++ b/mobile/android/base/ActionModeCompat.java @@ -5,6 +5,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.widget.GeckoPopupMenu; +import org.mozilla.gecko.menu.GeckoMenuItem; import android.view.Gravity; import android.view.Menu; @@ -99,7 +100,7 @@ class ActionModeCompat implements GeckoPopupMenu.OnMenuItemClickListener, /* GeckoPopupMenu.onMenuItemLongClickListener */ @Override public boolean onMenuItemLongClick(MenuItem item) { - showTooltip(item); + showTooltip((GeckoMenuItem) item); return true; } @@ -109,7 +110,7 @@ class ActionModeCompat implements GeckoPopupMenu.OnMenuItemClickListener, mPresenter.endActionModeCompat(); } - private void showTooltip(MenuItem item) { + private void showTooltip(GeckoMenuItem item) { // Computes the tooltip toast screen position (shown when long-tapping the menu item) with regards to the // menu item's position (i.e below the item and slightly to the left) int[] location = new int[2]; diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java index 871677f04e7a..689a33ee0200 100644 --- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -758,12 +758,17 @@ public class BrowserApp extends GeckoApp if (!TextUtils.isEmpty(text)) { Tabs.getInstance().loadUrl(text); Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.CONTEXT_MENU); + Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.CONTEXT_MENU, "pasteandgo"); } return true; } if (itemId == R.id.site_settings) { + // This can be selected from either the browser menu or the contextmenu, depending on the size and version (v11+) of the phone. GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Permissions:Get", null)); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.CONTEXT_MENU, "site_settings"); + } return true; } @@ -771,11 +776,13 @@ public class BrowserApp extends GeckoApp String text = Clipboard.getText(); if (!TextUtils.isEmpty(text)) { enterEditingMode(text); + Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.CONTEXT_MENU, "paste"); } return true; } if (itemId == R.id.subscribe) { + // This can be selected from either the browser menu or the contextmenu, depending on the size and version (v11+) of the phone. Tab tab = Tabs.getInstance().getSelectedTab(); if (tab != null && tab.hasFeeds()) { JSONObject args = new JSONObject(); @@ -785,6 +792,9 @@ public class BrowserApp extends GeckoApp Log.e(LOGTAG, "error building json arguments"); } GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Feeds:Subscribe", args.toString())); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.CONTEXT_MENU, "subscribe"); + } } return true; } @@ -815,6 +825,7 @@ public class BrowserApp extends GeckoApp String url = tab.getURL(); if (url != null) { Clipboard.setText(url); + Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.CONTEXT_MENU, "copyurl"); } } return true; diff --git a/mobile/android/chrome/content/SelectionHandler.js b/mobile/android/chrome/content/SelectionHandler.js index 7e3241c06c52..6a98e13820ab 100644 --- a/mobile/android/chrome/content/SelectionHandler.js +++ b/mobile/android/chrome/content/SelectionHandler.js @@ -518,7 +518,8 @@ var SelectionHandler = { id: "selectall_action", icon: "drawable://ab_select_all", action: function(aElement) { - SelectionHandler.startSelection(aElement) + SelectionHandler.startSelection(aElement); + UITelemetry.addEvent("action.1", "actionbar", null, "select_all"); }, order: 5, selector: { @@ -541,6 +542,7 @@ var SelectionHandler = { // copySelection closes the selection. Show a caret where we just cut the text. SelectionHandler.attachCaret(aElement); + UITelemetry.addEvent("action.1", "actionbar", null, "cut"); }, order: 4, selector: { @@ -557,6 +559,7 @@ var SelectionHandler = { icon: "drawable://ab_copy", action: function() { SelectionHandler.copySelection(); + UITelemetry.addEvent("action.1", "actionbar", null, "copy"); }, order: 3, selector: { @@ -581,6 +584,7 @@ var SelectionHandler = { target.editor.paste(Ci.nsIClipboard.kGlobalClipboard); target.focus(); SelectionHandler._closeSelection(); + UITelemetry.addEvent("action.1", "actionbar", null, "paste"); } }, order: 2, @@ -601,6 +605,7 @@ var SelectionHandler = { icon: "drawable://ic_menu_share", action: function() { SelectionHandler.shareSelection(); + UITelemetry.addEvent("action.1", "actionbar", null, "share"); }, selector: { matches: function() { @@ -618,6 +623,7 @@ var SelectionHandler = { action: function() { SelectionHandler.searchSelection(); SelectionHandler._closeSelection(); + UITelemetry.addEvent("action.1", "actionbar", null, "search"); }, order: 1, selector: { @@ -633,6 +639,7 @@ var SelectionHandler = { icon: "drawable://phone", action: function() { SelectionHandler.callSelection(); + UITelemetry.addEvent("action.1", "actionbar", null, "call"); }, order: 1, selector: { diff --git a/python/mozbuild/mozbuild/base.py b/python/mozbuild/mozbuild/base.py index 3456617a679c..51e98f3674fd 100644 --- a/python/mozbuild/mozbuild/base.py +++ b/python/mozbuild/mozbuild/base.py @@ -434,9 +434,7 @@ class MozbuildObject(ProcessExecutionMixin): args.append('-s') # Print entering/leaving directory messages. Some consumers look at - # these to measure progress. Ideally, we'd do everything with pymake - # and use hooks in its API. Unfortunately, it doesn't provide that - # feature... yet. + # these to measure progress. if print_directory: args.append('-w') diff --git a/security/build/Makefile.in b/security/build/Makefile.in index 45b0842f22f8..70b9c85dc28a 100644 --- a/security/build/Makefile.in +++ b/security/build/Makefile.in @@ -460,11 +460,6 @@ $(addprefix export-,$(NSS_DIRS)): export-%: private_export-% $(addprefix private_export-,$(NSS_DIRS)): EXTRA_GMAKE_FLAGS = $(addprefix private_export-,$(NSS_DIRS)): private_export-%: -# Work around bug #836228 in pymake -ifdef .PYMAKE -$(foreach p,libs export private_export,$(addprefix $(p)-,$(NSS_DIRS))): *=$(subst $(NULL) $(NULL),-,$(wordlist 2,$(words $(subst -, ,$@)),$(subst -, ,$@))) -endif - $(foreach p,libs export private_export,$(addprefix $(p)-,$(NSS_DIRS))): $(DEFAULT_GMAKE_ENV) $(MAKE) -C $(NSS_SRCDIR)/security/$* $(@:-$*=) $(DEFAULT_GMAKE_FLAGS) diff --git a/services/healthreport/docs/dataformat.rst b/services/healthreport/docs/dataformat.rst index 5f9770d0a3a4..37452dbfa478 100644 --- a/services/healthreport/docs/dataformat.rst +++ b/services/healthreport/docs/dataformat.rst @@ -1402,6 +1402,36 @@ Example "google.urlbar": 7 }, +org.mozilla.searches.engines +---------------------------- + +This measurement contains information about search engines. + +Version 1 +^^^^^^^^^ + +This version debuted with Firefox 31 on desktop. It contains the +following properties: + +default + Daily string identifier or name of the default search engine provider. + + This field will only be collected if Telemetry is enabled. If + Telemetry is enabled and then later disabled, this field may + disappear from future days in the payload. + + The special value ``NONE`` could occur if there is no default search + engine. + + The special value ``UNDEFINED`` could occur if a default search + engine exists but its identifier could not be determined. + + This field's contents are + ``Services.search.defaultEngine.identifier`` (if defined) or + ``"other-"`` + ``Services.search.defaultEngine.name`` if not. + In other words, search engines without an ``.identifier`` + are prefixed with ``other-``. + org.mozilla.sync.sync --------------------- @@ -1639,13 +1669,22 @@ lastActive ID of the final Telemetry Experiment that is active on a given day, if any. +Version 2 +^^^^^^^^^ + +Adds an additional optional property: + +lastActiveBranch + If the experiment uses branches, the branch identifier string. + Example ^^^^^^^ :: "org.mozilla.experiments.info": { - "_v": 1, - "lastActive": "some.experiment.id" + "_v": 2, + "lastActive": "some.experiment.id", + "lastActiveBranch": "control" } diff --git a/services/healthreport/providers.jsm b/services/healthreport/providers.jsm index a01a70ea3a8c..acb6e71856ab 100644 --- a/services/healthreport/providers.jsm +++ b/services/healthreport/providers.jsm @@ -55,10 +55,15 @@ const LAST_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_LAST_NUMERIC}; const LAST_TEXT_FIELD = {type: Metrics.Storage.FIELD_LAST_TEXT}; const DAILY_DISCRETE_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_DAILY_DISCRETE_NUMERIC}; const DAILY_LAST_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_NUMERIC}; +const DAILY_LAST_TEXT_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_TEXT}; const DAILY_COUNTER_FIELD = {type: Metrics.Storage.FIELD_DAILY_COUNTER}; const TELEMETRY_PREF = "toolkit.telemetry.enabled"; +function isTelemetryEnabled(prefs) { + return prefs.get(TELEMETRY_PREF, false); +} + /** * Represents basic application state. * @@ -353,7 +358,7 @@ AppInfoProvider.prototype = Object.freeze({ }, _recordIsTelemetryEnabled: function (m) { - let enabled = TELEMETRY_PREF && this._prefs.get(TELEMETRY_PREF, false); + let enabled = isTelemetryEnabled(this._prefs); this._log.debug("Recording telemetry enabled (" + TELEMETRY_PREF + "): " + enabled); yield m.setDailyLastNumeric("isTelemetryEnabled", enabled ? 1 : 0); }, @@ -1282,8 +1287,25 @@ SearchCountMeasurement3.prototype = Object.freeze({ }, }); +function SearchEnginesMeasurement1() { + Metrics.Measurement.call(this); +} + +SearchEnginesMeasurement1.prototype = Object.freeze({ + __proto__: Metrics.Measurement.prototype, + + name: "engines", + version: 1, + + fields: { + default: DAILY_LAST_TEXT_FIELD, + }, +}); + this.SearchesProvider = function () { Metrics.Provider.call(this); + + this._prefs = new Preferences({defaultBranch: null}); }; this.SearchesProvider.prototype = Object.freeze({ @@ -1294,6 +1316,7 @@ this.SearchesProvider.prototype = Object.freeze({ SearchCountMeasurement1, SearchCountMeasurement2, SearchCountMeasurement3, + SearchEnginesMeasurement1, ], /** @@ -1308,6 +1331,36 @@ this.SearchesProvider.prototype = Object.freeze({ return deferred.promise; }, + collectDailyData: function () { + return this.storage.enqueueTransaction(function getDaily() { + // We currently only record this if Telemetry is enabled. + if (!isTelemetryEnabled(this._prefs)) { + return; + } + + let m = this.getMeasurement(SearchEnginesMeasurement1.prototype.name, + SearchEnginesMeasurement1.prototype.version); + + let engine; + try { + engine = Services.search.defaultEngine; + } catch (e) {} + let name; + + if (!engine) { + name = "NONE"; + } else if (engine.identifier) { + name = engine.identifier; + } else if (engine.name) { + name = "other-" + engine.name; + } else { + name = "UNDEFINED"; + } + + yield m.setDailyLastText("default", name); + }.bind(this)); + }, + /** * Record that a search occurred. * diff --git a/services/healthreport/tests/xpcshell/test_provider_searches.js b/services/healthreport/tests/xpcshell/test_provider_searches.js index 0cdf1bb52d0d..54aa9dde908a 100644 --- a/services/healthreport/tests/xpcshell/test_provider_searches.js +++ b/services/healthreport/tests/xpcshell/test_provider_searches.js @@ -6,6 +6,7 @@ const {utils: Cu} = Components; Cu.import("resource://gre/modules/Metrics.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); let bsp = Cu.import("resource://gre/modules/services/healthreport/providers.jsm"); const DEFAULT_ENGINES = [ @@ -41,7 +42,7 @@ add_test(function test_constructor() { run_next_test(); }); -add_task(function test_record() { +add_task(function* test_record() { let storage = yield Metrics.Storage("record"); let provider = new MockSearchesProvider(); @@ -104,7 +105,7 @@ add_task(function test_record() { yield storage.close(); }); -add_task(function test_includes_other_fields() { +add_task(function* test_includes_other_fields() { let storage = yield Metrics.Storage("includes_other_fields"); let provider = new MockSearchesProvider(); @@ -134,3 +135,50 @@ add_task(function test_includes_other_fields() { yield storage.close(); }); + +add_task(function* test_default_search_engine() { + let storage = yield Metrics.Storage("default_search_engine"); + let provider = new SearchesProvider(); + yield provider.init(storage); + + let m = provider.getMeasurement("engines", 1); + + // Ensure no collection if Telemetry not enabled. + Services.prefs.setBoolPref("toolkit.telemetry.enabled", false); + + let now = new Date(); + yield provider.collectDailyData(); + + let data = yield m.getValues(); + Assert.equal(data.days.hasDay(now), false); + + // Now enable telemetry and ensure we populate. + Services.prefs.setBoolPref("toolkit.telemetry.enabled", true); + + yield provider.collectDailyData(); + data = yield m.getValues(); + Assert.ok(data.days.hasDay(now)); + + let day = data.days.getDay(now); + Assert.equal(day.size, 1); + Assert.ok(day.has("default")); + + // test environment doesn't have a default engine. + Assert.equal(day.get("default"), "NONE"); + + Services.search.addEngineWithDetails("testdefault", + "http://localhost/icon.png", + null, + "test description", + "GET", + "http://localhost/search/%s"); + let engine1 = Services.search.getEngineByName("testdefault"); + Assert.ok(engine1); + Services.search.defaultEngine = engine1; + + yield provider.collectDailyData(); + data = yield m.getValues(); + Assert.equal(data.days.getDay(now).get("default"), "other-testdefault"); + + yield storage.close(); +}); diff --git a/testing/gtest/Makefile.in b/testing/gtest/Makefile.in index 925ebd49ebaf..523ea17ab8f1 100644 --- a/testing/gtest/Makefile.in +++ b/testing/gtest/Makefile.in @@ -9,9 +9,7 @@ include $(topsrcdir)/config/rules.mk # Bug 1028035: Linking xul-gtest.dll takes too long, so we disable GTest on # Windows PGO builds. -# Bug 1029469: fix_stack_using_bpsyms.py doesn't know how to deal with the -# second xul.pdb file that linking xul-gtest.dll creates. -ifeq (WINNT,$(OS_ARCH)) +ifeq (1_WINNT,$(MOZ_PGO)_$(OS_ARCH)) SKIP_GTEST_DURING_MAKE_CHECK ?= 1 endif diff --git a/toolkit/components/telemetry/TelemetryPing.jsm b/toolkit/components/telemetry/TelemetryPing.jsm index 4b69a92b215d..e3d1e12463cc 100644 --- a/toolkit/components/telemetry/TelemetryPing.jsm +++ b/toolkit/components/telemetry/TelemetryPing.jsm @@ -535,9 +535,11 @@ let Impl = { try { let scope = {}; Cu.import("resource:///modules/experiments/Experiments.jsm", scope); - let activeExperiment = scope.Experiments.instance().getActiveExperimentID(); + let experiments = scope.Experiments.instance() + let activeExperiment = experiments.getActiveExperimentID(); if (activeExperiment) { ret.activeExperiment = activeExperiment; + ret.activeExperimentBranch = experiments.getActiveExperimentBranch(); } } catch(e) { // If this is not Firefox, the import will fail. diff --git a/toolkit/library/StaticXULComponents.ld b/toolkit/library/StaticXULComponents.ld new file mode 100644 index 000000000000..e4fe728134de --- /dev/null +++ b/toolkit/library/StaticXULComponents.ld @@ -0,0 +1,5 @@ +SECTIONS { + .data.rel.ro : { + *(.kPStaticModules) + } +} diff --git a/toolkit/library/StaticXULComponentsEnd/StaticXULComponentsEnd.cpp b/toolkit/library/StaticXULComponentsEnd/StaticXULComponentsEnd.cpp new file mode 100644 index 000000000000..7aa2dbac830c --- /dev/null +++ b/toolkit/library/StaticXULComponentsEnd/StaticXULComponentsEnd.cpp @@ -0,0 +1,14 @@ +#include "mozilla/Module.h" +#include "mozilla/NullPtr.h" + +/* Ensure end_kPStaticModules is at the end of the .kPStaticModules section + * on Windows. Somehow, placing the object last is not enough with PGO/LTCG. */ +#ifdef _MSC_VER +/* Sections on Windows are in two parts, separated with $. When linking, + * sections with the same first part are all grouped, and ordered + * alphabetically with the second part as sort key. */ +# pragma section(".kPStaticModules$Z", read) +# undef NSMODULE_SECTION +# define NSMODULE_SECTION __declspec(allocate(".kPStaticModules$Z"), dllexport) +#endif +NSMODULE_DEFN(end_kPStaticModules) = nullptr; diff --git a/toolkit/library/StaticXULComponentsEnd/moz.build b/toolkit/library/StaticXULComponentsEnd/moz.build new file mode 100644 index 000000000000..ed4291e5ed7f --- /dev/null +++ b/toolkit/library/StaticXULComponentsEnd/moz.build @@ -0,0 +1,11 @@ +# 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/. + +SOURCES += [ + 'StaticXULComponentsEnd.cpp', +] + +LIBRARY_NAME = 'StaticXULComponentsEnd' + +DEFINES['MOZILLA_INTERNAL_API'] = True diff --git a/toolkit/library/StaticXULComponentsStart.cpp b/toolkit/library/StaticXULComponentsStart.cpp new file mode 100644 index 000000000000..dc24b589459e --- /dev/null +++ b/toolkit/library/StaticXULComponentsStart.cpp @@ -0,0 +1,4 @@ +#include "mozilla/Module.h" +#include "mozilla/NullPtr.h" + +NSMODULE_DEFN(start_kPStaticModules) = nullptr; diff --git a/toolkit/library/gtest/Makefile.in b/toolkit/library/gtest/Makefile.in index bccf93c22f08..e775e6aa5d7a 100644 --- a/toolkit/library/gtest/Makefile.in +++ b/toolkit/library/gtest/Makefile.in @@ -24,4 +24,6 @@ endif $(DIST)/bin/dependentlibs.list.gtest: $(DIST)/bin/dependentlibs.list sed -e 's|$(SHARED_LIBRARY)|gtest/$(SHARED_LIBRARY)|' $< > $@ +LINK_PDBFILE = xul-gtest.pdb + endif diff --git a/toolkit/library/libxul.mk b/toolkit/library/libxul.mk index e416574d98a7..3ddabf390fe6 100644 --- a/toolkit/library/libxul.mk +++ b/toolkit/library/libxul.mk @@ -246,3 +246,28 @@ OS_LIBS += $(LIBICONV) ifeq ($(MOZ_WIDGET_TOOLKIT),windows) OS_LIBS += $(call EXPAND_LIBNAME,usp10 oleaut32) endif + +EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME_PATH,StaticXULComponentsEnd,$(DEPTH)/toolkit/library/StaticXULComponentsEnd) + +# BFD ld doesn't create multiple PT_LOADs as usual when an unknown section +# exists. Using an implicit linker script to make it fold that section in +# .data.rel.ro makes it create multiple PT_LOADs. That implicit linker +# script however makes gold misbehave, first because it doesn't like that +# the linker script is given after crtbegin.o, and even past that, replaces +# the default section rules with those from the script instead of +# supplementing them. Which leads to a lib with a huge load of sections. +ifdef LD_IS_BFD +EXTRA_DSO_LDOPTS += $(topsrcdir)/toolkit/library/StaticXULComponents.ld +endif + +ifeq (WINNT,$(OS_TARGET)) +get_first_and_last = dumpbin -exports $1 | grep _NSModule@@ | sort -k 3 | sed -n 's/^.*?\([^@]*\)@@.*$$/\1/;1p;$$p' +else +get_first_and_last = $(TOOLCHAIN_PREFIX)nm -g $1 | grep _NSModule$$ | sort | sed -n 's/^.* _*\([^ ]*\)$$/\1/;1p;$$p' +endif + +LOCAL_CHECKS = test "$$($(get_first_and_last) | xargs echo)" != "start_kPStaticModules_NSModule end_kPStaticModules_NSModule" && echo "NSModules are not ordered appropriately" && exit 1 || exit 0 + +ifeq (Linux,$(OS_ARCH)) +LOCAL_CHECKS += ; test "$$($(TOOLCHAIN_PREFIX)readelf -l $1 | awk '$1 == "LOAD" { t += 1 } END { print t }')" -le 1 && echo "Only one PT_LOAD segment" && exit 1 || exit 0 +endif diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build index bd73db0426de..fc084a4a8415 100644 --- a/toolkit/library/moz.build +++ b/toolkit/library/moz.build @@ -7,43 +7,18 @@ LIBRARY_NAME = 'xul' SOURCES += [ - 'nsStaticXULComponents.cpp', + 'StaticXULComponentsStart.cpp', ] +# This, combined with the fact the file is first, makes the start pointer +# it contains first in Windows PGO builds. +SOURCES['StaticXULComponentsStart.cpp'].no_pgo = True + if CONFIG['OS_ARCH'] == 'WINNT': SOURCES += [ 'nsDllMain.cpp', ] -# component libraries -additional_defines = ( - 'MOZ_AUTH_EXTENSION', - 'MOZ_GIO_COMPONENT', - 'MOZ_JSDEBUGGER', - 'MOZ_PERMISSIONS', - 'MOZ_PREF_EXTENSIONS', - 'MOZ_SPELLCHECK', - 'MOZ_UNIVERSALCHARDET', - 'MOZ_ZIPWRITER', -) - -for var in additional_defines: - if CONFIG[var]: - DEFINES[var] = True - -if CONFIG['MOZ_DEBUG'] and CONFIG['ENABLE_TESTS']: - DEFINES['ENABLE_LAYOUTDEBUG'] = True - -if CONFIG['MOZ_WIDGET_TOOLKIT'] not in ('android', 'gonk', 'qt', - 'cocoa', 'windows') and \ - CONFIG['MOZ_XUL']: - DEFINES['MOZ_FILEVIEW'] = True - -# Platform-specific icon channel stuff - supported mostly-everywhere -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'mac', 'cocoa', - 'gtk2', 'gtk3', 'qt', 'android'): - DEFINES['ICON_DECODER'] = True - LOCAL_INCLUDES += [ '/config', # need widget/windows for resource.h (included from widget.rc) @@ -57,4 +32,4 @@ if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']: FAIL_ON_WARNINGS = True -DIRS += ['build', 'gtest'] +DIRS += ['StaticXULComponentsEnd', 'build', 'gtest'] diff --git a/toolkit/library/nsStaticXULComponents.cpp b/toolkit/library/nsStaticXULComponents.cpp deleted file mode 100644 index 6378db2946bf..000000000000 --- a/toolkit/library/nsStaticXULComponents.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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/. */ - -#include "mozilla/Module.h" -#include "nsXPCOM.h" -#include "nsMemory.h" - -#ifdef MOZ_AUTH_EXTENSION -#define AUTH_MODULE MODULE(nsAuthModule) -#else -#define AUTH_MODULE -#endif - -#ifdef MOZ_PERMISSIONS -#define PERMISSIONS_MODULES \ - MODULE(nsCookieModule) \ - MODULE(nsPermissionsModule) -#else -#define PERMISSIONS_MODULES -#endif - -#ifdef MOZ_UNIVERSALCHARDET -#define UNIVERSALCHARDET_MODULE MODULE(nsUniversalCharDetModule) -#else -#define UNIVERSALCHARDET_MODULE -#endif - -#ifdef XP_WIN -# define WIDGET_MODULES MODULE(nsWidgetModule) -#elif defined(XP_MACOSX) -# define WIDGET_MODULES MODULE(nsWidgetMacModule) -#elif defined(MOZ_WIDGET_GTK) -# define WIDGET_MODULES MODULE(nsWidgetGtk2Module) -#elif defined(MOZ_WIDGET_QT) -# define WIDGET_MODULES MODULE(nsWidgetQtModule) -#elif defined(MOZ_WIDGET_ANDROID) -# define WIDGET_MODULES MODULE(nsWidgetAndroidModule) -#elif defined(MOZ_WIDGET_GONK) -# define WIDGET_MODULES MODULE(nsWidgetGonkModule) -#else -# error Unknown widget module. -#endif - -#ifndef MOZ_B2G -#define CONTENT_PROCESS_WIDGET_MODULES MODULE(nsContentProcessWidgetModule) -#else -#define CONTENT_PROCESS_WIDGET_MODULES -#endif - -#ifdef ICON_DECODER -#define ICON_MODULE MODULE(nsIconDecoderModule) -#else -#define ICON_MODULE -#endif - -#ifdef MOZ_ENABLE_XREMOTE -#define XREMOTE_MODULES MODULE(RemoteServiceModule) -#else -#define XREMOTE_MODULES -#endif - -#ifdef MOZ_PREF_EXTENSIONS -#define SYSTEMPREF_MODULES MODULE(nsAutoConfigModule) -#else -#define SYSTEMPREF_MODULES -#endif - -#ifdef ENABLE_LAYOUTDEBUG -#define LAYOUT_DEBUG_MODULE MODULE(nsLayoutDebugModule) -#else -#define LAYOUT_DEBUG_MODULE -#endif - -#ifdef MOZ_JSDEBUGGER -#define JSDEBUGGER_MODULES \ - MODULE(JavaScript_Debugger) -#else -#define JSDEBUGGER_MODULES -#endif - -#if defined(MOZ_FILEVIEW) && defined(MOZ_XUL) -#define FILEVIEW_MODULE MODULE(nsFileViewModule) -#else -#define FILEVIEW_MODULE -#endif - -#ifdef MOZ_ZIPWRITER -#define ZIPWRITER_MODULE MODULE(ZipWriterModule) -#else -#define ZIPWRITER_MODULE -#endif - -#ifdef MOZ_PLACES -#define PLACES_MODULES \ - MODULE(nsPlacesModule) -#else -#define PLACES_MODULES -#endif - -#ifdef MOZ_XUL -#define XULENABLED_MODULES \ - MODULE(tkAutoCompleteModule) \ - MODULE(satchel) \ - MODULE(PKI) -#else -#define XULENABLED_MODULES -#endif - -#ifdef MOZ_SPELLCHECK -#define SPELLCHECK_MODULE MODULE(mozSpellCheckerModule) -#else -#define SPELLCHECK_MODULE -#endif - -#ifdef MOZ_XUL -#ifdef MOZ_WIDGET_GTK -#define UNIXPROXY_MODULE MODULE(nsUnixProxyModule) -#endif -#if defined(MOZ_WIDGET_QT) -#define UNIXPROXY_MODULE MODULE(nsUnixProxyModule) -#endif -#endif -#ifndef UNIXPROXY_MODULE -#define UNIXPROXY_MODULE -#endif - -#if defined(XP_MACOSX) -#define OSXPROXY_MODULE MODULE(nsOSXProxyModule) -#else -#define OSXPROXY_MODULE -#endif - -#if defined(XP_WIN) -#define WINDOWSPROXY_MODULE MODULE(nsWindowsProxyModule) -#else -#define WINDOWSPROXY_MODULE -#endif - -#if defined(MOZ_WIDGET_ANDROID) -#define ANDROIDPROXY_MODULE MODULE(nsAndroidProxyModule) -#else -#define ANDROIDPROXY_MODULE -#endif - -#if defined(BUILD_CTYPES) -#define JSCTYPES_MODULE MODULE(jsctypes) -#else -#define JSCTYPES_MODULE -#endif - -#ifndef MOZ_APP_COMPONENT_MODULES -#if defined(MOZ_APP_COMPONENT_INCLUDE) -#include MOZ_APP_COMPONENT_INCLUDE -#define MOZ_APP_COMPONENT_MODULES APP_COMPONENT_MODULES -#else -#define MOZ_APP_COMPONENT_MODULES -#endif -#endif - -#if defined(MOZ_ENABLE_PROFILER_SPS) -#define PROFILER_MODULE MODULE(nsProfilerModule) -#else -#define PROFILER_MODULE -#endif - -#if defined(MOZ_WEBRTC) -#define PEERCONNECTION_MODULE MODULE(peerconnection) -#else -#define PEERCONNECTION_MODULE -#endif - -#if defined(MOZ_GIO_COMPONENT) -#define GIO_MODULE MODULE(nsGIOModule) -#else -#define GIO_MODULE -#endif - -#if defined(MOZ_SYNTH_PICO) -#define SYNTH_PICO_MODULE MODULE(synthpico) -#else -#define SYNTH_PICO_MODULE -#endif - -#define XUL_MODULES \ - MODULE(nsUConvModule) \ - MODULE(nsI18nModule) \ - MODULE(nsChardetModule) \ - UNIVERSALCHARDET_MODULE \ - MODULE(necko) \ - PERMISSIONS_MODULES \ - AUTH_MODULE \ - MODULE(nsJarModule) \ - ZIPWRITER_MODULE \ - MODULE(StartupCacheModule) \ - MODULE(nsPrefModule) \ - MODULE(nsRDFModule) \ - MODULE(nsWindowDataSourceModule) \ - MODULE(nsParserModule) \ - MODULE(nsImageLib2Module) \ - MODULE(nsMediaSnifferModule) \ - MODULE(nsGfxModule) \ - PROFILER_MODULE \ - WIDGET_MODULES \ - CONTENT_PROCESS_WIDGET_MODULES \ - ICON_MODULE \ - MODULE(nsPluginModule) \ - MODULE(nsLayoutModule) \ - MODULE(docshell_provider) \ - MODULE(embedcomponents) \ - MODULE(Browser_Embedding_Module) \ - MODULE(appshell) \ - MODULE(nsTransactionManagerModule) \ - MODULE(nsComposerModule) \ - MODULE(application) \ - MODULE(Apprunner) \ - MODULE(CommandLineModule) \ - FILEVIEW_MODULE \ - MODULE(mozStorageModule) \ - PLACES_MODULES \ - XULENABLED_MODULES \ - MODULE(nsToolkitCompsModule) \ - XREMOTE_MODULES \ - JSDEBUGGER_MODULES \ - MODULE(BOOT) \ - MODULE(NSS) \ - SYSTEMPREF_MODULES \ - SPELLCHECK_MODULE \ - LAYOUT_DEBUG_MODULE \ - UNIXPROXY_MODULE \ - OSXPROXY_MODULE \ - WINDOWSPROXY_MODULE \ - ANDROIDPROXY_MODULE \ - JSCTYPES_MODULE \ - MODULE(jsreflect) \ - MODULE(jsperf) \ - MODULE(identity) \ - MODULE(nsServicesCryptoModule) \ - MOZ_APP_COMPONENT_MODULES \ - MODULE(nsTelemetryModule) \ - MODULE(jsinspector) \ - MODULE(jsdebugger) \ - PEERCONNECTION_MODULE \ - GIO_MODULE \ - SYNTH_PICO_MODULE \ - MODULE(DiskSpaceWatcherModule) \ - /* end of list */ - -#define MODULE(_name) \ - NSMODULE_DECL(_name); - -XUL_MODULES - -#ifdef MOZ_WIDGET_GONK -MODULE(WifiCertServiceModule) -MODULE(WifiProxyServiceModule) -MODULE(NetworkWorkerModule) -#endif - -#undef MODULE - -#define MODULE(_name) \ - &NSMODULE_NAME(_name), - -extern const mozilla::Module *const *const kPStaticModules[] = { - XUL_MODULES -#ifdef MOZ_WIDGET_GONK -MODULE(WifiCertServiceModule) -MODULE(WifiProxyServiceModule) -MODULE(NetworkWorkerModule) -#endif - nullptr -}; - -#undef MODULE diff --git a/xpcom/components/Module.h b/xpcom/components/Module.h index 81025d7f1cba..e20fc39cfc7c 100644 --- a/xpcom/components/Module.h +++ b/xpcom/components/Module.h @@ -118,8 +118,21 @@ struct Module #if defined(MOZILLA_INTERNAL_API) # define NSMODULE_NAME(_name) _name##_NSModule -# define NSMODULE_DECL(_name) extern mozilla::Module const *const NSMODULE_NAME(_name) -# define NSMODULE_DEFN(_name) NSMODULE_DECL(_name) +# if defined(_MSC_VER) +# pragma section(".kPStaticModules$M", read) +# pragma comment(linker, "/merge:.kPStaticModules=.rdata") +# define NSMODULE_SECTION __declspec(allocate(".kPStaticModules$M"), dllexport) +# elif defined(__GNUC__) +# if defined(__ELF__) +# define NSMODULE_SECTION __attribute__((section(".kPStaticModules"), visibility("protected"))) +# elif defined(__MACH__) +# define NSMODULE_SECTION __attribute__((section("__DATA, .kPStaticModules"), visibility("default"))) +# endif +# endif +# if !defined(NSMODULE_SECTION) +# error Do not know how to define sections. +# endif +# define NSMODULE_DEFN(_name) extern NSMODULE_SECTION mozilla::Module const *const NSMODULE_NAME(_name) #else # define NSMODULE_NAME(_name) NSModule # define NSMODULE_DEFN(_name) extern "C" NS_EXPORT mozilla::Module const *const NSModule diff --git a/xpcom/components/nsComponentManager.cpp b/xpcom/components/nsComponentManager.cpp index 9aa40d5e7d7c..d9b227f9ca33 100644 --- a/xpcom/components/nsComponentManager.cpp +++ b/xpcom/components/nsComponentManager.cpp @@ -81,10 +81,6 @@ using namespace mozilla; PRLogModuleInfo* nsComponentManagerLog = nullptr; -// defined in nsStaticXULComponents.cpp to contain all the components in -// libxul. -extern mozilla::Module const *const *const kPStaticModules[]; - #if 0 || defined (DEBUG_timeless) #define SHOW_DENIED_ON_SHUTDOWN #define SHOW_CI_ON_EXISTING_SERVICE @@ -278,6 +274,15 @@ nsComponentManagerImpl::nsComponentManagerImpl() nsTArray* nsComponentManagerImpl::sStaticModules; +NSMODULE_DEFN(start_kPStaticModules); +NSMODULE_DEFN(end_kPStaticModules); + +/* The content between start_kPStaticModules and end_kPStaticModules is gathered + * by the linker from various objects containing symbols in a specific section. + * ASAN considers (rightfully) the use of this content as a global buffer + * overflow. But this is a deliberate and well-considered choice, with no proper + * way to make ASAN happy. */ +MOZ_ASAN_BLACKLIST /* static */ void nsComponentManagerImpl::InitializeStaticModules() { @@ -285,9 +290,10 @@ nsComponentManagerImpl::InitializeStaticModules() return; sStaticModules = new nsTArray; - for (const mozilla::Module *const *const *staticModules = kPStaticModules; - *staticModules; ++staticModules) - sStaticModules->AppendElement(**staticModules); + for (const mozilla::Module *const *staticModules = &NSMODULE_NAME(start_kPStaticModules) + 1; + staticModules < &NSMODULE_NAME(end_kPStaticModules); ++staticModules) + if (*staticModules) // ASAN adds padding + sStaticModules->AppendElement(*staticModules); } nsTArray*