Merge f-t to m-c, a=merge

This commit is contained in:
Phil Ringnalda 2016-01-09 11:44:32 -08:00
commit 542a3fabcb
86 changed files with 1012 additions and 651 deletions

View File

@ -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]),

View File

@ -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 <engine> for <selection>" string to show in menu
let engineName = Services.search.currentEngine.name;
var menuLabel = gNavigatorBundle.getFormattedString("contextMenuSearch",
[engineName,
selectedText]);

View File

@ -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);
}

View File

@ -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]

View File

@ -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": `<html><head><meta charset="utf-8"></head></html>`,
"bg/background.html": `<html><head>
<meta charset="utf-8">
<script src="background.js"></script>
</head></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);
});

View File

@ -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;

View File

@ -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

View File

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/donottrack.dtd" >
<prefwindow id="DoNotTrackDialog" type="child"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
title="&window.title;"
style="width: &window.width;; height: &window.height;;"
dlgbuttons="accept,cancel">
<prefpane>
<preferences>
<preference id="privacy.donottrackheader.enabled"
name="privacy.donottrackheader.enabled"
type="bool"/>
</preferences>
<hbox align="center" pack="start">
<!-- Work around focus ring not showing properly. -->
<spacer style="width: 1em;"/>
<checkbox label="&doNotTrackCheckbox.label;"
accesskey="&doNotTrackCheckbox.accesskey;"
preference="privacy.donottrackheader.enabled"/>
<label class="text-link doNotTrackLearnMore"
value="&doNotTrackLearnMore.label;"
href="https://www.mozilla.org/dnt"/>
</hbox>
</prefpane>
</prefwindow>

View File

@ -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
/*

View File

@ -10,9 +10,6 @@
<preferences id="privacyPreferences" hidden="true" data-category="panePrivacy">
<!-- Tracking -->
<preference id="privacy.donottrackheader.enabled"
name="privacy.donottrackheader.enabled"
type="bool"/>
<preference id="privacy.trackingprotection.enabled"
name="privacy.trackingprotection.enabled"
type="bool"/>
@ -30,6 +27,9 @@
<preference id="pref.privacy.disable_button.change_blocklist"
name="pref.privacy.disable_button.change_blocklist"
type="bool"/>
<preference id="pref.privacy.disable_button.tracking_protection_exceptions"
name="pref.privacy.disable_button.tracking_protection_exceptions"
type="bool"/>
<!-- Location Bar -->
<preference id="browser.urlbar.autocomplete.enabled"
@ -87,32 +87,40 @@
<!-- Tracking -->
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true">
<caption><label>&tracking.label;</label></caption>
<vbox>
<hbox align="center">
<checkbox id="privacyDoNotTrackCheckbox"
label="&dntTrackingNotOkay4.label;"
accesskey="&dntTrackingNotOkay4.accesskey;"
preference="privacy.donottrackheader.enabled"/>
<label id="doNotTrackInfo"
class="text-link"
href="https://www.mozilla.org/dnt">
&doNotTrackInfo.label;
</label>
</hbox>
</vbox>
<vbox id="trackingprotectionbox" hidden="true">
<hbox align="center">
<checkbox id="trackingProtection"
preference="privacy.trackingprotection.enabled"
accesskey="&trackingProtection5.accesskey;"
label="&trackingProtection5.label;" />
<label id="trackingProtectionLearnMore"
class="text-link"
value="&trackingProtectionLearnMore.label;"/>
<hbox align="start">
<vbox>
<caption><label>&trackingProtectionHeader.label;
<label id="trackingProtectionLearnMore" class="text-link"
value="&trackingProtectionLearnMore.label;"/>
</label></caption>
<radiogroup id="trackingProtectionRadioGroup">
<radio value="always"
label="&trackingProtectionAlways.label;"
accesskey="&trackingProtectionAlways.accesskey;"/>
<radio value="private"
label="&trackingProtectionPrivate.label;"
accesskey="&trackingProtectionPrivate.accesskey;"/>
<radio value="never"
label="&trackingProtectionNever.label;"
accesskey="&trackingProtectionNever.accesskey;"/>
</radiogroup>
</vbox>
<spacer flex="1" />
<vbox>
<button id="trackingProtectionExceptions"
label="&trackingProtectionExceptions.label;"
accesskey="&trackingProtectionExceptions.accesskey;"
preference="pref.privacy.disable_button.tracking_protection_exceptions"/>
<button id="changeBlockList"
label="&changeBlockList.label;"
accesskey="&changeBlockList.accesskey;"
preference="pref.privacy.disable_button.change_blocklist"/>
</vbox>
</hbox>
</vbox>
<vbox id="trackingprotectionpbmbox">
<caption><label>&tracking.label;</label></caption>
<hbox align="center">
<checkbox id="trackingProtectionPBM"
preference="privacy.trackingprotection.pbmode.enabled"
@ -122,11 +130,16 @@
class="text-link"
value="&trackingProtectionPBMLearnMore.label;"/>
<spacer flex="1" />
<button id="changeBlockList"
<button id="changeBlockListPBM"
label="&changeBlockList.label;" accesskey="&changeBlockList.accesskey;"
preference="pref.privacy.disable_button.change_blocklist"/>
</hbox>
</vbox>
<vbox>
<description>&doNotTrack.pre.label;<html:a
class="inline-link" id="doNotTrackSettings" href="#"
>&doNotTrack.settings.label;</html:a>&doNotTrack.post.label;</description>
</vbox>
</groupbox>
<!-- History -->

View File

@ -97,7 +97,7 @@ var gSubDialog = {
handleEvent: function(aEvent) {
switch (aEvent.type) {
case "command":
this.close(aEvent);
this._frame.contentWindow.close();
break;
case "dialogclosing":
this._onDialogClosing(aEvent);
@ -127,7 +127,7 @@ var gSubDialog = {
_onUnload: function(aEvent) {
if (aEvent.target.location.href == this._openedURL) {
this.close(this._closingEvent);
this._frame.contentWindow.close();
}
},

View File

@ -32,7 +32,6 @@ skip-if = e10s # Bug ?????? - "leaked until shutdown [nsGlobalWindow #99 about:
[browser_sanitizeOnShutdown_prefLocked.js]
[browser_searchsuggestions.js]
[browser_subdialogs.js]
skip-if = e10s # Bug 1087114
support-files = subdialog.xul
[browser_telemetry.js]
# Skip this test on Android and B2G as FHR and Telemetry are separate systems there.

View File

@ -7,268 +7,265 @@
* Tests for the sub-dialog infrastructure, not for actual sub-dialog functionality.
*/
var gTeardownAfterClose = false;
const gDialogURL = getRootDirectory(gTestPath) + "subdialog.xul";
function test() {
waitForExplicitFinish();
open_preferences((win) => {
Task.spawn(function () {
for (let test of gTests) {
info("STARTING TEST: " + test.desc);
try {
yield test.run();
} finally {
if (test.teardown) {
yield test.teardown();
}
}
function* open_subdialog_and_test_generic_start_state(browser, domcontentloadedFn) {
let domcontentloadedFnStr = domcontentloadedFn ?
"(" + domcontentloadedFn.toString() + ")()" :
"";
return ContentTask.spawn(browser, {gDialogURL, domcontentloadedFnStr}, function*(args) {
let {gDialogURL, domcontentloadedFnStr} = args;
let rv = { acceptCount: 0 };
let win = content.window;
let subdialog = win.gSubDialog;
subdialog.open(gDialogURL, null, rv);
info("waiting for subdialog DOMFrameContentLoaded");
yield ContentTaskUtils.waitForEvent(win, "DOMFrameContentLoaded", true);
let result;
if (domcontentloadedFnStr) {
result = eval(domcontentloadedFnStr);
}
info("waiting for subdialog load");
yield ContentTaskUtils.waitForEvent(subdialog._frame, "load");
info("subdialog window is loaded");
let expectedStyleSheetURLs = subdialog._injectedStyleSheets.slice(0);
for (let styleSheet of subdialog._frame.contentDocument.styleSheets) {
let index = expectedStyleSheetURLs.indexOf(styleSheet.href);
if (index >= 0) {
expectedStyleSheetURLs.splice(index, 1);
}
});
}
ok(!!subdialog._frame.contentWindow, "The dialog should be non-null");
isnot(subdialog._frame.contentWindow.location.toString(), "about:blank",
"Subdialog URL should not be about:blank");
is(win.getComputedStyle(subdialog._overlay, "").visibility, "visible",
"Overlay should be visible");
is(expectedStyleSheetURLs.length, 0,
"No stylesheets that were expected are missing");
return result;
});
}
var gTests = [{
desc: "Check titlebar, focus, return value, title changes, and accepting",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
function* close_subdialog_and_test_generic_end_state(browser, closingFn, closingButton, acceptCount, options) {
let dialogclosingPromise = ContentTask.spawn(browser, {closingButton, acceptCount}, function*(expectations) {
let win = content.window;
let subdialog = win.gSubDialog;
let frame = subdialog._frame;
info("waiting for dialogclosing");
let closingEvent =
yield ContentTaskUtils.waitForEvent(frame.contentWindow, "dialogclosing");
let actualAcceptCount = frame.contentWindow.arguments &&
frame.contentWindow.arguments[0].acceptCount;
// Check focus is in the textbox
is(dialog.document.activeElement.value, "Default text", "Textbox with correct text is focused");
info("waiting for about:blank load");
yield ContentTaskUtils.waitForEvent(frame, "load");
// Titlebar
is(content.document.getElementById("dialogTitle").textContent, "Sample sub-dialog",
"Dialog title should be correct initially");
let receivedEvent = waitForEvent(gBrowser.selectedBrowser, "DOMTitleChanged");
dialog.document.title = "Updated title";
// Wait for the title change listener
yield receivedEvent;
is(content.document.getElementById("dialogTitle").textContent, "Updated title",
"Dialog title should be updated with changes");
isnot(win.getComputedStyle(subdialog._overlay, "").visibility, "visible",
"overlay is not visible");
is(frame.getAttribute("style"), "", "inline styles should be cleared");
is(frame.contentWindow.location.href.toString(), "about:blank",
"sub-dialog should be unloaded");
is(closingEvent.detail.button, expectations.closingButton,
"closing event should indicate button was '" + expectations.closingButton + "'");
is(actualAcceptCount, expectations.acceptCount,
"should be 1 if accepted, 0 if canceled, undefined if closed w/out button");
});
let closingPromise = promiseDialogClosing(dialog);
// Accept the dialog
dialog.document.documentElement.acceptDialog();
let closingEvent = yield closingPromise;
is(closingEvent.detail.button, "accept", "closing event should indicate button was 'accept'");
yield deferredClose.promise;
is(rv.acceptCount, 1, "return value should have been updated");
},
},
{
desc: "Check canceling the dialog",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
let closingPromise = promiseDialogClosing(dialog);
info("cancelling the dialog");
dialog.document.documentElement.cancelDialog();
let closingEvent = yield closingPromise;
is(closingEvent.detail.button, "cancel", "closing event should indicate button was 'cancel'");
yield deferredClose.promise;
is(rv.acceptCount, 0, "return value should NOT have been updated");
},
},
{
desc: "Check window.close on the dialog",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
let closingPromise = promiseDialogClosing(dialog);
info("window.close called on the dialog");
dialog.window.close();
let closingEvent = yield closingPromise;
is(closingEvent.detail.button, null, "closing event should indicate no button was clicked");
yield deferredClose.promise;
is(rv.acceptCount, 0, "return value should NOT have been updated");
},
},
{
desc: "Check clicking the close button on the dialog",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
yield EventUtils.synthesizeMouseAtCenter(content.document.getElementById("dialogClose"), {},
content.window);
yield deferredClose.promise;
is(rv.acceptCount, 0, "return value should NOT have been updated");
},
},
{
desc: "Check that 'back' navigation will close the dialog",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
info("cancelling the dialog");
content.gSubDialog._frame.goBack();
yield deferredClose.promise;
is(rv.acceptCount, 0, "return value should NOT have been updated");
},
},
{
desc: "Hitting escape in the dialog",
run: function* () {
let rv = { acceptCount: 0 };
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, rv,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
EventUtils.synthesizeKey("VK_ESCAPE", {}, content.window);
yield deferredClose.promise;
is(rv.acceptCount, 0, "return value should NOT have been updated");
},
},
{
desc: "Check that width and height from the sub-dialog are used to size the <browser>",
run: function* () {
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, null,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let dialog = yield dialogPromise;
is(content.gSubDialog._frame.style.width, "32em", "Width should be set on the frame from the dialog");
is(content.gSubDialog._frame.style.height, "5em", "Height should be set on the frame from the dialog");
content.gSubDialog.close();
yield deferredClose.promise;
},
},
{
desc: "Check that a set width and content causing wrapping still lead to correct scrollHeight-implied height",
run: function* () {
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, null,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
let oldHeight;
content.addEventListener("DOMFrameContentLoaded", function frame2Loaded() {
content.removeEventListener("DOMFrameContentLoaded", frame2Loaded);
let doc = content.gSubDialog._frame.contentDocument;
oldHeight = doc.documentElement.scrollHeight;
doc.documentElement.style.removeProperty("height");
doc.getElementById("desc").textContent = `
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas
sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas
sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas
sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
voluptatem sequi nesciunt.`
doc = null;
});
let dialog = yield dialogPromise;
is(content.gSubDialog._frame.style.width, "32em", "Width should be set on the frame from the dialog");
let docEl = content.gSubDialog._frame.contentDocument.documentElement;
ok(docEl.scrollHeight > oldHeight, "Content height increased (from " + oldHeight + " to " + docEl.scrollHeight + ").");
is(content.gSubDialog._frame.style.height, docEl.scrollHeight + "px", "Height on the frame should be higher now");
content.gSubDialog.close();
yield deferredClose.promise;
},
},
{
desc: "Check that a dialog that is too high gets cut down to size",
run: function* () {
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, null,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
content.addEventListener("DOMFrameContentLoaded", function frame3Loaded() {
content.removeEventListener("DOMFrameContentLoaded", frame3Loaded);
content.gSubDialog._frame.contentDocument.documentElement.style.height = '100000px';
});
let dialog = yield dialogPromise;
is(content.gSubDialog._frame.style.width, "32em", "Width should be set on the frame from the dialog");
let newHeight = content.gSubDialog._frame.contentDocument.documentElement.scrollHeight;
ok(parseInt(content.gSubDialog._frame.style.height) < window.innerHeight,
"Height on the frame should be smaller than window's innerHeight");
content.gSubDialog.close();
yield deferredClose.promise;
if (options && options.runClosingFnOutsideOfContentTask) {
yield closingFn();
} else {
ContentTask.spawn(browser, null, closingFn);
}
},
{
desc: "Check that scrollWidth and scrollHeight from the sub-dialog are used to size the <browser>",
run: function* () {
let deferredClose = Promise.defer();
let dialogPromise = openAndLoadSubDialog(gDialogURL, null, null,
(aEvent) => dialogClosingCallback(deferredClose, aEvent));
content.addEventListener("DOMFrameContentLoaded", function frameLoaded() {
content.removeEventListener("DOMFrameContentLoaded", frameLoaded);
content.gSubDialog._frame.contentDocument.documentElement.style.removeProperty("height");
content.gSubDialog._frame.contentDocument.documentElement.style.removeProperty("width");
});
let dialog = yield dialogPromise;
ok(content.gSubDialog._frame.style.width.endsWith("px"),
"Width (" + content.gSubDialog._frame.style.width + ") should be set to a px value of the scrollWidth from the dialog");
ok(content.gSubDialog._frame.style.height.endsWith("px"),
"Height (" + content.gSubDialog._frame.style.height + ") should be set to a px value of the scrollHeight from the dialog");
gTeardownAfterClose = true;
content.gSubDialog.close();
yield deferredClose.promise;
},
}];
function promiseDialogClosing(dialog) {
return waitForEvent(dialog, "dialogclosing");
yield dialogclosingPromise;
}
function dialogClosingCallback(aPromise, aEvent) {
// Wait for the close handler to unload the page
waitForEvent(content.gSubDialog._frame, "load", 4000).then((aEvt) => {
info("Load event happened: " + !(aEvt instanceof Error));
is_element_hidden(content.gSubDialog._overlay, "Overlay is not visible");
is(content.gSubDialog._frame.getAttribute("style"), "",
"Check that inline styles were cleared");
is(content.gSubDialog._frame.contentWindow.location.toString(), "about:blank",
"Check the sub-dialog was unloaded");
if (gTeardownAfterClose) {
content.close();
finish();
}
aPromise.resolve();
}, Cu.reportError);
}
let tab;
add_task(function* test_initialize() {
tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
});
add_task(function* check_titlebar_focus_returnval_titlechanges_accepting() {
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
let domtitlechangedPromise = BrowserTestUtils.waitForEvent(tab.linkedBrowser, "DOMTitleChanged");
yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
let dialog = content.window.gSubDialog._frame.contentWindow;
let dialogTitleElement = content.document.getElementById("dialogTitle");
is(dialogTitleElement.textContent, "Sample sub-dialog",
"Title should be correct initially");
is(dialog.document.activeElement.value, "Default text",
"Textbox with correct text is focused");
dialog.document.title = "Updated title";
});
info("waiting for DOMTitleChanged event");
yield domtitlechangedPromise;
ContentTask.spawn(tab.linkedBrowser, null, function*() {
let dialogTitleElement = content.document.getElementById("dialogTitle");
is(dialogTitleElement.textContent, "Updated title", "subdialog should have updated title");
});
// Accept the dialog
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { content.window.gSubDialog._frame.contentDocument.documentElement.acceptDialog(); },
"accept", 1);
});
add_task(function* check_canceling_dialog() {
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
info("canceling the dialog");
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { content.window.gSubDialog._frame.contentDocument.documentElement.cancelDialog(); },
"cancel", 0);
});
add_task(function* window_close_on_dialog() {
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
info("canceling the dialog");
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { content.window.gSubDialog._frame.contentWindow.window.close(); },
null, 0);
});
add_task(function* click_close_button_on_dialog() {
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
info("canceling the dialog");
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { return BrowserTestUtils.synthesizeMouseAtCenter("#dialogClose", {}, tab.linkedBrowser); },
null, 0, {runClosingFnOutsideOfContentTask: true});
});
add_task(function* back_navigation_on_subdialog_should_close_dialog() {
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
info("canceling the dialog");
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { content.window.gSubDialog._frame.goBack(); },
null, undefined);
});
add_task(function* back_navigation_on_browser_tab_should_close_dialog() {
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
info("canceling the dialog");
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { tab.linkedBrowser.goBack(); },
null, undefined, {runClosingFnOutsideOfContentTask: true});
});
add_task(function* escape_should_close_dialog() {
todo(false, "BrowserTestUtils.sendChar('VK_ESCAPE') triggers " +
"'can't access dead object' on `navigator` in this test. " +
"See bug 1238065.")
return;
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
info("canceling the dialog");
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { return BrowserTestUtils.sendChar("VK_ESCAPE", tab.linkedBrowser); },
null, undefined, {runClosingFnOutsideOfContentTask: true});
});
add_task(function* correct_width_and_height_should_be_used_for_dialog() {
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
let frameStyle = content.window.gSubDialog._frame.style;
is(frameStyle.width, "32em", "Width should be set on the frame from the dialog");
is(frameStyle.height, "5em", "Height should be set on the frame from the dialog");
});
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { content.window.gSubDialog._frame.contentWindow.window.close(); },
null, 0);
});
add_task(function* wrapped_text_in_dialog_should_have_expected_scrollHeight() {
let oldHeight = yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser, function domcontentloadedFn() {
let frame = content.window.gSubDialog._frame;
let doc = frame.contentDocument;
let oldHeight = doc.documentElement.scrollHeight;
doc.documentElement.style.removeProperty("height");
doc.getElementById("desc").textContent = `
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas
sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas
sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas
sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
voluptatem sequi nesciunt.`
return oldHeight;
});
yield ContentTask.spawn(tab.linkedBrowser, oldHeight, function*(oldHeight) {
let frame = content.window.gSubDialog._frame;
let docEl = frame.contentDocument.documentElement;
is(frame.style.width, "32em",
"Width should be set on the frame from the dialog");
ok(docEl.scrollHeight > oldHeight,
"Content height increased (from " + oldHeight + " to " + docEl.scrollHeight + ").");
is(frame.style.height, docEl.scrollHeight + "px",
"Height on the frame should be higher now");
});
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { content.window.gSubDialog._frame.contentWindow.window.close(); },
null, 0);
});
add_task(function* dialog_too_tall_should_get_reduced_in_height() {
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser, function domcontentloadedFn() {
let frame = content.window.gSubDialog._frame;
frame.contentDocument.documentElement.style.height = '100000px';
});
yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
let frame = content.window.gSubDialog._frame;
is(frame.style.width, "32em", "Width should be set on the frame from the dialog");
ok(parseInt(frame.style.height) < content.window.innerHeight,
"Height on the frame should be smaller than window's innerHeight");
});
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { content.window.gSubDialog._frame.contentWindow.window.close(); },
null, 0);
});
add_task(function* scrollWidth_and_scrollHeight_from_subdialog_should_size_the_browser() {
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser, function domcontentloadedFn() {
let frame = content.window.gSubDialog._frame;
frame.contentDocument.documentElement.style.removeProperty("height");
frame.contentDocument.documentElement.style.removeProperty("width");
});
yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
let frame = content.window.gSubDialog._frame;
ok(frame.style.width.endsWith("px"),
"Width (" + frame.style.width + ") should be set to a px value of the scrollWidth from the dialog");
ok(frame.style.height.endsWith("px"),
"Height (" + frame.style.height + ") should be set to a px value of the scrollHeight from the dialog");
});
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
function() { content.window.gSubDialog._frame.contentWindow.window.close(); },
null, 0);
});
add_task(function* test_shutdown() {
gBrowser.removeTab(tab);
});

View File

@ -12,6 +12,7 @@ browser.jar:
* content/browser/preferences/cookies.js
* content/browser/preferences/connection.xul
content/browser/preferences/connection.js
content/browser/preferences/donottrack.xul
* content/browser/preferences/fonts.xul
content/browser/preferences/fonts.js
content/browser/preferences/handlers.xml

View File

@ -249,6 +249,10 @@ var gPermissionManager = {
var urlLabel = document.getElementById("urlLabel");
urlLabel.hidden = !urlFieldVisible;
if (aParams.hideStatusColumn) {
document.getElementById("statusCol").hidden = true;
}
let treecols = document.getElementsByTagName("treecols")[0];
treecols.addEventListener("click", event => {
if (event.target.nodeName != "treecol" || event.button != 0) {

View File

@ -130,8 +130,7 @@
<property name="currentEngine">
<setter><![CDATA[
let ss = Services.search;
ss.defaultEngine = ss.currentEngine = val;
Services.search.currentEngine = val;
return val;
]]></setter>
<getter><![CDATA[

View File

@ -530,13 +530,18 @@ this.UITour = {
}
let infoOptions = {};
if (typeof data.closeButtonCallbackID == "string") {
infoOptions.closeButtonCallback = () => {
this.sendPageCallback(messageManager, data.closeButtonCallbackID);
};
}
if (typeof data.targetCallbackID == "string") {
infoOptions.targetCallback = details => {
this.sendPageCallback(messageManager, data.targetCallbackID, details);
};
}
if (typeof data.closeButtonCallbackID == "string")
infoOptions.closeButtonCallbackID = data.closeButtonCallbackID;
if (typeof data.targetCallbackID == "string")
infoOptions.targetCallbackID = data.targetCallbackID;
this.showInfo(window, messageManager, target, data.title, data.text, iconURL, buttons, infoOptions);
this.showInfo(window, target, data.title, data.text, iconURL, buttons, infoOptions);
}).catch(log.error);
break;
}
@ -1395,17 +1400,17 @@ this.UITour = {
* Show an info panel.
*
* @param {ChromeWindow} aChromeWindow
* @param {nsIMessageSender} aMessageManager
* @param {Node} aAnchor
* @param {String} [aTitle=""]
* @param {String} [aDescription=""]
* @param {String} [aIconURL=""]
* @param {Object[]} [aButtons=[]]
* @param {Object} [aOptions={}]
* @param {String} [aOptions.closeButtonCallbackID]
* @param {String} [aOptions.closeButtonCallback]
* @param {String} [aOptions.targetCallback]
*/
showInfo: function(aChromeWindow, aMessageManager, aAnchor, aTitle = "", aDescription = "", aIconURL = "",
aButtons = [], aOptions = {}) {
showInfo(aChromeWindow, aAnchor, aTitle = "", aDescription = "",
aIconURL = "", aButtons = [], aOptions = {}) {
function showInfoPanel(aAnchorEl) {
aAnchorEl.focus();
@ -1461,8 +1466,9 @@ this.UITour = {
let tooltipClose = document.getElementById("UITourTooltipClose");
let closeButtonCallback = (event) => {
this.hideInfo(document.defaultView);
if (aOptions && aOptions.closeButtonCallbackID)
this.sendPageCallback(aMessageManager, aOptions.closeButtonCallbackID);
if (aOptions && aOptions.closeButtonCallback) {
aOptions.closeButtonCallback();
}
};
tooltipClose.addEventListener("command", closeButtonCallback);
@ -1471,16 +1477,16 @@ this.UITour = {
target: aAnchor.targetName,
type: event.type,
};
this.sendPageCallback(aMessageManager, aOptions.targetCallbackID, details);
aOptions.targetCallback(details);
};
if (aOptions.targetCallbackID && aAnchor.addTargetListener) {
if (aOptions.targetCallback && aAnchor.addTargetListener) {
aAnchor.addTargetListener(document, targetCallback);
}
tooltip.addEventListener("popuphiding", function tooltipHiding(event) {
tooltip.removeEventListener("popuphiding", tooltipHiding);
tooltipClose.removeEventListener("command", closeButtonCallback);
if (aOptions.targetCallbackID && aAnchor.removeTargetListener) {
if (aOptions.targetCallback && aAnchor.removeTargetListener) {
aAnchor.removeTargetListener(document, targetCallback);
}
});

View File

@ -25,6 +25,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "Pocket",
XPCOMUtils.defineLazyGetter(this, "gPocketBundle", function() {
return Services.strings.createBundle("chrome://pocket/locale/pocket.properties");
});
XPCOMUtils.defineLazyGetter(this, "gPocketStyleURI", function() {
return Services.io.newURI("chrome://pocket/skin/pocket.css", null, null);
});
const PREF_BRANCH = "extensions.pocket.";
@ -286,10 +289,12 @@ function pktUIGetter(prop, window) {
var PocketOverlay = {
startup: function(reason) {
let styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"]
.getService(Ci.nsIStyleSheetService);
this._sheetType = styleSheetService.AUTHOR_SHEET;
this._cachedSheet = styleSheetService.preloadSheet(gPocketStyleURI,
this._sheetType);
CreatePocketWidget(reason);
Services.obs.addObserver(this,
"browser-delayed-startup-finished",
false);
CustomizableUI.addListener(this);
PocketContextMenu.init();
PocketReader.startup();
@ -322,9 +327,7 @@ var PocketOverlay = {
PocketContextMenu.shutdown();
PocketReader.shutdown();
},
observe: function(aSubject, aTopic, aData) {
// new browser window, initialize the "overlay"
let window = aSubject;
onWindowOpened: function(window) {
this.setWindowScripts(window);
this.addStyles(window);
this.updateWindow(window);
@ -435,21 +438,13 @@ var PocketOverlay = {
},
addStyles: function(win) {
let xmlPI = win.document.createProcessingInstruction("xml-stylesheet",
"type=\"text/css\" href=\"chrome://pocket/skin/pocket.css\"");
win.document.insertBefore(xmlPI, win.document.documentElement);
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
utils.addSheet(this._cachedSheet, this._sheetType);
},
removeStyles: function(win) {
let el = win.document.documentElement.previousSibling;
while (el) {
if (el.nodeType == el.PROCESSING_INSTRUCTION_NODE &&
el.sheet && el.sheet.href == "chrome://pocket/skin/pocket.css") {
el.remove();
break;
}
el = el.previousSibling;
}
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
utils.removeSheet(gPocketStyleURI, this._sheetType);
}
}

View File

@ -0,0 +1,12 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!ENTITY window.title "Do Not Track">
<!ENTITY window.width "40em">
<!ENTITY window.height "8em">
<!ENTITY doNotTrackCheckbox.label "Use Do Not Track">
<!ENTITY doNotTrackCheckbox.accesskey "U">
<!ENTITY doNotTrackLearnMore.label "Learn More">

View File

@ -19,6 +19,8 @@ acceptVeryLargeMinimumFont=Keep my changes anyway
#### Permissions Manager
trackingprotectionpermissionstext=You have disabled Tracking Protection on these sites.
trackingprotectionpermissionstitle=Exceptions - Tracking Protection
cookiepermissionstext=You can specify which websites are always or never allowed to use cookies. Type the exact address of the site you want to manage and then click Block, Allow for Session, or Allow.
cookiepermissionstitle=Exceptions - Cookies
addonspermissionstext=You can specify which websites are allowed to install add-ons. Type the exact address of the site you want to allow and then click Allow.

View File

@ -2,20 +2,30 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!ENTITY tracking.label "Tracking">
<!ENTITY trackingProtectionHeader.label "Use Tracking Protection">
<!ENTITY trackingProtectionAlways.label "Always">
<!ENTITY trackingProtectionAlways.accesskey "y">
<!ENTITY trackingProtectionPrivate.label "Only in private windows">
<!ENTITY trackingProtectionPrivate.accesskey "l">
<!ENTITY trackingProtectionNever.label "Never">
<!ENTITY trackingProtectionNever.accesskey "n">
<!ENTITY trackingProtectionLearnMore.label "Learn more">
<!ENTITY trackingProtectionExceptions.label "Exceptions…">
<!ENTITY trackingProtectionExceptions.accesskey "x">
<!ENTITY dntTrackingNotOkay4.label "Request that sites not track you">
<!ENTITY dntTrackingNotOkay4.accesskey "n">
<!ENTITY doNotTrackInfo.label "Learn More">
<!ENTITY trackingProtection5.label "Use Tracking Protection">
<!ENTITY trackingProtection5.accesskey "i">
<!ENTITY trackingProtectionLearnMore.label "Learn more">
<!ENTITY tracking.label "Tracking">
<!ENTITY trackingProtectionPBM5.label "Use Tracking Protection in Private Windows">
<!ENTITY trackingProtectionPBM5.accesskey "v">
<!ENTITY trackingProtectionPBMLearnMore.label "Learn more">
<!ENTITY changeBlockList.label "Change Block List">
<!ENTITY changeBlockList.accesskey "C">
<!-- LOCALIZATION NOTE (doNotTrack.pre.label): include a trailing space as needed -->
<!-- LOCALIZATION NOTE (doNotTrack.post.label): include a starting space as needed -->
<!ENTITY doNotTrack.pre.label "You can also ">
<!ENTITY doNotTrack.settings.label "manage your Do Not Track settings">
<!ENTITY doNotTrack.post.label ".">
<!ENTITY history.label "History">
<!ENTITY locationBar.label "Location Bar">

View File

@ -70,6 +70,7 @@
locale/browser/preferences/cookies.dtd (%chrome/browser/preferences/cookies.dtd)
locale/browser/preferences/content.dtd (%chrome/browser/preferences/content.dtd)
locale/browser/preferences/connection.dtd (%chrome/browser/preferences/connection.dtd)
locale/browser/preferences/donottrack.dtd (%chrome/browser/preferences/donottrack.dtd)
locale/browser/preferences/applications.dtd (%chrome/browser/preferences/applications.dtd)
locale/browser/preferences/fonts.dtd (%chrome/browser/preferences/fonts.dtd)
locale/browser/preferences/main.dtd (%chrome/browser/preferences/main.dtd)

View File

@ -189,7 +189,7 @@ var ReaderParent = {
} else {
icon += "reader-tour.png";
}
UITour.showInfo(win, browser.messageManager, target,
UITour.showInfo(win, target,
browserBundle.GetStringFromName("readingList.promo.firstUse.readerView.title"),
browserBundle.GetStringFromName("readingList.promo.firstUse.readerView.body"),
icon);

View File

@ -16,10 +16,11 @@
%define forwardTransitionLength 150ms
%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper
%define conditionalForwardWithUrlbarWidth 31
:root {
--backbutton-urlbar-overlap: 6px;
/* icon width + border + horizontal padding (includes the overlap from backbutton-urlbar-overlap) */
--forwardbutton-width: 31px;
--toolbarbutton-hover-background: rgba(255,255,255,.5) linear-gradient(rgba(255,255,255,.5), transparent);
--toolbarbutton-hover-bordercolor: rgba(0,0,0,.25);
@ -743,7 +744,7 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
padding-right: 3px;
border-left-style: none;
border-radius: 0;
max-width: @conditionalForwardWithUrlbarWidth@px;
max-width: var(--forwardbutton-width);
}
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button {
@ -751,7 +752,7 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
}
@conditionalForwardWithUrlbar@ > #forward-button[disabled] {
margin-left: -@conditionalForwardWithUrlbarWidth@px;
margin-left: calc(0px - var(--forwardbutton-width));
}
@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] {
@ -761,7 +762,7 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] {
/* when not hovered anymore, trigger a new transition to hide the forward button immediately */
margin-left: -@conditionalForwardWithUrlbarWidth@.01px;
margin-left: calc(-0.01px - var(--forwardbutton-width));
}
/* undo close tab menu item */

View File

@ -4,6 +4,10 @@
%include ../shared/devedition.inc.css
:root {
--forwardbutton-width: 29px;
}
:root[devtoolstheme="dark"] .findbar-closebutton:not(:hover),
:root[devtoolstheme="dark"] #sidebar-header > .close-icon:not(:hover),
.tab-close-button[visuallyselected]:not(:hover) {

View File

@ -8,7 +8,6 @@
%filter substitution
%define forwardTransitionLength 150ms
%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper
%define conditionalForwardWithUrlbarWidth 32
%define toolbarButtonPressed :hover:active:not([disabled="true"]):not([cui-areatype="menu-panel"])
%define windowButtonMarginTop 11px
@ -21,6 +20,8 @@
--tabs-toolbar-color: #333;
--backbutton-urlbar-overlap: 6px;
/* icon width + border + horizontal padding (includes the overlap from backbutton-urlbar-overlap) */
--forwardbutton-width: 32px;
--toolbarbutton-hover-background: hsla(0,0%,100%,.1) linear-gradient(hsla(0,0%,100%,.3), hsla(0,0%,100%,.1)) padding-box;
--toolbarbutton-hover-bordercolor: hsla(0,0%,0%,.2);
@ -1371,7 +1372,7 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button {
}
@conditionalForwardWithUrlbar@ > #forward-button[disabled] {
margin-left: -@conditionalForwardWithUrlbarWidth@px;
margin-left: calc(0px - var(--forwardbutton-width));
}
@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] {
@ -1381,7 +1382,7 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button {
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] {
/* when not hovered anymore, trigger a new transition to hide the forward button immediately */
margin-left: -@conditionalForwardWithUrlbarWidth@.01px;
margin-left: calc(-0.01px - var(--forwardbutton-width));
}
.unified-nav-back[_moz-menuactive]:-moz-locale-dir(ltr),

View File

@ -41,6 +41,18 @@
#forward-button {
-moz-border-start: none !important;
/* browser.css and friends set up the width of the button to be 32px.
* They then set margin-left to -2px to ensure the button is not too wide
* compared to the back button, and set padding-left to center the icon
* correctly.
* In our theme, the back and forward buttons are the same width, with the
* back button being 32px with 1px border on both sides. To ensure the
* forward button's content box looks like it is the same size with width
* set to 32px and a 1px border on only 1 side, we overlap by 1px, so both
* buttons end up with a content box that looks like it's 30px.
*/
margin-left: -1px;
padding-left: 1px;
}
#forward-button > .toolbarbutton-icon {

View File

@ -222,11 +222,12 @@ treecol {
/* Privacy pane */
#doNotTrackInfo,
.doNotTrackLearnMore,
#trackingProtectionPBMLearnMore,
#trackingProtectionLearnMore {
-moz-margin-start: 1.5em !important;
margin-top: 0;
font-weight: normal;
}
/* Collapse the non-active vboxes in decks to use only the height the

View File

@ -20,6 +20,9 @@
--backbutton-urlbar-overlap: 6px;
/* icon width + border + horizontal padding (includes the overlap from backbutton-urlbar-overlap) */
--forwardbutton-width: 31px;
--toolbarbutton-vertical-inner-padding: 2px;
--toolbarbutton-vertical-outer-padding: 8px;
@ -939,9 +942,7 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
border-radius: 0 !important;
padding-left: calc(var(--backbutton-urlbar-overlap) + 3px) !important;
padding-right: 3px !important;
% icon width + border + horizontal padding without --backbutton-urlbar-overlap
%define forwardButtonWidth 25
max-width: calc(@forwardButtonWidth@px + var(--backbutton-urlbar-overlap)) !important;
max-width: var(--forwardbutton-width) !important;
}
@conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button {
@ -949,7 +950,7 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
}
@conditionalForwardWithUrlbar@ > #forward-button[disabled] {
margin-left: calc(-@forwardButtonWidth@px - var(--backbutton-urlbar-overlap));
margin-left: calc(0px - var(--forwardbutton-width));
}
@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] {
@ -959,7 +960,7 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] {
/* when not hovered anymore, trigger a new transition to hide the forward button immediately */
margin-left: calc(-@forwardButtonWidth@.01px - var(--backbutton-urlbar-overlap));
margin-left: calc(-0.01px - var(--forwardbutton-width));
}
#back-button {

View File

@ -4,6 +4,10 @@
%include ../shared/devedition.inc.css
:root {
--forwardbutton-width: 29px;
}
:root[devtoolstheme="dark"],
:root[devtoolstheme="light"] {
/* Matches the #browser-border-start, #browser-border-end color */

View File

@ -5725,6 +5725,7 @@ MOZ_DIRECTX_SDK_PATH=
MOZ_D3DCOMPILER_XP_DLL=
MOZ_D3DCOMPILER_XP_CAB=
if test "$COMPILE_ENVIRONMENT" ; then
case "$target_os" in
*mingw*)
MOZ_ANGLE_RENDERER=1
@ -5887,7 +5888,9 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
AC_MSG_ERROR([ Install Windows SDK 8.0+, as well as DirectX SDK (June 2010 version or newer), or reconfigure without this flag.])
fi
fi
fi
fi # MOZ_ANGLE_RENDERER
fi # COMPILE_ENVIRONMENT
dnl ========================================================
@ -6280,41 +6283,49 @@ dnl minimum minor version of Unicode NSIS isn't in the path
dnl (unless in case of cross compiling, for which Unicode
dnl is not yet sufficient).
if test "$OS_ARCH" = "WINNT"; then
MIN_NSIS_MAJOR_VER=2
MIN_NSIS_MINOR_VER=46
MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensis-3.0b1.exe makensisu-3.0a2.exe makensisu-2.46.exe makensis)
MIN_NSIS_MAJOR_VER=3
MIN_NSIS_MINOR_VER=0
MIN_NSIS_PRERELEASE_TYPE=b
MIN_NSIS_PRERELEASE_VER=1
MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensis-3.0b3.exe makensis-3.0b1.exe makensis)
if test -n "$MAKENSISU" -a "$MAKENSISU" != ":"; then
AC_MSG_RESULT([yes])
MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null`
changequote(,)
MAKENSISU_PARSED_VER=`echo "$MAKENSISU_VER" | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\).*\-Unicode$/\1/g'`
MAKENSISU_PARSED_VER=`echo "$MAKENSISU_VER" | sed -e 's/^v\([0-9]\+\.[0-9]\+\).*$/\1/g'`
changequote([,])
if test "$MAKENSISU_PARSED_VER" = ""; then
changequote(,)
MAKENSISU_PARSED_VER=`echo "$MAKENSISU_VER" | sed -e 's/^v\([0-9]\+\.[0-9]\+\).*$/\1/g'`
changequote([,])
fi
MAKENSISU_MAJOR_VER=0
MAKENSISU_MINOR_VER=0
MAKENSISU_PRERELEASE_TYPE=$MIN_NSIS_PRERELEASE_TYPE
MAKENSISU_PRERELEASE_VER=$MIN_NSIS_PRERELEASE_VER
if test ! "$MAKENSISU_PARSED_VER" = ""; then
MAKENSISU_MAJOR_VER=`echo $MAKENSISU_PARSED_VER | $AWK -F\. '{ print $1 }'`
MAKENSISU_MINOR_VER=`echo $MAKENSISU_PARSED_VER | $AWK -F\. '{ print $2 }'`
changequote(,)
MAKENSISU_PARSED_PRERELEASE=`echo "$MAKENSISU_VER" | sed -e 's/^v[0-9]\+\.[0-9]\+\([^0-9]\+\)\([0-9]\+\).*$/\1.\2/g'`
changequote([,])
if test ! "$MAKENSISU_PARSED_PRERELEASE" = "$MAKENSISU_VER"; then
MAKENSISU_PRERELEASE_TYPE=`echo $MAKENSISU_PARSED_PRERELEASE | $AWK -F\. '{ print $1 }'`
MAKENSISU_PRERELEASE_VER=`echo $MAKENSISU_PARSED_PRERELEASE | $AWK -F\. '{ print $2 }'`
fi
fi
AC_MSG_CHECKING([for Unicode NSIS version $MIN_NSIS_MAJOR_VER.$MIN_NSIS_MINOR_VER or greater])
AC_MSG_CHECKING([for NSIS version $MIN_NSIS_MAJOR_VER.$MIN_NSIS_MINOR_VER$MIN_NSIS_PRERELEASE_TYPE$MIN_NSIS_PRERELEASE_VER or greater])
if test "$MAKENSISU_MAJOR_VER" -eq $MIN_NSIS_MAJOR_VER -a \
"$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER ||
test "$MAKENSISU_MAJOR_VER" -gt $MIN_NSIS_MAJOR_VER; then
"$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER -a \
"$MAKENSISU_PRERELEASE_TYPE" = "$MIN_NSIS_PRERELEASE_TYPE" -a \
"$MAKENSISU_PRERELEASE_VER" -ge $MIN_NSIS_PRERELEASE_VER; then
AC_MSG_RESULT([yes])
AC_MSG_RESULT([Found NSIS Version: $MAKENSISU_VER])
else
AC_MSG_RESULT([no])
if test -z "$CROSS_COMPILE"; then
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS version $MIN_NSIS_MAJOR_VER.$MIN_NSIS_MINOR_VER or greater in your path.])
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or NSIS version $MIN_NSIS_MAJOR_VER.$MIN_NSIS_MINOR_VER$MIN_NSIS_PRERELEASE_TYPE$MIN_NSIS_PRERELEASE_VER or greater in your path.])
else
MAKENSISU=
fi
fi
elif test -z "$CROSS_COMPILE"; then
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS version $MIN_NSIS_MAJOR_VER.$MIN_NSIS_MINOR_VER or greater in your path.])
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or NSIS version $MIN_NSIS_MAJOR_VER.$MIN_NSIS_MINOR_VER$MIN_NSIS_PRERELEASE_TYPE$MIN_NSIS_PRERELEASE_VER or greater in your path.])
else
MAKENSISU=
fi
@ -8146,11 +8157,14 @@ if test "$MOZ_TREE_CAIRO"; then
MOZ_ENABLE_D2D_SURFACE=1
MOZ_ENABLE_DWRITE_FONT=1
MOZ_CHECK_HEADER(d3d9.h, MOZ_ENABLE_D3D9_LAYER=1)
if test "$COMPILE_ENVIRONMENT"; then
dnl D3D10 Layers depend on D2D Surfaces.
if test -n "$WIN32_D2D_SURFACE_FEATURE"; then
MOZ_CHECK_HEADER(d3d10.h, MOZ_ENABLE_D3D10_LAYER=1)
MOZ_CHECK_HEADER(d3d9.h, MOZ_ENABLE_D3D9_LAYER=1)
dnl D3D10 Layers depend on D2D Surfaces.
if test -n "$WIN32_D2D_SURFACE_FEATURE"; then
MOZ_CHECK_HEADER(d3d10.h, MOZ_ENABLE_D3D10_LAYER=1)
fi
fi
;;
esac

View File

@ -1,6 +1,7 @@
content devtools client/
skin devtools classic/1.0 client/themes/
resource devtools .
locale devtools en-US client/locales/en-US/
content webide client/webide/content/
skin webide classic/1.0 client/webide/themes/

View File

@ -1,54 +0,0 @@
"use strict";
var SOURCE_URL = getFileUrl("setBreakpoint-on-line-with-no-offests-in-gcd-script.js");
function run_test() {
return Task.spawn(function* () {
do_test_pending();
let global = testGlobal("test");
loadSubScript(SOURCE_URL, global);
Cu.forceGC();
DebuggerServer.registerModule("xpcshell-test/testactors");
DebuggerServer.init(() => true);
DebuggerServer.addTestGlobal(global);
let client = new DebuggerClient(DebuggerServer.connectPipe());
yield connect(client);
let tab = yield findTab(client, "test");
let [, tabClient] = yield attachTab(client, tab);
let [, threadClient] = yield attachThread(tabClient);
yield resume(threadClient);
let source = yield findSource(threadClient, SOURCE_URL);
let sourceClient = threadClient.source(source);
let location = { line: 7 };
let [packet, breakpointClient] = yield setBreakpoint(sourceClient, location);
do_check_true(packet.isPending);
executeSoon(function () {
reload(tabClient).then(function () {
loadSubScript(SOURCE_URL, global);
});
});
packet = yield waitForPaused(threadClient);
do_check_eq(packet.type, "paused");
let why = packet.why;
do_check_eq(why.type, "breakpoint");
do_check_eq(why.actors.length, 1);
do_check_eq(why.actors[0], breakpointClient.actor);
let frame = packet.frame;
let where = frame.where;
do_check_eq(where.source.actor, source.actor);
do_check_eq(where.line, location.line + 1);
let variables = frame.environment.bindings.variables;
do_check_eq(variables.a.value, 1);
do_check_eq(variables.c.value.type, "undefined");
yield resume(threadClient);
yield close(client);
do_test_finished();
});
}

View File

@ -471,8 +471,13 @@ pref("plugin.default.state", 1);
// The breakpad report server to link to in about:crashes
pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/");
pref("app.support.baseURL", "http://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/");
// Used to submit data to input from about:feedback
pref("app.feedback.postURL", "https://input.mozilla.org/api/v1/feedback/");
// URL for feedback page
pref("app.feedbackURL", "about:feedback");
pref("app.privacyURL", "https://www.mozilla.org/privacy/firefox/");
pref("app.creditsURL", "http://www.mozilla.org/credits/");
pref("app.channelURL", "http://www.mozilla.org/%LOCALE%/firefox/channel/");

View File

@ -67,7 +67,14 @@ public abstract class SessionParser {
int selectedIndex = -1;
try {
for (String sessionString : sessionStrings) {
final JSONObject window = new JSONObject(sessionString).getJSONArray("windows").getJSONObject(0);
final JSONArray windowsArray = new JSONObject(sessionString).getJSONArray("windows");
if (windowsArray.length() == 0) {
// Session json can be empty if the user has opted out of session restore.
Log.d(LOGTAG, "Session restore file is empty, no session entries found.");
continue;
}
final JSONObject window = windowsArray.getJSONObject(0);
final JSONArray tabs = window.getJSONArray("tabs");
final int optSelected = window.optInt("selected", -1);
final JSONArray closedTabs = window.optJSONArray("closedTabs");

View File

@ -133,18 +133,15 @@ OnSharedPreferenceChangeListener
private static final String PREFS_TRACKING_PROTECTION_PB = "privacy.trackingprotection.pbmode.enabled";
public static final String PREFS_VOICE_INPUT_ENABLED = NON_PREF_PREFIX + "voice_input_enabled";
public static final String PREFS_QRCODE_ENABLED = NON_PREF_PREFIX + "qrcode_enabled";
private static final String PREFS_ADVANCED = NON_PREF_PREFIX + "advanced.enabled";
private static final String PREFS_ACCESSIBILITY = NON_PREF_PREFIX + "accessibility.enabled";
private static final String PREFS_CUSTOMIZE_HOME = NON_PREF_PREFIX + "customize_home";
private static final String PREFS_TRACKING_PROTECTION_PRIVATE_BROWSING = "privacy.trackingprotection.pbmode.enabled";
private static final String PREFS_TRACKING_PROTECTION_LEARN_MORE = NON_PREF_PREFIX + "trackingprotection.learn_more";
private static final String PREFS_CLEAR_PRIVATE_DATA = NON_PREF_PREFIX + "privacy.clear";
private static final String PREFS_CLEAR_PRIVATE_DATA_EXIT = NON_PREF_PREFIX + "history.clear_on_exit";
private static final String PREFS_SCREEN_ADVANCED = NON_PREF_PREFIX + "advanced_screen";
private static final String PREFS_CATEGORY_HOMEPAGE = NON_PREF_PREFIX + "category_homepage";
public static final String PREFS_HOMEPAGE = NON_PREF_PREFIX + "homepage";
public static final String PREFS_HISTORY_SAVED_SEARCH = NON_PREF_PREFIX + "search.search_history.enabled";
private static final String PREFS_FAQ_LINK = NON_PREF_PREFIX + "faq.link";
private static final String PREFS_FEEDBACK_LINK = NON_PREF_PREFIX + "feedback.link";
private static final String ACTION_STUMBLER_UPLOAD_PREF = AppConstants.ANDROID_PACKAGE_NAME + ".STUMBLER_PREF";
@ -852,6 +849,18 @@ OnSharedPreferenceChangeListener
final String url = getResources().getString(R.string.faq_link, VERSION, OS, LOCALE);
((LinkPreference) pref).setUrl(url);
} else if (PREFS_FEEDBACK_LINK.equals(key)) {
PrefsHelper.getPref("app.feedbackURL", new PrefsHelper.PrefHandlerBase() {
@Override
public void prefValue(String prefName, final String value) {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
((LinkPreference) pref).setUrl(value);
}
});
}
});
}
// Some Preference UI elements are not actually preferences,

View File

@ -35,12 +35,7 @@ public class RestrictedProfileConfiguration implements RestrictionConfiguration
configuration.put(Restrictable.ADVANCED_SETTINGS, false);
configuration.put(Restrictable.CAMERA_MICROPHONE, false);
configuration.put(Restrictable.DATA_CHOICES, false);
// Hold behind Nightly flag until we have an actual block list deployed.
if (AppConstants.NIGHTLY_BUILD) {
configuration.put(Restrictable.BLOCK_LIST, false);
}
configuration.put(Restrictable.BLOCK_LIST, false);
configuration.put(Restrictable.TELEMETRY, false);
configuration.put(Restrictable.HEALTH_REPORT, true);
configuration.put(Restrictable.DEFAULT_THEME, true);
@ -49,12 +44,18 @@ public class RestrictedProfileConfiguration implements RestrictionConfiguration
/**
* These restrictions are hidden from the admin configuration UI.
*/
private static List<Restrictable> hiddenRestrictions = Arrays.asList(
Restrictable.MASTER_PASSWORD,
Restrictable.GUEST_BROWSING,
Restrictable.DATA_CHOICES,
Restrictable.DEFAULT_THEME
);
private static List<Restrictable> hiddenRestrictions = new ArrayList<>();
static {
hiddenRestrictions.add(Restrictable.MASTER_PASSWORD);
hiddenRestrictions.add(Restrictable.GUEST_BROWSING);
hiddenRestrictions.add(Restrictable.DATA_CHOICES);
hiddenRestrictions.add(Restrictable.DEFAULT_THEME);
// Hold behind Nightly flag until we have an actual block list deployed.
if (!AppConstants.NIGHTLY_BUILD){
hiddenRestrictions.add(Restrictable.BLOCK_LIST);
}
}
/* package-private */ static boolean shouldHide(Restrictable restrictable) {
return hiddenRestrictions.contains(restrictable);

View File

@ -354,7 +354,7 @@ public class DateTimePicker extends FrameLayout {
mDaySpinnerInput = (EditText) mDaySpinner.getChildAt(1);
mMonthSpinner = setupSpinner(R.id.month, 1,
mTempDate.get(Calendar.MONTH));
mTempDate.get(Calendar.MONTH) + 1); // Month is 0-based
mMonthSpinner.setFormatter(TWO_DIGIT_FORMATTER);
mMonthSpinner.setDisplayedValues(mShortMonths);
mMonthSpinnerInput = (EditText) mMonthSpinner.getChildAt(1);

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1023 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -19,7 +19,6 @@
<org.mozilla.gecko.preferences.LinkPreference android:key="android.not_a_preference.feedback.link"
android:title="@string/pref_vendor_feedback"
android:persistent="false"
url="about:feedback" />
android:persistent="false"/>
</PreferenceScreen>

View File

@ -4,15 +4,57 @@
"use strict";
var Feedback = {
observe: function(aMessage, aTopic, aData) {
if (aTopic !== "Feedback:Show")
return;
// Only prompt for feedback if this isn't a distribution build.
get _feedbackURL() {
delete this._feedbackURL;
return this._feedbackURL = Services.prefs.getCharPref("app.feedbackURL");
},
observe: function(aMessage, aTopic, aData) {
if (aTopic !== "Feedback:Show") {
return;
}
// Don't prompt for feedback in distribution builds.
try {
Services.prefs.getCharPref("distribution.id");
} catch (e) {
BrowserApp.addTab("about:feedback?source=feedback-prompt", { selected: true, parentId: BrowserApp.selectedTab.id });
return;
} catch (e) {}
let url = this._feedbackURL + "?source=feedback-prompt";
let browser = BrowserApp.selectOrAddTab(url, { parentId: BrowserApp.selectedTab.id }).browser;
browser.addEventListener("FeedbackClose", this, false, true);
browser.addEventListener("FeedbackMaybeLater", this, false, true);
browser.addEventListener("FeedbackOpenPlay", this, false, true);
},
handleEvent: function(event) {
if (!this._isAllowed(event.target)) {
return;
}
switch (event.type) {
case "FeedbackClose":
// Do nothing.
break;
case "FeedbackMaybeLater":
Messaging.sendRequest({ type: "Feedback:MaybeLater" });
break;
case "FeedbackOpenPlay":
Messaging.sendRequest({ type: "Feedback:OpenPlayStore" });
break;
}
let win = event.target.ownerDocument.defaultView.top;
BrowserApp.closeTab(BrowserApp.getTabForWindow(win));
},
_isAllowed: function(node) {
let uri = node.ownerDocument.documentURIObject;
let feedbackURI = Services.io.newURI(this._feedbackURL, null, null);
return uri.prePath === feedbackURI.prePath;
}
};

View File

@ -51,24 +51,31 @@ browser.contentHandlers.types.0.uri=https://add.my.yahoo.com/rss?url=%s
# mobile/android/tests/browser/robocop/testDistribution.java
# to reflect the new set of IDs reported as tiles data.
#
browser.suggestedsites.list.0=mozilla
browser.suggestedsites.list.1=fxaddons
browser.suggestedsites.list.2=fxsupport
browser.suggestedsites.list.0=facebook
browser.suggestedsites.list.1=youtube
browser.suggestedsites.list.2=amazon
browser.suggestedsites.list.3=wikipedia
browser.suggestedsites.list.4=twitter
browser.suggestedsites.mozilla.title=The Mozilla Project
browser.suggestedsites.mozilla.url=https://www.mozilla.org/en-US/
browser.suggestedsites.mozilla.bgcolor=#ce4e41
browser.suggestedsites.mozilla.trackingid=632
browser.suggestedsites.facebook.title=Facebook
browser.suggestedsites.facebook.url=https://m.facebook.com/
browser.suggestedsites.facebook.bgcolor=#385185
browser.suggestedsites.fxaddons.title=Add-ons: Customize Firefox
browser.suggestedsites.fxaddons.url=https://addons.mozilla.org/en-US/android/
browser.suggestedsites.fxaddons.bgcolor=#62be06
browser.suggestedsites.fxaddons.trackingid=630
browser.suggestedsites.youtube.title=YouTube
browser.suggestedsites.youtube.url=https://m.youtube.com/
browser.suggestedsites.youtube.bgcolor=#cd201f
browser.suggestedsites.fxsupport.title=Firefox Help and Support
browser.suggestedsites.fxsupport.url=https://support.mozilla.org/en-US/products/mobile
browser.suggestedsites.fxsupport.bgcolor=#f37c00
browser.suggestedsites.fxsupport.trackingid=631
browser.suggestedsites.amazon.title=Amazon
browser.suggestedsites.amazon.url=https://www.amazon.com/
browser.suggestedsites.amazon.bgcolor=#000000
browser.suggestedsites.wikipedia.title=Wikipedia
browser.suggestedsites.wikipedia.url=https://www.wikipedia.org/
browser.suggestedsites.wikipedia.bgcolor=#000000
browser.suggestedsites.twitter.title=Twitter
browser.suggestedsites.twitter.url=https://mobile.twitter.com/
browser.suggestedsites.twitter.bgcolor=#55acee
browser.suggestedsites.restricted.list.0=restricted_fxsupport
browser.suggestedsites.restricted.list.1=webmaker

View File

@ -420,14 +420,17 @@ interface nsIBrowserSearchService : nsISupports
void removeEngine(in nsISearchEngine engine);
/**
* The default search engine. Returns the first visible engine if the default
* engine is hidden. May be null if there are no visible search engines.
* Alias for the currentEngine attribute, kept for add-on compatibility.
*/
attribute nsISearchEngine defaultEngine;
/**
* The currently active search engine. May be null if there are no visible
* search engines.
* The currently active search engine.
* Unless the application doesn't ship any search plugin, this should never
* be null. If the currently active engine is removed, this attribute will
* fallback first to the original default engine if it's not hidden, then to
* the first visible engine, and as a last resort it will unhide the original
* default engine.
*/
attribute nsISearchEngine currentEngine;

View File

@ -75,7 +75,7 @@ class ProcessExecutionMixin(LoggingMixin):
"""
args = self._normalize_command(args, require_unix_environment)
self.log(logging.INFO, 'new_process', {'args': args}, ' '.join(args))
self.log(logging.INFO, 'new_process', {'args': ' '.join(args)}, '{args}')
def handleLine(line):
# Converts str to unicode on Python 2 and bytes to str on Python 3.
@ -144,7 +144,7 @@ class ProcessExecutionMixin(LoggingMixin):
ensure_exit_code = 0
if status != ensure_exit_code:
raise Exception('Process executed with non-0 exit code: %s' % args)
raise Exception('Process executed with non-0 exit code %d: %s' % (status, args))
return status

View File

@ -50,6 +50,7 @@ import re
import shutil
import stat
import subprocess
import tarfile
import tempfile
import urlparse
import zipfile
@ -131,6 +132,41 @@ class AndroidArtifactJob(ArtifactJob):
writer.add(basename.encode('utf-8'), f)
class LinuxArtifactJob(ArtifactJob):
def process_artifact(self, filename, processed_filename):
with JarWriter(file=processed_filename, optimize=False, compress_level=5) as writer:
prefix = 'firefox/'
whitelist = {
'application.ini',
'crashreporter',
'dependentlibs.list',
'firefox',
'firefox-bin',
'platform.ini',
'plugin-container',
'updater',
'webapprt-stub',
}
with tarfile.open(filename) as reader:
for f in reader:
if not f.isfile():
continue
if not f.name.startswith(prefix):
raise ValueError('Archive format changed! Filename should start with "firefox/"; was "{filename}"'.format(filename=f.name))
basename = f.name[len(prefix):]
if not basename.endswith('.so') and \
basename not in whitelist:
continue
self.log(logging.INFO, 'artifact',
{'basename': basename},
'Adding {basename} to processed archive')
writer.add(basename.encode('utf-8'), reader.extractfile(f), mode=f.mode)
class MacArtifactJob(ArtifactJob):
def process_artifact(self, filename, processed_filename):
tempdir = tempfile.mkdtemp()
@ -223,14 +259,44 @@ class MacArtifactJob(ArtifactJob):
pass
# Keep the keys of this map in sync with the |mach artifact| --job options.
class WinArtifactJob(ArtifactJob):
def process_artifact(self, filename, processed_filename):
with JarWriter(file=processed_filename, optimize=False, compress_level=5) as writer:
prefix = 'firefox/'
whitelist = {
'dependentlibs.list',
'platform.ini',
'application.ini',
}
for f in JarReader(filename):
if not f.filename.startswith(prefix):
raise ValueError('Archive format changed! Filename should start with "firefox/"; was "{filename}"'.format(filename=f.filename))
basename = f.filename[len(prefix):]
if not basename.endswith('.dll') and \
not basename.endswith('.exe') and \
basename not in whitelist:
continue
self.log(logging.INFO, 'artifact',
{'basename': basename},
'Adding {basename} to processed archive')
writer.add(basename.encode('utf-8'), f)
# Keep the keys of this map in sync with the |mach artifact| --job
# options. The keys of this map correspond to entries at
# https://tools.taskcluster.net/index/artifacts/#buildbot.branches.mozilla-central/buildbot.branches.mozilla-central.
JOB_DETAILS = {
# 'android-api-9': (AndroidArtifactJob, 'public/build/fennec-(.*)\.android-arm\.apk'),
'android-api-11': (AndroidArtifactJob, 'public/build/fennec-(.*)\.android-arm\.apk'),
'android-x86': (AndroidArtifactJob, 'public/build/fennec-(.*)\.android-i386\.apk'),
# 'linux': (ArtifactJob, 'public/build/firefox-(.*)\.linux-i686\.tar\.bz2'),
# 'linux64': (ArtifactJob, 'public/build/firefox-(.*)\.linux-x86_64\.tar\.bz2'),
'linux': (LinuxArtifactJob, 'public/build/firefox-(.*)\.linux-i686\.tar\.bz2'),
'linux64': (LinuxArtifactJob, 'public/build/firefox-(.*)\.linux-x86_64\.tar\.bz2'),
'macosx64': (MacArtifactJob, 'public/build/firefox-(.*)\.mac\.dmg'),
'win32': (WinArtifactJob, 'public/build/firefox-(.*)\.win32.zip'),
'win64': (WinArtifactJob, 'public/build/firefox-(.*)\.win64.zip'),
}
def get_job_details(job, log=None):
@ -342,12 +408,39 @@ class PushHeadCache(CacheManager):
@cachedmethod(operator.attrgetter('_cache'))
def pushheads(self, tree, parent):
pushheads = subprocess.check_output([self._hg, 'log',
try:
pushheads = subprocess.check_output([self._hg, 'log',
'--template', '{node}\n',
'-r', 'last(pushhead("{tree}") and ::"{parent}", {num})'.format(
tree=tree, parent=parent, num=NUM_PUSHHEADS_TO_QUERY_PER_PARENT)])
# Filter blank lines.
pushheads = [ pushhead for pushhead in pushheads.strip().split('\n') if pushhead ]
if pushheads:
return pushheads
except subprocess.CalledProcessError as e:
# Probably don't have the mozext extension installed.
ret = subprocess.call([self._hg, 'showconfig', 'extensions.mozext'])
if ret:
raise Exception('Could not find candidate pushheads.\n\n'
'You need to enable the "mozext" hg extension: '
'see https://developer.mozilla.org/en-US/docs/Artifact_builds')
raise e
# Probably don't have the pushlog database present locally. Check.
tree_pushheads = subprocess.check_output([self._hg, 'log',
'--template', '{node}\n',
'-r', 'last(pushhead("{tree}") & ::"{parent}", {num})'.format(
tree=tree, parent=parent, num=NUM_PUSHHEADS_TO_QUERY_PER_PARENT)])
pushheads = pushheads.strip().split('\n')
return pushheads
'-r', 'last(pushhead("{tree}"))'.format(tree=tree)])
# Filter blank lines.
tree_pushheads = [ pushhead for pushhead in tree_pushheads.strip().split('\n') if pushhead ]
if tree_pushheads:
# Okay, we have some pushheads but no candidates. This can happen
# for legitimate reasons: old revisions with no upstream builds
# remaining; or new revisions that don't have upstream builds yet.
return []
raise Exception('Could not find any pushheads for tree "{tree}".\n\n'
'Try running |hg pushlogsync|; '
'see https://developer.mozilla.org/en-US/docs/Artifact_builds'.format(tree=tree))
class TaskCache(CacheManager):
@ -516,7 +609,7 @@ class Artifacts(object):
if info.filename.endswith('.ini'):
continue
n = mozpath.join(bindir, info.filename)
fh = FileAvoidWrite(n, mode='r')
fh = FileAvoidWrite(n, mode='rb')
shutil.copyfileobj(zf.open(info), fh)
file_existed, file_updated = fh.close()
self.log(logging.INFO, 'artifact',

View File

@ -633,7 +633,7 @@ class Build(MachCommandBase):
self.log(logging.INFO, 'artifact',
{}, "Running |mach artifact install|.")
args = [os.path.join(self.topsrcdir, 'mach'), 'artifact', 'install']
self._run_command_in_srcdir(args=args,
self._run_command_in_srcdir(args=args, require_unix_environment=True,
pass_thru=True, ensure_exit_code=True)
@CommandProvider
@ -1397,10 +1397,19 @@ class MachDebug(MachCommandBase):
class ArtifactSubCommand(SubCommand):
def __call__(self, func):
after = SubCommand.__call__(self, func)
jobchoices = {
'android-api-11',
'android-x86',
'linux',
'linux64',
'macosx64',
'win32',
'win64'
}
args = [
CommandArgument('--tree', metavar='TREE', type=str,
help='Firefox tree.'),
CommandArgument('--job', metavar='JOB', choices=['android-api-11', 'android-x86', 'macosx64'],
CommandArgument('--job', metavar='JOB', choices=jobchoices,
help='Build job.'),
CommandArgument('--verbose', '-v', action='store_true',
help='Print verbose output.'),
@ -1446,7 +1455,10 @@ class PackageFrontend(MachCommandBase):
cache_dir = os.path.join(state_dir, 'package-frontend')
import which
hg = which.which('hg')
if self._is_windows():
hg = which.which('hg.exe')
else:
hg = which.which('hg')
# Absolutely must come after the virtualenv is populated!
from mozbuild.artifacts import Artifacts
@ -1460,12 +1472,16 @@ class PackageFrontend(MachCommandBase):
return (tree, job)
if self.substs.get('MOZ_BUILD_APP', '') == 'mobile/android':
if self.substs['ANDROID_CPU_ARCH'] == 'x86':
return (tree, 'android-x86')
return (tree, 'android-api-11')
return tree, 'android-x86'
return tree, 'android-api-11'
# TODO: check for 32/64 bit builds. We'd like to use HAVE_64BIT_BUILD
# but that relies on the compile environment.
if self.defines.get('XP_LINUX', False):
return tree, 'linux64'
if self.defines.get('XP_MACOSX', False):
# TODO: check for 64 bit builds. We'd like to use HAVE_64BIT_BUILD
# but that relies on the compile environment.
return (tree, 'macosx64')
return tree, 'macosx64'
if self.defines.get('XP_WIN', False):
return tree, 'win32'
raise Exception('Cannot determine default tree and job for |mach artifact|!')
@ArtifactSubCommand('artifact', 'install',

View File

@ -166,7 +166,12 @@ class FileAvoidWrite(BytesIO):
existing.close()
ensureParentDir(self.name)
with open(self.name, 'w') as file:
# Maintain 'b' if specified. 'U' only applies to modes starting with
# 'r', so it is dropped.
writemode = 'w'
if 'b' in self.mode:
writemode += 'b'
with open(self.name, writemode) as file:
file.write(buf)
if self._capture_diff:

View File

@ -75,7 +75,7 @@ config = {
'HG_SHARE_BASE_DIR': 'C:/builds/hg-shared',
'MOZ_CRASHREPORTER_NO_REPORT': '1',
'MOZ_OBJDIR': 'obj-firefox',
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/nsis-2.46u;C:/mozilla-build/python27;'
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/python27;'
'C:/mozilla-build/buildbotve/scripts;'
'%s' % (os.environ.get('path')),
'PDBSTR_PATH': '/c/Program Files (x86)/Windows Kits/8.0/Debuggers/x64/srcsrv/pdbstr.exe',

View File

@ -76,7 +76,7 @@ config = {
'HG_SHARE_BASE_DIR': 'C:/builds/hg-shared',
'MOZ_CRASHREPORTER_NO_REPORT': '1',
'MOZ_OBJDIR': 'obj-firefox',
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/nsis-2.46u;C:/mozilla-build/python27;'
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/python27;'
'C:/mozilla-build/buildbotve/scripts;'
'%s' % (os.environ.get('path')),
'PDBSTR_PATH': '/c/Program Files (x86)/Windows Kits/8.0/Debuggers/x64/srcsrv/pdbstr.exe',

View File

@ -75,7 +75,8 @@ config = {
'HG_SHARE_BASE_DIR': 'C:/builds/hg-shared',
'MOZ_CRASHREPORTER_NO_REPORT': '1',
'MOZ_OBJDIR': 'obj-firefox',
'PATH': 'C:/mozilla-build/python27;C:/mozilla-build/buildbotve/scripts;'
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/python27;'
'C:/mozilla-build/buildbotve/scripts;'
'%s' % (os.environ.get('path')),
'PDBSTR_PATH': '/c/Program Files (x86)/Windows Kits/8.0/Debuggers/x64/srcsrv/pdbstr.exe',
'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),

View File

@ -26,7 +26,7 @@ config = {
'MOZ_AUTOMATION': '1',
'MOZ_CRASHREPORTER_NO_REPORT': '1',
'MOZ_OBJDIR': 'obj-firefox',
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/nsis-2.46u;C:/mozilla-build/python27;'
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/python27;'
'C:/mozilla-build/buildbotve/scripts;'
'%s' % (os.environ.get('path')),
'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),

View File

@ -25,7 +25,7 @@ config = {
'MOZ_AUTOMATION': '1',
'MOZ_CRASHREPORTER_NO_REPORT': '1',
'MOZ_OBJDIR': 'obj-firefox',
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/nsis-2.46u;C:/mozilla-build/python27;'
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/python27;'
'C:/mozilla-build/buildbotve/scripts;'
'%s' % (os.environ.get('path')),
'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),

View File

@ -25,7 +25,8 @@ config = {
'MOZ_AUTOMATION': '1',
'MOZ_CRASHREPORTER_NO_REPORT': '1',
'MOZ_OBJDIR': 'obj-firefox',
'PATH': 'C:/mozilla-build/python27;C:/mozilla-build/buildbotve/scripts;'
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/python27;'
'C:/mozilla-build/buildbotve/scripts;'
'%s' % (os.environ.get('path')),
'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),
'TINDERBOX_OUTPUT': '1',

View File

@ -25,7 +25,7 @@ config = {
'MOZ_AUTOMATION': '1',
'MOZ_CRASHREPORTER_NO_REPORT': '1',
'MOZ_OBJDIR': 'obj-graphene',
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/nsis-2.46u;C:/mozilla-build/python27;'
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/python27;'
'C:/mozilla-build/buildbotve/scripts;'
'%s' % (os.environ.get('path')),
'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),

View File

@ -25,7 +25,7 @@ config = {
'MOZ_AUTOMATION': '1',
'MOZ_CRASHREPORTER_NO_REPORT': '1',
'MOZ_OBJDIR': 'obj-horizon',
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/nsis-2.46u;C:/mozilla-build/python27;'
'PATH': 'C:/mozilla-build/nsis-3.0b1;C:/mozilla-build/python27;'
'C:/mozilla-build/buildbotve/scripts;'
'%s' % (os.environ.get('path')),
'PROPERTIES_FILE': os.path.join(os.getcwd(), 'buildprops.json'),

View File

@ -924,21 +924,6 @@ function getLocalizedPref(aPrefName, aDefault) {
return aDefault;
}
/**
* Wrapper for nsIPrefBranch::setComplexValue.
* @param aPrefName
* The name of the pref to set.
*/
function setLocalizedPref(aPrefName, aValue) {
const nsIPLS = Ci.nsIPrefLocalizedString;
try {
var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
.createInstance(Ci.nsIPrefLocalizedString);
pls.data = aValue;
Services.prefs.setComplexValue(aPrefName, nsIPLS, pls);
} catch (ex) {}
}
/**
* Wrapper for nsIPrefBranch::getBoolPref.
* @param aPrefName
@ -3122,7 +3107,6 @@ SearchService.prototype = {
this._engines = {};
this.__sortedEngines = null;
this._currentEngine = null;
this._defaultEngine = null;
this._visibleDefaultEngines = [];
this._metaData = {};
this._cacheFileJSON = null;
@ -3987,10 +3971,6 @@ SearchService.prototype = {
this._currentEngine = null;
}
if (engineToRemove == this.defaultEngine) {
this._defaultEngine = null;
}
if (engineToRemove._readOnly) {
// Just hide it (the "hidden" setter will notify) and remove its alias to
// avoid future conflicts with other engines.
@ -4082,52 +4062,10 @@ SearchService.prototype = {
}
},
get defaultEngine() {
this._ensureInitialized();
if (!this._defaultEngine) {
let defPref = getGeoSpecificPrefName(BROWSER_SEARCH_PREF + "defaultenginename");
let defaultEngine = this.getEngineByName(getLocalizedPref(defPref, ""))
if (!defaultEngine)
defaultEngine = this._getSortedEngines(false)[0] || null;
this._defaultEngine = defaultEngine;
}
if (this._defaultEngine.hidden)
return this._getSortedEngines(false)[0];
return this._defaultEngine;
},
get defaultEngine() { return this.currentEngine; },
set defaultEngine(val) {
this._ensureInitialized();
// Sometimes we get wrapped nsISearchEngine objects (external XPCOM callers),
// and sometimes we get raw Engine JS objects (callers in this file), so
// handle both.
if (!(val instanceof Ci.nsISearchEngine) && !(val instanceof Engine))
FAIL("Invalid argument passed to defaultEngine setter");
let newDefaultEngine = this.getEngineByName(val.name);
if (!newDefaultEngine)
FAIL("Can't find engine in store!", Cr.NS_ERROR_UNEXPECTED);
if (newDefaultEngine == this._defaultEngine)
return;
this._defaultEngine = newDefaultEngine;
let defPref = getGeoSpecificPrefName(BROWSER_SEARCH_PREF + "defaultenginename");
// If we change the default engine in the future, that change should impact
// users who have switched away from and then back to the build's "default"
// engine. So clear the user pref when the defaultEngine is set to the
// build's default engine, so that the defaultEngine getter falls back to
// whatever the default is.
if (this._defaultEngine == this._originalDefaultEngine) {
Services.prefs.clearUserPref(defPref);
}
else {
setLocalizedPref(defPref, this._defaultEngine.name);
}
notifyAction(this._defaultEngine, SEARCH_ENGINE_DEFAULT);
this.currentEngine = val;
},
get currentEngine() {
@ -4204,6 +4142,7 @@ SearchService.prototype = {
this.setGlobalAttr("current", newName);
this.setGlobalAttr("hash", getVerificationHash(newName));
notifyAction(this._currentEngine, SEARCH_ENGINE_DEFAULT);
notifyAction(this._currentEngine, SEARCH_ENGINE_CURRENT);
},

View File

@ -458,18 +458,14 @@ function installTestEngine() {
}
/**
* Wrapper for nsIPrefBranch::setComplexValue.
* Set a localized preference on the default branch
* @param aPrefName
* The name of the pref to set.
*/
function setLocalizedPref(aPrefName, aValue) {
const nsIPLS = Ci.nsIPrefLocalizedString;
try {
var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
.createInstance(Ci.nsIPrefLocalizedString);
pls.data = aValue;
Services.prefs.setComplexValue(aPrefName, nsIPLS, pls);
} catch (ex) {}
function setLocalizedDefaultPref(aPrefName, aValue) {
let value = "data:text/plain," + BROWSER_SEARCH_PREF + aPrefName + "=" + aValue;
Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF)
.setCharPref(aPrefName, value);
}
@ -496,8 +492,8 @@ function setUpGeoDefaults() {
do_get_file("data/engine2.xml").copyTo(engineDir, "engine2.xml");
setLocalizedPref("browser.search.defaultenginename", "Test search engine");
setLocalizedPref("browser.search.defaultenginename.US", "A second test engine");
setLocalizedDefaultPref("defaultenginename", "Test search engine");
setLocalizedDefaultPref("defaultenginename.US", "A second test engine");
do_register_cleanup(function() {
removeMetadata();

View File

@ -17,13 +17,15 @@ function run_test() {
}
add_task(function* test_defaultEngine() {
let search = Services.search;
let originalDefault = search.defaultEngine;
let [engine1, engine2] = yield addTestEngines([
{ name: "Test search engine", xmlFileName: "engine.xml" },
{ name: "A second test engine", xmlFileName: "engine2.xml" },
]);
let search = Services.search;
search.defaultEngine = engine1;
do_check_eq(search.defaultEngine, engine1);
search.defaultEngine = engine2
@ -32,22 +34,18 @@ add_task(function* test_defaultEngine() {
do_check_eq(search.defaultEngine, engine1);
// Test that hiding the currently-default engine affects the defaultEngine getter
// (when the default is hidden, we fall back to the first in the list, so move
// our second engine to that position)
search.moveEngine(engine2, 0);
// We fallback first to the original default...
engine1.hidden = true;
do_check_eq(search.defaultEngine, engine2);
do_check_eq(search.defaultEngine, originalDefault);
// Test that the default engine is restored when it is unhidden
engine1.hidden = false;
do_check_eq(search.defaultEngine, engine1);
// ... and then to the first visible engine in the list, so move our second
// engine to that position.
search.moveEngine(engine2, 0);
originalDefault.hidden = true;
do_check_eq(search.defaultEngine, engine2);
// Test that setting defaultEngine to an already-hidden engine works, but
// doesn't change the return value of the getter
engine2.hidden = true;
search.moveEngine(engine1, 0)
search.defaultEngine = engine2;
do_check_eq(search.defaultEngine, engine1);
engine2.hidden = false;
search.defaultEngine = engine1;
do_check_eq(search.defaultEngine, engine2);
});

View File

@ -48,11 +48,8 @@ add_task(function* test_persistAcrossRestarts() {
do_check_eq(Services.search.currentEngine.name, kTestEngineName);
// Cleanup (set the engine back to default).
Services.search.currentEngine = Services.search.defaultEngine;
// This check is no longer valid with bug 1102416's patch - defaultEngine
// is not based on the same value as _originalDefaultEngine in non-Firefox
// users of the search service.
//do_check_eq(Services.search.currentEngine.name, getDefaultEngineName());
Services.search.resetToOriginalDefaultEngine();
do_check_eq(Services.search.currentEngine.name, getDefaultEngineName());
});
// An engine set without a valid hash should be ignored.

View File

@ -794,7 +794,7 @@ EnvironmentCache.prototype = {
if (!Preferences.isSet(pref)) {
continue;
}
// Check the policy for the preference and decide if we need to store its value
// or whether it changed from the default value.
let prefValue = undefined;
@ -863,7 +863,7 @@ EnvironmentCache.prototype = {
this._log.trace("observe - aTopic: " + aTopic + ", aData: " + aData);
switch (aTopic) {
case SEARCH_ENGINE_MODIFIED_TOPIC:
if (aData != "engine-default" && aData != "engine-current") {
if (aData != "engine-current") {
return;
}
// Record the new default search choice and send the change notification.

View File

@ -1115,10 +1115,10 @@ add_task(function* test_defaultSearchEngine() {
for (let engine of Services.search.getEngines()) {
Services.search.removeEngine(engine);
}
// The search service does not notify "engine-default" when removing a default engine.
// The search service does not notify "engine-current" when removing a default engine.
// Manually force the notification.
// TODO: remove this when bug 1165341 is resolved.
Services.obs.notifyObservers(null, "browser-search-engine-modified", "engine-default");
Services.obs.notifyObservers(null, "browser-search-engine-modified", "engine-current");
// Then check that no default engine is reported if none is available.
data = TelemetryEnvironment.currentEnvironment;