merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-09-11 15:29:54 +02:00
commit ca0a81a939
40 changed files with 573 additions and 89 deletions

View File

@ -96,7 +96,7 @@ function shouldAllowRelink(acctName) {
let wrapper = {
iframe: null,
init: function (url=null) {
init: function (url, entryPoint) {
let weave = Cc["@mozilla.org/weave/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject;
@ -116,9 +116,11 @@ let wrapper = {
let iframe = document.getElementById("remote");
this.iframe = iframe;
iframe.addEventListener("load", this);
try {
iframe.src = url || fxAccounts.getAccountsSignUpURI();
if (entryPoint) {
url += (url.indexOf("?") >= 0 ? "&" : "?") + entryPoint;
}
iframe.src = url;
} catch (e) {
error("Couldn't init Firefox Account wrapper: " + e.message);
}
@ -288,6 +290,17 @@ function openPrefs() {
function init() {
fxAccounts.getSignedInUser().then(user => {
// If the url contains an entrypoint query parameter, extract it into a variable
// to append it to the accounts URI resource.
// Works for the following cases:
// - about:accounts?entrypoint="abouthome"
// - about:accounts?entrypoint=abouthome&action=signup
let entryPointQParam = "entrypoint=";
let entryPointPos = window.location.href.indexOf(entryPointQParam);
let entryPoint = "";
if (entryPointPos >= 0) {
entryPoint = window.location.href.substring(entryPointPos).split("&")[0];
}
// tests in particular might cause the window to start closing before
// getSignedInUser has returned.
if (window.closed) {
@ -299,7 +312,7 @@ function init() {
show("stage", "manage");
} else {
show("remote");
wrapper.init(fxAccounts.getAccountsSignInURI());
wrapper.init(fxAccounts.getAccountsSignInURI(), entryPoint);
}
} else if (window.location.href.contains("action=signup")) {
if (user) {
@ -307,7 +320,7 @@ function init() {
show("stage", "manage");
} else {
show("remote");
wrapper.init();
wrapper.init(fxAccounts.getAccountsSignUpURI(), entryPoint);
}
} else if (window.location.href.contains("action=reauth")) {
// ideally we would only show this when we know the user is in a
@ -316,7 +329,7 @@ function init() {
// promiseAccountsForceSigninURI, just always show it.
fxAccounts.promiseAccountsForceSigninURI().then(url => {
show("remote");
wrapper.init(url);
wrapper.init(url, entryPoint);
});
} else {
// No action specified
@ -327,7 +340,7 @@ function init() {
} else {
show("stage", "intro");
// load the remote frame in the background
wrapper.init();
wrapper.init(fxAccounts.getAccountsSignUpURI(), entryPoint);
}
}
});

View File

@ -224,10 +224,22 @@ let gFxAccounts = {
},
openAccountsPage: function () {
switchToTabHavingURI("about:accounts", true);
let entryPoint = "menupanel";
if (UITour.originTabs.get(window) && UITour.originTabs.get(window).has(gBrowser.selectedTab)) {
entryPoint = "uitour";
}
switchToTabHavingURI("about:accounts?entrypoint=" + entryPoint, true, {
replaceQueryString: true
});
},
openSignInAgainPage: function () {
switchToTabHavingURI("about:accounts?action=reauth", true);
let entryPoint = "menupanel";
if (UITour.originTabs.get(window) && UITour.originTabs.get(window).has(gBrowser.selectedTab)) {
entryPoint = "uitour";
}
switchToTabHavingURI("about:accounts?action=reauth&entrypoint=" + entryPoint, true, {
replaceQueryString: true
});
}
};

View File

@ -476,7 +476,7 @@
label="&syncSetup.label;"
accesskey="&syncSetup.accesskey;"
observes="sync-setup-state"
oncommand="gSyncUI.openSetup()"/>
oncommand="gSyncUI.openSetup(null, 'menubar')"/>
<menuitem id="sync-syncnowitem"
label="&syncSyncNowItem.label;"
accesskey="&syncSyncNowItem.accesskey;"
@ -486,7 +486,7 @@
label="&syncReAuthItem.label;"
accesskey="&syncReAuthItem.accesskey;"
observes="sync-reauth-state"
oncommand="gSyncUI.openSignInAgainPage();"/>
oncommand="gSyncUI.openSignInAgainPage('menubar');"/>
#endif
<menuseparator id="devToolsSeparator"/>
<menu id="webDeveloperMenu"

View File

@ -314,9 +314,11 @@ let gSyncUI = {
* null -- regular set up wizard
* "pair" -- pair a device first
* "reset" -- reset sync
* @param entryPoint
* Indicates the entrypoint from where this method was called.
*/
openSetup: function SUI_openSetup(wizardType) {
openSetup: function SUI_openSetup(wizardType, entryPoint = "syncbutton") {
let xps = Components.classes["@mozilla.org/weave/service;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
@ -325,7 +327,13 @@ let gSyncUI = {
if (userData) {
this.openPrefs();
} else {
switchToTabHavingURI("about:accounts", true);
// If the user is also in an uitour, set the entrypoint to `uitour`
if (UITour.originTabs.get(window) && UITour.originTabs.get(window).has(gBrowser.selectedTab)) {
entryPoint = "uitour";
}
switchToTabHavingURI("about:accounts?entrypoint=" + entryPoint, true, {
replaceQueryString: true
});
}
});
} else {
@ -366,8 +374,14 @@ let gSyncUI = {
openPreferences("paneSync");
},
openSignInAgainPage: function () {
switchToTabHavingURI("about:accounts?action=reauth", true);
openSignInAgainPage: function (entryPoint = "syncbutton") {
// If the user is also in an uitour, set the entrypoint to `uitour`
if (UITour.originTabs.get(window) && UITour.originTabs.get(window).has(gBrowser.selectedTab)) {
entryPoint = "uitour";
}
switchToTabHavingURI("about:accounts?action=reauth&entrypoint=" + entryPoint, true, {
replaceQueryString: true
});
},
// Helpers

View File

@ -180,6 +180,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "TabCrashReporter",
XPCOMUtils.defineLazyModuleGetter(this, "FormValidationHandler",
"resource:///modules/FormValidationHandler.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UITour",
"resource:///modules/UITour.jsm");
let gInitialPages = [
"about:blank",
"about:newtab",
@ -6917,9 +6920,13 @@ let gRemoteTabsUI = {
* If switching to this URI results in us opening a tab, aOpenParams
* will be the parameter object that gets passed to openUILinkIn. Please
* see the documentation for openUILinkIn to see what parameters can be
* passed via this object. This object also allows the 'ignoreFragment'
* property to be set to true to exclude fragment-portion matching when
* comparing URIs.
* passed via this object.
* This object also allows:
* - 'ignoreFragment' property to be set to true to exclude fragment-portion
* matching when comparing URIs.
* - 'replaceQueryString' property to be set to true to exclude query string
* matching when comparing URIs and ovewrite the initial query string with
* the one from the new URI.
* @return True if an existing tab was found, false otherwise
*/
function switchToTabHavingURI(aURI, aOpenNew, aOpenParams={}) {
@ -6930,6 +6937,8 @@ function switchToTabHavingURI(aURI, aOpenNew, aOpenParams={}) {
]);
let ignoreFragment = aOpenParams.ignoreFragment;
let replaceQueryString = aOpenParams.replaceQueryString;
// This property is only used by switchToTabHavingURI and should
// not be used as a parameter for the new load.
delete aOpenParams.ignoreFragment;
@ -6961,6 +6970,15 @@ function switchToTabHavingURI(aURI, aOpenNew, aOpenParams={}) {
}
return true;
}
if (replaceQueryString) {
if (browser.currentURI.spec.split("?")[0] == aURI.spec.split("?")[0]) {
// Focus the matching window & tab
aWindow.focus();
aWindow.gBrowser.tabContainer.selectedIndex = i;
browser.loadURI(aURI.spec);
return true;
}
}
}
return false;
}

View File

@ -189,6 +189,38 @@ let gTests = [
is(tab.linkedBrowser.contentDocument.location.href, "about:accounts?action=signin");
}
},
{
desc: "Test entrypoint query string, no action, no user logged in",
teardown: () => gBrowser.removeCurrentTab(),
run: function* () {
// When this loads with no user logged-in, we expect the "normal" URL
setPref("identity.fxaccounts.remote.signup.uri", "https://example.com/");
let [tab, url] = yield promiseNewTabWithIframeLoadEvent("about:accounts?entrypoint=abouthome");
is(url, "https://example.com/?entrypoint=abouthome", "entrypoint=abouthome got the expected URL");
},
},
{
desc: "Test entrypoint query string for signin",
teardown: () => gBrowser.removeCurrentTab(),
run: function* () {
// When this loads with no user logged-in, we expect the "normal" URL
const expected_url = "https://example.com/?is_sign_in";
setPref("identity.fxaccounts.remote.signin.uri", expected_url);
let [tab, url] = yield promiseNewTabWithIframeLoadEvent("about:accounts?action=signin&entrypoint=abouthome");
is(url, expected_url + "&entrypoint=abouthome", "entrypoint=abouthome got the expected URL");
},
},
{
desc: "Test entrypoint query string for signup",
teardown: () => gBrowser.removeCurrentTab(),
run: function* () {
// When this loads with no user logged-in, we expect the "normal" URL
const sign_up_url = "https://example.com/?is_sign_up";
setPref("identity.fxaccounts.remote.signup.uri", sign_up_url);
let [tab, url] = yield promiseNewTabWithIframeLoadEvent("about:accounts?entrypoint=abouthome&action=signup");
is(url, sign_up_url + "&entrypoint=abouthome", "entrypoint=abouthome got the expected URL");
},
},
]; // gTests
function test()

View File

@ -454,6 +454,18 @@ let gTests = [
yield promiseWaitForCondition(() => doc.activeElement === searchInput);
is(searchInput, doc.activeElement, "Search bar should be the active element.");
})
},
{
desc: "Sync button should open about:accounts page with `abouthome` entrypoint",
setup: function () {},
run: Task.async(function* () {
let syncButton = gBrowser.selectedTab.linkedBrowser.contentDocument.getElementById("sync");
yield EventUtils.synthesizeMouseAtCenter(syncButton, {}, gBrowser.contentWindow);
yield promiseTabLoadEvent(gBrowser.selectedTab, null, "load");
is(gBrowser.currentURI.spec, "about:accounts?entrypoint=abouthome",
"Entry point should be `abouthome`.");
})
}
];

View File

@ -15,21 +15,48 @@ add_task(function() {
gBrowser.selectedTab = tabRefAboutMozilla;
let numTabsAtStart = gBrowser.tabs.length;
switchTab("about:home#1", false, true);
switchTab("about:mozilla", false, true);
switchTab("about:home#2", true, true);
switchTab("about:home#1", false, false, true);
switchTab("about:mozilla", false, false, true);
switchTab("about:home#2", true, false, true);
is(tabRefAboutHome, gBrowser.selectedTab, "The same about:home tab should be switched to");
is(gBrowser.currentURI.ref, "2", "The ref should be updated to the new ref");
switchTab("about:mozilla", false, true);
switchTab("about:home#1", false, false);
switchTab("about:mozilla", false, false, true);
switchTab("about:home#1", false, false, false);
isnot(tabRefAboutHome, gBrowser.selectedTab, "Selected tab should not be initial about:blank tab");
is(gBrowser.tabs.length, numTabsAtStart + 1, "Should have one new tab opened");
switchTab("about:about", true, false);
switchTab("about:about", true, false, false);
});
function switchTab(aURI, aIgnoreFragment, aShouldFindExistingTab) {
let tabFound = switchToTabHavingURI(aURI, true, {ignoreFragment: aIgnoreFragment});
// Test for replaceQueryString option.
add_task(function() {
registerCleanupFunction(function() {
while (gBrowser.tabs.length > 1)
gBrowser.removeCurrentTab();
});
let tabRefAboutHome = gBrowser.addTab("about:home?hello=firefox");
yield promiseTabLoaded(tabRefAboutHome);
switchTab("about:home", false, false, false);
switchTab("about:home?hello=firefox", false, false, true);
switchTab("about:home?hello=firefoxos", false, false, false);
// Remove the last opened tab to test replaceQueryString option.
gBrowser.removeCurrentTab();
switchTab("about:home?hello=firefoxos", false, true, true);
is(tabRefAboutHome, gBrowser.selectedTab, "Selected tab should be the initial about:home tab");
// Wait for the tab to load the new URI spec.
yield promiseTabLoaded(tabRefAboutHome);
is(gBrowser.currentURI.spec, "about:home?hello=firefoxos", "The spec should be updated to the new spec");
});
function switchTab(aURI, aIgnoreFragment, aReplaceQueryString, aShouldFindExistingTab) {
let tabFound = switchToTabHavingURI(aURI, true, {
ignoreFragment: aIgnoreFragment,
replaceQueryString: aReplaceQueryString
});
is(tabFound, aShouldFindExistingTab,
"Should switch to existing " + aURI + " tab if one existed, " +
(aIgnoreFragment ? "ignoring" : "including") + " fragment portion");
(aIgnoreFragment ? "ignoring" : "including") + " fragment portion, " +
(aReplaceQueryString ? "ignoring" : "replacing") + " query string.");
}

View File

@ -2,12 +2,16 @@
* 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/. */
// The test expects the about:accounts page to open in the current tab
"use strict";
XPCOMUtils.defineLazyModuleGetter(this, "UITour", "resource:///modules/UITour.jsm");
let initialLocation = gBrowser.currentURI.spec;
let newTab = null;
add_task(function() {
function openAboutAccountsFromMenuPanel(entryPoint) {
info("Check Sync button functionality");
Services.prefs.setCharPref("identity.fxaccounts.remote.signup.uri", "http://example.com/");
@ -17,14 +21,27 @@ add_task(function() {
// check the button's functionality
yield PanelUI.show();
if (entryPoint == "uitour") {
UITour.originTabs.set(window, new Set());
UITour.originTabs.get(window).add(gBrowser.selectedTab);
}
let syncButton = document.getElementById("sync-button");
ok(syncButton, "The Sync button was added to the Panel Menu");
let deferred = Promise.defer();
let handler = () => {
gBrowser.selectedTab.removeEventListener("load", handler, true);
deferred.resolve();
}
gBrowser.selectedTab.addEventListener("load", handler, true);
syncButton.click();
yield deferred.promise;
newTab = gBrowser.selectedTab;
yield promiseTabLoadEvent(newTab, "about:accounts");
is(gBrowser.currentURI.spec, "about:accounts", "Firefox Sync page opened");
is(gBrowser.currentURI.spec, "about:accounts?entrypoint=" + entryPoint,
"Firefox Sync page opened with `menupanel` entrypoint");
ok(!isPanelUIOpen(), "The panel closed");
if(isPanelUIOpen()) {
@ -32,9 +49,9 @@ add_task(function() {
PanelUI.hide();
yield panelHidePromise;
}
});
}
add_task(function asyncCleanup() {
function asyncCleanup() {
Services.prefs.clearUserPref("identity.fxaccounts.remote.signup.uri");
// reset the panel UI to the default state
yield resetCustomization();
@ -43,4 +60,11 @@ add_task(function asyncCleanup() {
// restore the tabs
gBrowser.addTab(initialLocation);
gBrowser.removeTab(newTab);
});
UITour.originTabs.delete(window);
}
add_task(() => openAboutAccountsFromMenuPanel("syncbutton"));
add_task(asyncCleanup);
// Test that uitour is in progress, the entrypoint is `uitour` and not `menupanel`
add_task(() => openAboutAccountsFromMenuPanel("uitour"));
add_task(asyncCleanup);

View File

@ -2263,6 +2263,22 @@ let E10SUINotification = {
if (!activationNoticeShown) {
this._showE10sActivatedNotice();
}
} else {
let e10sPromptShownCount = 0;
try {
e10sPromptShownCount = Services.prefs.getIntPref("browser.displayedE10SPrompt");
} catch(e) {}
if (!Services.appinfo.inSafeMode && e10sPromptShownCount < 5) {
Services.tm.mainThread.dispatch(() => {
try {
this._showE10SPrompt();
Services.prefs.setIntPref("browser.displayedE10SPrompt", e10sPromptShownCount + 1);
} catch (ex) {
Cu.reportError("Failed to show e10s prompt: " + ex);
}
}, Ci.nsIThread.DISPATCH_NORMAL);
}
}
},
@ -2287,7 +2303,47 @@ let E10SUINotification = {
nb.appendNotification(message, "e10s-activated-noticed",
null, nb.PRIORITY_WARNING_MEDIUM, buttons);
}
},
_showE10SPrompt: function BG__showE10SPrompt() {
let win = RecentWindow.getMostRecentBrowserWindow();
if (!win)
return;
let browser = win.gBrowser.selectedBrowser;
let promptMessage = "Would you like to help us test multiprocess Nightly (e10s)? You can also enable e10s in Nightly preferences.";
let mainAction = {
label: "Enable and Restart",
accessKey: "E",
callback: function () {
Services.prefs.setBoolPref("browser.tabs.remote.autostart", true);
Services.prefs.setBoolPref("browser.enabledE10SFromPrompt", true);
// Restart the app
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
if (cancelQuit.data)
return; // somebody canceled our quit request
Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);
}
};
let secondaryActions = [
{
label: "No thanks",
accessKey: "N",
callback: function () {
Services.prefs.setIntPref("browser.displayedE10SPrompt", 5);
}
}
];
let options = {
popupIconURL: "chrome://browser/skin/e10s-64@2x.png",
learnMoreURL: "https://wiki.mozilla.org/Electrolysis",
persistWhileVisible: true
};
win.PopupNotifications.show(browser, "enable_e10s", promptMessage, null, mainAction, secondaryActions, options);
},
};
#endif

View File

@ -88,12 +88,52 @@ var gMainPane = {
setEventListener("chooseFolder", "command",
gMainPane.chooseFolder);
#ifdef E10S_TESTING_ONLY
setEventListener("e10sAutoStart", "command",
gMainPane.enableE10SChange);
let e10sCheckbox = document.getElementById("e10sAutoStart");
let e10sPref = document.getElementById("browser.tabs.remote.autostart");
e10sCheckbox.checked = e10sPref.value;
#endif
// Notify observers that the UI is now ready
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService)
.notifyObservers(window, "main-pane-loaded", null);
},
#ifdef E10S_TESTING_ONLY
enableE10SChange: function ()
{
let e10sCheckbox = document.getElementById("e10sAutoStart");
let e10sPref = document.getElementById("browser.tabs.remote.autostart");
const Cc = Components.classes, Ci = Components.interfaces;
let brandName = document.getElementById("bundleBrand").getString("brandShortName");
let bundle = document.getElementById("bundlePreferences");
let msg = bundle.getFormattedString(e10sCheckbox.checked ?
"featureEnableRequiresRestart" : "featureDisableRequiresRestart",
[brandName]);
let title = bundle.getFormattedString("shouldRestartTitle", [brandName]);
let shouldProceed = Services.prompt.confirm(window, title, msg)
if (shouldProceed) {
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
"restart");
shouldProceed = !cancelQuit.data;
if (shouldProceed) {
e10sPref.value = e10sCheckbox.checked;
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
}
}
// Revert the checkbox in case we didn't quit
e10sCheckbox.checked = e10sPref.value;
},
#endif
// HOME PAGE
/*

View File

@ -9,6 +9,12 @@
<preferences id="mainPreferences">
#ifdef E10S_TESTING_ONLY
<preference id="browser.tabs.remote.autostart"
name="browser.tabs.remote.autostart"
type="bool"/>
#endif
<!-- Startup -->
<preference id="browser.startup.page"
name="browser.startup.page"
@ -108,6 +114,11 @@
hidden="true">
<caption><label>&startup.label;</label></caption>
#ifdef E10S_TESTING_ONLY
<checkbox id="e10sAutoStart"
label="Enable E10S (multi-process)"/>
#endif
#ifdef HAVE_SHELL_SERVICE
<vbox id="defaultBrowserBox">
<hbox align="center">

View File

@ -4,7 +4,7 @@
# 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/.
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME', 'E10S_TESTING_ONLY'):
DEFINES[var] = CONFIG[var]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'cocoa'):

View File

@ -313,7 +313,9 @@ let gSyncPane = {
.wrappedJSObject;
if (service.fxAccountsEnabled) {
this.openContentInBrowser("about:accounts");
this.openContentInBrowser("about:accounts?entrypoint=preferences", {
replaceQueryString: true
});
} else {
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
if (win)
@ -326,7 +328,7 @@ let gSyncPane = {
}
},
openContentInBrowser: function(url) {
openContentInBrowser: function(url, options) {
let win = Services.wm.getMostRecentWindow("navigator:browser");
if (!win) {
// no window to use, so use _openLink to create a new one. We don't
@ -335,7 +337,7 @@ let gSyncPane = {
gSyncUtils._openLink(url);
return;
}
win.openUILinkIn(url, "tab");
win.switchToTabHavingURI(url, true, options);
},
@ -350,15 +352,21 @@ let gSyncPane = {
},
signUp: function() {
this.openContentInBrowser("about:accounts?action=signup");
this.openContentInBrowser("about:accounts?action=signup&entrypoint=preferences", {
replaceQueryString: true
});
},
signIn: function() {
this.openContentInBrowser("about:accounts?action=signin");
this.openContentInBrowser("about:accounts?action=signin&entrypoint=preferences", {
replaceQueryString: true
});
},
reSignIn: function() {
this.openContentInBrowser("about:accounts?action=reauth");
this.openContentInBrowser("about:accounts?action=reauth&entrypoint=preferences", {
replaceQueryString: true
});
},
manageFirefoxAccount: function() {

View File

@ -229,7 +229,9 @@ let gSyncPane = {
.wrappedJSObject;
if (service.fxAccountsEnabled) {
this.openContentInBrowser("about:accounts");
this.openContentInBrowser("about:accounts?entrypoint=preferences", {
replaceQueryString: true
});
} else {
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
if (win) {
@ -242,7 +244,7 @@ let gSyncPane = {
}
},
openContentInBrowser: function(url) {
openContentInBrowser: function(url, options) {
let win = Services.wm.getMostRecentWindow("navigator:browser");
if (!win) {
// no window to use, so use _openLink to create a new one. We don't
@ -251,21 +253,27 @@ let gSyncPane = {
gSyncUtils._openLink(url);
return;
}
win.switchToTabHavingURI(url, true);
win.switchToTabHavingURI(url, true, options);
// seeing as we are doing this in a tab we close the prefs dialog.
window.close();
},
signUp: function() {
this.openContentInBrowser("about:accounts?action=signup");
this.openContentInBrowser("about:accounts?action=signup&entrypoint=preferences", {
replaceQueryString: true
});
},
signIn: function() {
this.openContentInBrowser("about:accounts?action=signin");
this.openContentInBrowser("about:accounts?action=signin&entrypoint=preferences", {
replaceQueryString: true
});
},
reSignIn: function() {
this.openContentInBrowser("about:accounts?action=reauth");
this.openContentInBrowser("about:accounts?action=reauth&entrypoint=preferences", {
replaceQueryString: true
});
},
manageFirefoxAccount: function() {

View File

@ -31,6 +31,7 @@ MOZ_SERVICES_CRYPTO=1
MOZ_SERVICES_HEALTHREPORT=1
MOZ_SERVICES_METRICS=1
MOZ_SERVICES_SYNC=1
MOZ_SERVICES_CLOUDSYNC=1
MOZ_APP_VERSION=$FIREFOX_VERSION
MOZ_EXTENSIONS_DEFAULT=" gio"
# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh

View File

@ -159,7 +159,7 @@ let AboutHome = {
if (userData) {
window.openPreferences("paneSync");
} else {
window.loadURI("about:accounts");
window.loadURI("about:accounts?entrypoint=abouthome");
}
});
} else {

View File

@ -424,7 +424,7 @@ this.UITour = {
// 'signup' is the only action that makes sense currently, so we don't
// accept arbitrary actions just to be safe...
// We want to replace the current tab.
contentDocument.location.href = "about:accounts?action=signup";
contentDocument.location.href = "about:accounts?action=signup&entrypoint=uitour";
break;
}
}

View File

@ -51,7 +51,7 @@ let tests = [
tabBrowser.removeEventListener("load", onload, true);
ise(tabBrowser.contentDocument.location.href,
"about:accounts?action=signup",
"about:accounts?action=signup&entrypoint=uitour",
"about:accounts should have replaced the tab");
// the iframe in about:accounts will still be loading, so we stop

View File

@ -383,3 +383,6 @@ browser.jar:
skin/classic/browser/devtools/tooltip/arrow-horizontal-light@2x.png (../shared/devtools/tooltip/arrow-horizontal-light@2x.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light.png (../shared/devtools/tooltip/arrow-vertical-light.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light@2x.png (../shared/devtools/tooltip/arrow-vertical-light@2x.png)
#ifdef E10S_TESTING_ONLY
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif

View File

@ -6,4 +6,6 @@
DIRS += ['communicator']
JAR_MANIFESTS += ['jar.mn']
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
JAR_MANIFESTS += ['jar.mn']

View File

@ -542,6 +542,9 @@ browser.jar:
skin/classic/browser/devtools/tooltip/arrow-horizontal-light@2x.png (../shared/devtools/tooltip/arrow-horizontal-light@2x.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light.png (../shared/devtools/tooltip/arrow-vertical-light.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light@2x.png (../shared/devtools/tooltip/arrow-vertical-light@2x.png)
#ifdef E10S_TESTING_ONLY
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif
% override chrome://browser/skin/toolbarbutton-dropmarker.png chrome://browser/skin/lion/toolbarbutton-dropmarker.png os=Darwin osversion>=10.7
% override chrome://browser/skin/tabbrowser/alltabs-box-bkgnd-icon.png chrome://browser/skin/lion/tabbrowser/alltabs-box-bkgnd-icon.png os=Darwin osversion>=10.7

View File

@ -6,4 +6,6 @@
DIRS += ['communicator']
JAR_MANIFESTS += ['jar.mn']
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
JAR_MANIFESTS += ['jar.mn']

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -420,6 +420,9 @@ browser.jar:
skin/classic/browser/devtools/tooltip/arrow-horizontal-light@2x.png (../shared/devtools/tooltip/arrow-horizontal-light@2x.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light.png (../shared/devtools/tooltip/arrow-vertical-light.png)
skin/classic/browser/devtools/tooltip/arrow-vertical-light@2x.png (../shared/devtools/tooltip/arrow-vertical-light@2x.png)
#ifdef E10S_TESTING_ONLY
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif
#ifdef XP_WIN
browser.jar:
@ -841,6 +844,9 @@ browser.jar:
skin/classic/aero/browser/devtools/tooltip/arrow-horizontal-light@2x.png (../shared/devtools/tooltip/arrow-horizontal-light@2x.png)
skin/classic/aero/browser/devtools/tooltip/arrow-vertical-light.png (../shared/devtools/tooltip/arrow-vertical-light.png)
skin/classic/aero/browser/devtools/tooltip/arrow-vertical-light@2x.png (../shared/devtools/tooltip/arrow-vertical-light@2x.png)
#ifdef E10S_TESTING_ONLY
skin/classic/aero/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif
% override chrome://browser/skin/Toolbar.png chrome://browser/skin/Toolbar-aero.png os=WINNT osversion=6
% override chrome://browser/skin/Toolbar.png chrome://browser/skin/Toolbar-aero.png os=WINNT osversion=6.1

View File

@ -6,4 +6,6 @@
DIRS += ['communicator']
JAR_MANIFESTS += ['jar.mn']
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
JAR_MANIFESTS += ['jar.mn']

View File

@ -21,6 +21,7 @@ public class StartPane extends Activity {
@Override
public void onClick(View v) {
Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, "firstrun-sync");
showAccountSetup();
}
});
@ -30,6 +31,7 @@ public class StartPane extends Activity {
@Override
public void onClick(View v) {
Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, "firstrun-browser");
showBrowser();
}
});

View File

@ -11,7 +11,7 @@ AB_rCD = $(if $(filter he, $(AB_CD)),iw,$(if $(filter id, $(AB_CD)),in,$(subst -
# The search strings path is always passed to strings.xml.in; the
# decision to include is made based on the feature flag at the
# inclusion site.
SEARCHSTRINGSPATH = $(srcdir)/../../search/strings/search_strings.dtd
SEARCHSTRINGSPATH = $(abspath $(call MERGE_FILE,search_strings.dtd))
SYNCSTRINGSPATH = $(abspath $(call MERGE_FILE,sync_strings.dtd))
STRINGSPATH = $(abspath $(call MERGE_FILE,android_strings.dtd))

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/transparent"/>
</shape>

View File

@ -95,6 +95,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
XPCOMUtils.defineLazyModuleGetter(this, "NetErrorHelper",
"resource://gre/modules/NetErrorHelper.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PermissionsUtils",
"resource://gre/modules/PermissionsUtils.jsm");
// Lazily-loaded browser scripts:
[
["SelectHelper", "chrome://browser/content/SelectHelper.js"],
@ -2848,6 +2851,9 @@ var LightWeightThemeWebInstaller = {
},
_isAllowed: function (node) {
// Make sure the whitelist has been imported to permissions
PermissionsUtils.importFromPrefs("xpinstall.", "install");
let pm = Services.perms;
let uri = node.ownerDocument.documentURIObject;

View File

@ -23,9 +23,12 @@ function test() {
];
let nevents = 0;
let nflushed = 0;
function handleTabChangeEvent () {
cloudSync.tabs.removeEventListener("change", handleTabChangeEvent);
++ nevents;
info("tab change event " + nevents);
next();
}
function getLocalTabs() {
@ -50,18 +53,16 @@ function test() {
cloudSync.tabs.addEventListener("change", handleTabChangeEvent);
let nflushed = 0;
expected.forEach(function(url) {
let tab = gBrowser.addTab(url);
function flush() {
tab.linkedBrowser.removeEventListener("load", flush);
tab.linkedBrowser.removeEventListener("load", flush, true);
local.TabState.flush(tab.linkedBrowser);
++ nflushed;
info("flushed " + nflushed);
if (nflushed == expected.length) {
getLocalTabs();
}
next();
}
tab.linkedBrowser.addEventListener("load", flush, true);
@ -69,4 +70,10 @@ function test() {
opentabs.push(tab);
});
}
function next() {
if (nevents == 1 && nflushed == expected.length) {
getLocalTabs();
}
}
}

View File

@ -250,3 +250,6 @@ user_pref("loop.throttled", false);
// Ensure UITour won't hit the network
user_pref("browser.uitour.pinnedTabUrl", "http://%(server)s/uitour-dummy/pinnedTab");
user_pref("browser.uitour.url", "http://%(server)s/uitour-dummy/tour");
// Don't prompt about e10s
user_pref("browser.displayedE10SPrompt", 5);

View File

@ -5348,7 +5348,14 @@ function fetch(aURL, aOptions={ loadFromCache: true }) {
channel.loadFlags = aOptions.loadFromCache
? channel.LOAD_FROM_CACHE
: channel.LOAD_BYPASS_CACHE;
channel.asyncOpen(streamListener, null);
try {
channel.asyncOpen(streamListener, null);
} catch(e) {
deferred.reject(new Error("Request failed for '"
+ url
+ "': "
+ e.message));
}
break;
}

View File

@ -0,0 +1,172 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This test verifies that the transport's queue operates correctly when various
* packets are scheduled simultaneously.
*/
let { DebuggerServer } =
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
let { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
function run_test() {
initTestDebuggerServer();
add_task(function() {
yield test_transport(socket_transport);
yield test_transport(local_transport);
DebuggerServer.destroy();
});
run_next_test();
}
/*** Tests ***/
function test_transport(transportFactory) {
let clientDeferred = promise.defer();
let serverDeferred = promise.defer();
// Ensure test files are not present from a failed run
cleanup_files();
let reallyLong = really_long();
writeTestTempFile("bulk-input", reallyLong);
do_check_eq(Object.keys(DebuggerServer._connections).length, 0);
let transport = transportFactory();
// Sending from client to server
function write_data({copyFrom}) {
NetUtil.asyncFetch(getTestTempFile("bulk-input"), function(input, status) {
copyFrom(input).then(() => {
input.close();
});
});
}
// Receiving on server from client
function on_bulk_packet({actor, type, length, copyTo}) {
do_check_eq(actor, "root");
do_check_eq(type, "file-stream");
do_check_eq(length, reallyLong.length);
let outputFile = getTestTempFile("bulk-output", true);
outputFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("666", 8));
let output = FileUtils.openSafeFileOutputStream(outputFile);
copyTo(output).then(() => {
FileUtils.closeSafeFileOutputStream(output);
return verify();
}).then(() => {
// It's now safe to close
transport.hooks.onClosed = () => {
clientDeferred.resolve();
};
transport.close();
});
}
// Client
function send_packets() {
// Specifically, we want to ensure that multiple send()s proceed without
// causing the transport to die.
transport.send({
actor: "root",
type: "explode"
});
transport.startBulkSend({
actor: "root",
type: "file-stream",
length: reallyLong.length
}).then(write_data);
}
transport.hooks = {
onPacket: function(packet) {
if (packet.error) {
transport.hooks.onError(packet);
} else if (packet.applicationType) {
transport.hooks.onServerHello(packet);
} else {
do_throw("Unexpected server reply");
}
},
onServerHello: function(packet) {
// We've received the initial start up packet
do_check_eq(packet.from, "root");
do_check_eq(packet.applicationType, "xpcshell-tests");
// Server
do_check_eq(Object.keys(DebuggerServer._connections).length, 1);
do_print(Object.keys(DebuggerServer._connections));
for (let connId in DebuggerServer._connections) {
DebuggerServer._connections[connId].onBulkPacket = on_bulk_packet;
}
DebuggerServer.on("connectionchange", (event, type) => {
if (type === "closed") {
serverDeferred.resolve();
}
});
send_packets();
},
onError: function(packet) {
// The explode actor doesn't exist
do_check_eq(packet.from, "root");
do_check_eq(packet.error, "noSuchActor");
},
onClosed: function() {
do_throw("Transport closed before we expected");
}
};
transport.ready();
return promise.all([clientDeferred.promise, serverDeferred.promise]);
}
/*** Test Utils ***/
function verify() {
let reallyLong = really_long();
let inputFile = getTestTempFile("bulk-input");
let outputFile = getTestTempFile("bulk-output");
do_check_eq(inputFile.fileSize, reallyLong.length);
do_check_eq(outputFile.fileSize, reallyLong.length);
// Ensure output file contents actually match
let compareDeferred = promise.defer();
NetUtil.asyncFetch(getTestTempFile("bulk-output"), input => {
let outputData = NetUtil.readInputStreamToString(input, reallyLong.length);
// Avoid do_check_eq here so we don't log the contents
do_check_true(outputData === reallyLong);
input.close();
compareDeferred.resolve();
});
return compareDeferred.promise.then(cleanup_files);
}
function cleanup_files() {
let inputFile = getTestTempFile("bulk-input", true);
if (inputFile.exists()) {
inputFile.remove(false);
}
let outputFile = getTestTempFile("bulk-output", true);
if (outputFile.exists()) {
outputFile.remove(false);
}
}

View File

@ -15,4 +15,5 @@ reason = bug 821285
[test_delimited_read.js]
[test_no_bulk.js]
[test_packet.js]
[test_queue.js]
[test_transport_bulk.js]

View File

@ -259,7 +259,7 @@ DebuggerTransport.prototype = {
* may not complete.
*/
onOutputStreamReady: DevToolsUtils.makeInfallible(function(stream) {
if (this._outgoing.length === 0) {
if (!this._outgoingEnabled || this._outgoing.length === 0) {
return;
}

View File

@ -18,8 +18,8 @@ this.BinarySearch = Object.freeze({
*
* @return The index of `target` in `array` or -1 if `target` is not found.
*/
indexOf: function (array, target, comparator) {
let [found, idx] = this.search(array, target, comparator);
indexOf: function (comparator, array, target) {
let [found, idx] = this.search(comparator, array, target);
return found ? idx : -1;
},
@ -32,17 +32,13 @@ this.BinarySearch = Object.freeze({
* @return The index in `array` where `target` may be inserted to keep `array`
* ordered.
*/
insertionIndexOf: function (array, target, comparator) {
return this.search(array, target, comparator)[1];
insertionIndexOf: function (comparator, array, target) {
return this.search(comparator, array, target)[1];
},
/**
* Searches for the given target in the given array.
*
* @param array
* An array whose elements are ordered by `comparator`.
* @param target
* The value to search for.
* @param comparator
* A function that takes two arguments and compares them, returning a
* negative number if the first should be ordered before the second,
@ -50,13 +46,17 @@ this.BinarySearch = Object.freeze({
* number if the second should be ordered before the first. The first
* argument is always `target`, and the second argument is a value
* from the array.
* @param array
* An array whose elements are ordered by `comparator`.
* @param target
* The value to search for.
* @return An array with two elements. If `target` is found, the first
* element is true, and the second element is its index in the array.
* If `target` is not found, the first element is false, and the
* second element is the index where it may be inserted to keep the
* array ordered.
*/
search: function (array, target, comparator) {
search: function (comparator, array, target) {
let low = 0;
let high = array.length - 1;
while (low <= high) {

View File

@ -632,8 +632,7 @@ let PlacesProvider = {
i++;
}
for (let link of outOfOrder) {
i = BinarySearch.insertionIndexOf(links, link,
Links.compareLinks.bind(Links));
i = BinarySearch.insertionIndexOf(Links.compareLinks, links, link);
links.splice(i, 0, link);
}
@ -871,6 +870,8 @@ let Links = {
* @return A negative number if aLink1 is ordered before aLink2, zero if
* aLink1 and aLink2 have the same ordering, or a positive number if
* aLink1 is ordered after aLink2.
*
* @note compareLinks's this object is bound to Links below.
*/
compareLinks: function Links_compareLinks(aLink1, aLink2) {
for (let prop of this._sortProperties) {
@ -1037,7 +1038,7 @@ let Links = {
},
_binsearch: function Links__binsearch(aArray, aLink, aMethod) {
return BinarySearch[aMethod](aArray, aLink, this.compareLinks.bind(this));
return BinarySearch[aMethod](this.compareLinks, aArray, aLink);
},
/**
@ -1066,6 +1067,8 @@ let Links = {
Ci.nsISupportsWeakReference])
};
Links.compareLinks = Links.compareLinks.bind(Links);
/**
* Singleton used to collect telemetry data.
*

View File

@ -67,13 +67,13 @@ function run_test() {
}
function ok(array, target, expectedFound, expectedIdx) {
let [found, idx] = BinarySearch.search(array, target, cmp);
let [found, idx] = BinarySearch.search(cmp, array, target);
do_check_eq(found, expectedFound);
do_check_eq(idx, expectedIdx);
idx = expectedFound ? expectedIdx : -1;
do_check_eq(BinarySearch.indexOf(array, target, cmp), idx);
do_check_eq(BinarySearch.insertionIndexOf(array, target, cmp), expectedIdx);
do_check_eq(BinarySearch.indexOf(cmp, array, target), idx);
do_check_eq(BinarySearch.insertionIndexOf(cmp, array, target), expectedIdx);
}
function cmp(num1, num2) {