diff --git a/browser/base/content/browser-trackingprotection.js b/browser/base/content/browser-trackingprotection.js index 2c13f088062..ffc0443c8fb 100644 --- a/browser/base/content/browser-trackingprotection.js +++ b/browser/base/content/browser-trackingprotection.js @@ -184,7 +184,6 @@ var TrackingProtection = { }, showIntroPanel: Task.async(function*() { - let mm = gBrowser.selectedBrowser.messageManager; let brandBundle = document.getElementById("bundle_brand"); let brandShortName = brandBundle.getString("brandShortName"); @@ -219,7 +218,7 @@ var TrackingProtection = { let panelTarget = yield UITour.getTarget(window, "trackingProtection"); UITour.initForBrowser(gBrowser.selectedBrowser, window); - UITour.showInfo(window, mm, panelTarget, + UITour.showInfo(window, panelTarget, gNavigatorBundle.getString("trackingProtection.intro.title"), gNavigatorBundle.getFormattedString("trackingProtection.intro.description", [brandShortName]), diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index 30f13c76678..d092ccbf241 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -1759,17 +1759,8 @@ nsContextMenu.prototype = { selectedText = selectedText.substr(0,truncLength) + this.ellipsis; } - // Use the current engine if the search bar is visible, the default - // engine otherwise. - var engineName = ""; - var ss = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); - if (isElementVisible(BrowserSearch.searchBar)) - engineName = ss.currentEngine.name; - else - engineName = ss.defaultEngine.name; - // format "Search for " string to show in menu + let engineName = Services.search.currentEngine.name; var menuLabel = gNavigatorBundle.getFormattedString("contextMenuSearch", [engineName, selectedText]); diff --git a/browser/components/extensions/ext-tabs.js b/browser/components/extensions/ext-tabs.js index 8ae7d933cd5..f724d8f5fee 100644 --- a/browser/components/extensions/ext-tabs.js +++ b/browser/components/extensions/ext-tabs.js @@ -261,27 +261,21 @@ extensions.registerSchemaAPI("tabs", null, (extension, context) => { }).api(), create: function(createProperties, callback) { - if (!createProperties) { - createProperties = {}; - } - let url = createProperties.url || aboutNewTabService.newTabURL; - url = extension.baseURI.resolve(url); + url = context.uri.resolve(url); function createInWindow(window) { let tab = window.gBrowser.addTab(url); let active = true; - if ("active" in createProperties) { + if (createProperties.active !== null) { active = createProperties.active; - } else if ("selected" in createProperties) { - active = createProperties.selected; } if (active) { window.gBrowser.selectedTab = tab; } - if ("index" in createProperties) { + if (createProperties.index !== null) { window.gBrowser.moveTabTo(tab, createProperties.index); } diff --git a/browser/components/extensions/test/browser/browser.ini b/browser/components/extensions/test/browser/browser.ini index e6e16afc479..b24a926f069 100644 --- a/browser/components/extensions/test/browser/browser.ini +++ b/browser/components/extensions/test/browser/browser.ini @@ -24,6 +24,7 @@ support-files = [browser_ext_tabs_executeScript_bad.js] [browser_ext_tabs_query.js] [browser_ext_tabs_getCurrent.js] +[browser_ext_tabs_create.js] [browser_ext_tabs_update.js] [browser_ext_tabs_onUpdated.js] [browser_ext_tabs_sendMessage.js] diff --git a/browser/components/extensions/test/browser/browser_ext_tabs_create.js b/browser/components/extensions/test/browser/browser_ext_tabs_create.js new file mode 100644 index 00000000000..c5b7ec8c64b --- /dev/null +++ b/browser/components/extensions/test/browser/browser_ext_tabs_create.js @@ -0,0 +1,169 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +add_task(function* () { + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots"); + gBrowser.selectedTab = tab; + + // TODO: Multiple windows. + + // Using pre-loaded new tab pages interferes with onUpdated events. + // It probably shouldn't. + SpecialPowers.setBoolPref("browser.newtab.preload", false); + registerCleanupFunction(() => { + SpecialPowers.clearUserPref("browser.newtab.preload"); + }); + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + "permissions": ["tabs"], + + "background": { "page": "bg/background.html" }, + }, + + files: { + "bg/blank.html": ``, + + "bg/background.html": ` + + + `, + + "bg/background.js": function() { + // Wrap API methods in promise-based variants. + let promiseTabs = {}; + Object.keys(browser.tabs).forEach(method => { + promiseTabs[method] = (...args) => { + return new Promise(resolve => { + browser.tabs[method](...args, resolve); + }); + }; + }); + + + let activeTab; + let activeWindow; + + function runTests() { + const DEFAULTS = { + index: 2, + windowId: activeWindow, + active: true, + pinned: false, + url: "about:newtab", + }; + + let tests = [ + { + create: { url: "http://example.com/" }, + result: { url: "http://example.com/" }, + }, + { + create: { url: "blank.html" }, + result: { url: browser.runtime.getURL("bg/blank.html") }, + }, + { + create: {}, + result: { url: "about:newtab" }, + }, + { + create: { active: false }, + result: { active: false }, + }, + { + create: { active: true }, + result: { active: true }, + }, + { + create: { pinned: true }, + result: { pinned: true, index: 0 }, + }, + { + create: { pinned: true, active: true }, + result: { pinned: true, active: true, index: 0 }, + }, + { + create: { pinned: true, active: false }, + result: { pinned: true, active: false, index: 0 }, + }, + { + create: { index: 1 }, + result: { index: 1 }, + }, + { + create: { index: 1, active: false }, + result: { index: 1, active: false }, + }, + { + create: { windowId: activeWindow }, + result: { windowId: activeWindow }, + }, + ]; + + function nextTest() { + if (!tests.length) { + browser.test.notifyPass("tabs.create"); + return; + } + + let test = tests.shift(); + let expected = Object.assign({}, DEFAULTS, test.result); + + browser.test.log(`Testing tabs.create(${JSON.stringify(test.create)}), expecting ${JSON.stringify(test.result)}`); + + let tabId; + let updatedPromise = new Promise(resolve => { + let onUpdated = (changedTabId, changed) => { + if (changedTabId === tabId && changed.url) { + browser.tabs.onUpdated.removeListener(onUpdated); + resolve(changed.url); + } + }; + browser.tabs.onUpdated.addListener(onUpdated); + }); + + promiseTabs.create(test.create).then(tab => { + tabId = tab.id; + + for (let key of Object.keys(expected)) { + if (key === "url") { + // FIXME: This doesn't get updated until later in the load cycle. + continue; + } + + browser.test.assertEq(expected[key], tab[key], `Expected value for tab.${key}`); + } + + return updatedPromise; + }).then(url => { + browser.test.assertEq(expected.url, url, `Expected value for tab.url`); + + return promiseTabs.remove(tabId); + }).then(() => { + return promiseTabs.update(activeTab, { active: true }); + }).then(() => { + nextTest(); + }); + } + + nextTest(); + } + + browser.tabs.query({ active: true, currentWindow: true }, tabs => { + activeTab = tabs[0].id; + activeWindow = tabs[0].windowId; + + runTests(); + }); + }, + }, + }); + + yield extension.startup(); + yield extension.awaitFinish("tabs.create"); + yield extension.unload(); + + yield BrowserTestUtils.removeTab(tab); +}); + diff --git a/browser/components/nsBrowserContentHandler.js b/browser/components/nsBrowserContentHandler.js index e89004dcb09..93aa8c9cf1e 100644 --- a/browser/components/nsBrowserContentHandler.js +++ b/browser/components/nsBrowserContentHandler.js @@ -38,7 +38,6 @@ const nsIWebNavigation = Components.interfaces.nsIWebNavigation; const nsIWindowMediator = Components.interfaces.nsIWindowMediator; const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher; const nsIWebNavigationInfo = Components.interfaces.nsIWebNavigationInfo; -const nsIBrowserSearchService = Components.interfaces.nsIBrowserSearchService; const nsICommandLineValidator = Components.interfaces.nsICommandLineValidator; const NS_BINDING_ABORTED = Components.results.NS_BINDING_ABORTED; @@ -262,10 +261,7 @@ function logSystemBasedSearch(engine) { } function doSearch(searchTerm, cmdLine) { - var ss = Components.classes["@mozilla.org/browser/search-service;1"] - .getService(nsIBrowserSearchService); - - var engine = ss.defaultEngine; + var engine = Services.search.defaultEngine; logSystemBasedSearch(engine); var submission = engine.getSubmission(searchTerm, null, "system"); @@ -796,9 +792,7 @@ nsDefaultCommandLineHandler.prototype = { } if (allowedParams.indexOf(formParam) != -1) { var term = params.get("q"); - var ss = Components.classes["@mozilla.org/browser/search-service;1"] - .getService(nsIBrowserSearchService); - var engine = ss.defaultEngine; + var engine = Services.search.defaultEngine; logSystemBasedSearch(engine); var submission = engine.getSubmission(term, null, "system"); uri = submission.uri; diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index d49586ceaeb..3117adce82b 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -446,30 +446,6 @@ BrowserGlue.prototype = { Preferences.set("browser.search.hiddenOneOffs", hiddenList.join(",")); } - - if (data != "engine-default" && data != "engine-current") { - break; - } - // Enforce that the search service's defaultEngine is always equal to - // its currentEngine. The search service will notify us any time either - // of them are changed (either by directly setting the relevant prefs, - // i.e. if add-ons try to change this directly, or if the - // nsIBrowserSearchService setters are called). - // No need to initialize the search service, since it's guaranteed to be - // initialized already when this notification fires. - let ss = Services.search; - if (ss.currentEngine.name == ss.defaultEngine.name) - return; - if (data == "engine-current") - ss.defaultEngine = ss.currentEngine; - else - ss.currentEngine = ss.defaultEngine; - break; - case "browser-search-service": - if (data != "init-complete") - return; - Services.obs.removeObserver(this, "browser-search-service"); - this._syncSearchEngines(); break; #ifdef NIGHTLY_BUILD case "nsPref:changed": @@ -568,16 +544,6 @@ BrowserGlue.prototype = { } }, - _syncSearchEngines: function () { - // Only do this if the search service is already initialized. This function - // gets called in finalUIStartup and from a browser-search-service observer, - // to catch both cases (search service initialization occurring before and - // after final-ui-startup) - if (Services.search.isInitialized) { - Services.search.defaultEngine = Services.search.currentEngine; - } - }, - // initialization (called on application startup) _init: function BG__init() { let os = Services.obs; @@ -609,7 +575,6 @@ BrowserGlue.prototype = { os.addObserver(this, "keyword-search", false); #endif os.addObserver(this, "browser-search-engine-modified", false); - os.addObserver(this, "browser-search-service", false); os.addObserver(this, "restart-in-safe-mode", false); os.addObserver(this, "flash-plugin-hang", false); os.addObserver(this, "xpi-signature-changed", false); @@ -669,10 +634,6 @@ BrowserGlue.prototype = { os.removeObserver(this, "keyword-search"); #endif os.removeObserver(this, "browser-search-engine-modified"); - try { - os.removeObserver(this, "browser-search-service"); - // may have already been removed by the observer - } catch (ex) {} #ifdef NIGHTLY_BUILD Services.prefs.removeObserver(POLARIS_ENABLED, this); #endif @@ -823,8 +784,6 @@ BrowserGlue.prototype = { // handle any UI migration this._migrateUI(); - this._syncSearchEngines(); - WebappManager.init(); PageThumbs.init(); #ifdef NIGHTLY_BUILD diff --git a/browser/components/preferences/donottrack.xul b/browser/components/preferences/donottrack.xul new file mode 100644 index 00000000000..40f0aacebbe --- /dev/null +++ b/browser/components/preferences/donottrack.xul @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/components/preferences/in-content/privacy.js b/browser/components/preferences/in-content/privacy.js index 3ec0afe9c27..3f5cfeec3d8 100644 --- a/browser/components/preferences/in-content/privacy.js +++ b/browser/components/preferences/in-content/privacy.js @@ -30,7 +30,10 @@ var gPrivacyPane = { let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "tracking-protection"; link.setAttribute("href", url); + this.trackingProtectionReadPrefs(); + document.getElementById("trackingprotectionbox").hidden = false; + document.getElementById("trackingprotectionpbmbox").hidden = true; }, #endif @@ -108,6 +111,10 @@ var gPrivacyPane = { gPrivacyPane.clearPrivateDataNow(true); return false; }); + setEventListener("doNotTrackSettings", "click", function () { + gPrivacyPane.showDoNotTrackSettings(); + return false; + }); setEventListener("privateBrowsingAutoStart", "command", gPrivacyPane.updateAutostart); setEventListener("cookieExceptions", "command", @@ -116,8 +123,54 @@ var gPrivacyPane = { gPrivacyPane.showCookies); setEventListener("clearDataSettings", "command", gPrivacyPane.showClearPrivateDataSettings); + setEventListener("trackingProtectionRadioGroup", "command", + gPrivacyPane.trackingProtectionWritePrefs); + setEventListener("trackingProtectionExceptions", "command", + gPrivacyPane.showTrackingProtectionExceptions); setEventListener("changeBlockList", "command", gPrivacyPane.showBlockLists); + setEventListener("changeBlockListPBM", "command", + gPrivacyPane.showBlockLists); + }, + + // TRACKING PROTECTION MODE + + /** + * Selects the right item of the Tracking Protection radiogroup. + */ + trackingProtectionReadPrefs() { + let enabledPref = document.getElementById("privacy.trackingprotection.enabled"); + let pbmPref = document.getElementById("privacy.trackingprotection.pbmode.enabled"); + let radiogroup = document.getElementById("trackingProtectionRadioGroup"); + + // Global enable takes precedence over enabled in Private Browsing. + radiogroup.value = enabledPref.value ? "always" : + pbmPref.value ? "private" : + "never"; + }, + + /** + * Sets the pref values based on the selected item of the radiogroup. + */ + trackingProtectionWritePrefs() { + let enabledPref = document.getElementById("privacy.trackingprotection.enabled"); + let pbmPref = document.getElementById("privacy.trackingprotection.pbmode.enabled"); + let radiogroup = document.getElementById("trackingProtectionRadioGroup"); + + switch (radiogroup.value) { + case "always": + enabledPref.value = true; + pbmPref.value = true; + break; + case "private": + enabledPref.value = false; + pbmPref.value = true; + break; + case "never": + enabledPref.value = false; + pbmPref.value = false; + break; + } }, // HISTORY MODE @@ -371,6 +424,21 @@ var gPrivacyPane = { this._shouldPromptForRestart = true; }, + /** + * Displays fine-grained, per-site preferences for tracking protection. + */ + showTrackingProtectionExceptions() { + let bundlePreferences = document.getElementById("bundlePreferences"); + let params = { + permissionType: "trackingprotection", + hideStatusColumn: true, + windowTitle: bundlePreferences.getString("trackingprotectionpermissionstitle"), + introText: bundlePreferences.getString("trackingprotectionpermissionstext"), + }; + gSubDialog.open("chrome://browser/content/preferences/permissions.xul", + null, params); + }, + /** * Displays the available block lists for tracking protection. */ @@ -386,6 +454,14 @@ var gPrivacyPane = { null, params); }, + /** + * Displays the Do Not Track settings dialog. + */ + showDoNotTrackSettings() { + gSubDialog.open("chrome://browser/content/preferences/donottrack.xul", + "resizable=no"); + }, + // HISTORY /* diff --git a/browser/components/preferences/in-content/privacy.xul b/browser/components/preferences/in-content/privacy.xul index beb1800d289..3f9de6839ce 100644 --- a/browser/components/preferences/in-content/privacy.xul +++ b/browser/components/preferences/in-content/privacy.xul @@ -10,9 +10,6 @@