diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index f8989ed38ab..56619a7f424 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1327,8 +1327,8 @@ pref("services.sync.prefs.sync.xpinstall.whitelist.required", true); // Developer edition preferences #ifdef MOZ_DEV_EDITION -pref("lightweightThemes.selectedThemeID", "firefox-devedition@mozilla.org"); -pref("browser.devedition.theme.enabled", true); +sticky_pref("lightweightThemes.selectedThemeID", "firefox-devedition@mozilla.org"); +sticky_pref("browser.devedition.theme.enabled", true); #endif // Developer edition promo preferences @@ -1443,6 +1443,15 @@ pref("devtools.performance.ui.show-idle-blocks", true); pref("devtools.performance.ui.enable-memory", false); pref("devtools.performance.ui.enable-framerate", true); pref("devtools.performance.ui.show-jit-optimizations", false); +// If in aurora (40.0, will revert for 40.1), set default +// to retro mode. +// TODO bug 1160313 +#if MOZ_UPDATE_CHANNEL == aurora + pref("devtools.performance.ui.retro-mode", true); +#else + pref("devtools.performance.ui.retro-mode", false); +#endif + // The default cache UI setting pref("devtools.cache.disabled", false); @@ -1507,9 +1516,9 @@ pref("devtools.webaudioeditor.inspectorWidth", 300); // Default theme ("dark" or "light") #ifdef MOZ_DEV_EDITION -pref("devtools.theme", "dark"); +sticky_pref("devtools.theme", "dark"); #else -pref("devtools.theme", "light"); +sticky_pref("devtools.theme", "light"); #endif // Display the introductory text @@ -1646,10 +1655,10 @@ pref("browser.newtabpage.rows", 3); pref("browser.newtabpage.columns", 5); // directory tiles download URL -pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v2/links/fetch/%LOCALE%"); +pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v3/links/fetch/%LOCALE%/%CHANNEL%"); // endpoint to send newtab click and view pings -pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v2/links/"); +pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v3/links/"); // Enable the DOM fullscreen API. pref("full-screen-api.enabled", true); @@ -1863,7 +1872,7 @@ pref("browser.polaris.enabled", false); pref("privacy.trackingprotection.ui.enabled", false); #endif -#ifdef NIGHTLY_BUILD +#ifdef E10S_TESTING_ONLY // At the moment, autostart.2 is used, while autostart.1 is unused. // We leave it here set to false to reset users' defaults and allow // us to change everybody to true in the future, when desired. @@ -1871,7 +1880,7 @@ pref("browser.tabs.remote.autostart.1", false); pref("browser.tabs.remote.autostart.2", true); #endif -#ifdef NIGHTLY_BUILD +#ifdef E10S_TESTING_ONLY // Enable e10s add-on interposition by default. pref("extensions.interposition.enabled", true); pref("extensions.interposition.prefetching", true); @@ -1900,6 +1909,7 @@ pref("browser.readinglist.sidebarEverOpened", false); pref("readinglist.scheduler.enabled", false); pref("readinglist.server", "https://readinglist.services.mozilla.com/v1"); +pref("browser.reader.detectedFirstArticle", false); // Don't limit how many nodes we care about on desktop: pref("reader.parse-node-limit", 0); diff --git a/browser/base/content/newtab/sites.js b/browser/base/content/newtab/sites.js index eb56fddcb34..87e0bc47f1f 100644 --- a/browser/base/content/newtab/sites.js +++ b/browser/base/content/newtab/sites.js @@ -133,7 +133,7 @@ Site.prototype = { if (this.link.targetedSite) { this.node.setAttribute("suggested", true); - let targetedSite = ` ${this.link.targetedSite} `; + let targetedSite = ` ${this.link.targetedName} `; this._querySelector(".newtab-suggested").innerHTML = `
${newTabString("suggested.button", [targetedSite])}
`; } diff --git a/browser/base/content/tab-content.js b/browser/base/content/tab-content.js index ed94a7dd7e7..db943faca90 100644 --- a/browser/base/content/tab-content.js +++ b/browser/base/content/tab-content.js @@ -555,7 +555,9 @@ addEventListener("unload", () => { }, false); addMessageListener("Browser:AppTab", function(message) { - docShell.isAppTab = message.data.isAppTab; + if (docShell) { + docShell.isAppTab = message.data.isAppTab; + } }); let WebBrowserChrome = { diff --git a/browser/base/content/test/chat/browser_chatwindow.js b/browser/base/content/test/chat/browser_chatwindow.js index b0665050dc5..2dcc897f982 100644 --- a/browser/base/content/test/chat/browser_chatwindow.js +++ b/browser/base/content/test/chat/browser_chatwindow.js @@ -6,30 +6,6 @@ Components.utils.import("resource://gre/modules/Promise.jsm", this); let chatbar = document.getElementById("pinnedchats"); -function waitForCondition(condition, errorMsg) { - let deferred = Promise.defer(); - var tries = 0; - var interval = setInterval(function() { - if (tries >= 30) { - ok(false, errorMsg); - moveOn(); - } - var conditionPassed; - try { - conditionPassed = condition(); - } catch (e) { - ok(false, e + "\n" + e.stack); - conditionPassed = false; - } - if (conditionPassed) { - moveOn(); - } - tries++; - }, 100); - var moveOn = function() { clearInterval(interval); deferred.resolve(); }; - return deferred.promise; -} - add_chat_task(function* testOpenCloseChat() { let chatbox = yield promiseOpenChat("http://example.com"); Assert.strictEqual(chatbox, chatbar.selectedChat); @@ -115,7 +91,7 @@ add_chat_task(function* testSecondTopLevelWindow() { secondWindow.close(); }); -// Test that chats are created in the correct window. +// Test that findChromeWindowForChats() returns the expected window. add_chat_task(function* testChatWindowChooser() { let chat = yield promiseOpenChat("http://example.com"); Assert.equal(numChatsInWindow(window), 1, "first window has the chat"); @@ -124,42 +100,34 @@ add_chat_task(function* testChatWindowChooser() { let secondWindow = OpenBrowserWindow(); yield promiseOneEvent(secondWindow, "load"); Assert.equal(secondWindow, Chat.findChromeWindowForChats(null), "Second window is the preferred chat window"); - Assert.equal(numChatsInWindow(secondWindow), 0, "second window starts with no chats"); - yield promiseOpenChat("http://example.com#2"); - Assert.equal(numChatsInWindow(secondWindow), 1, "second window now has chats"); - Assert.equal(numChatsInWindow(window), 1, "first window still has 1 chat"); - chat.close(); - // a bit heavy handed, but handy fixing bug 1090633 - yield waitForCondition(function () !chat.parentNode, "chat has been detached"); - Assert.equal(numChatsInWindow(window), 0, "first window now has no chats"); - // now open another chat - it should still open in the second. - yield promiseOpenChat("http://example.com#3"); - Assert.equal(numChatsInWindow(window), 0, "first window still has no chats"); - Assert.equal(numChatsInWindow(secondWindow), 2, "second window has both chats"); + // focus the first window, and check it will be selected for future chats. + // Bug 1090633 - there are lots of issues around focus, especially when the + // browser itself doesn't have focus. We can end up with + // Services.wm.getMostRecentWindow("navigator:browser") returning a different + // window than, say, Services.focus.activeWindow. But the focus manager isn't + // the point of this test. + // So we simply keep focusing the first window until it is reported as the + // most recent. + do { + dump("trying to force window to become the most recent.\n"); + secondWindow.focus(); + window.focus(); + yield promiseWaitForFocus(); + } while (Services.wm.getMostRecentWindow("navigator:browser") != window) - // focus the first window, and open yet another chat - it - // should open in the first window. - window.focus(); - yield promiseWaitForFocus(); - chat = yield promiseOpenChat("http://example.com#4"); - Assert.equal(numChatsInWindow(window), 1, "first window got new chat"); - chat.close(); - Assert.equal(numChatsInWindow(window), 0, "first window has no chats"); + Assert.equal(window, Chat.findChromeWindowForChats(null), "First window now the preferred chat window"); let privateWindow = OpenBrowserWindow({private: true}); yield promiseOneEvent(privateWindow, "load") - // open a last chat - the focused window can't accept - // chats (it's a private window), so the chat should open - // in the window that was selected before. This is known - // to be broken on Linux. - chat = yield promiseOpenChat("http://example.com#5"); - let os = Services.appinfo.OS; - const BROKEN_WM_Z_ORDER = os != "WINNT" && os != "Darwin"; - let fn = BROKEN_WM_Z_ORDER ? todo : ok; - fn(numChatsInWindow(window) == 1, "first window got the chat"); - chat.close(); + // The focused window can't accept chats (it's a private window), so the + // chat should open in the window that was selected before. This will be + // either window or secondWindow (linux may choose a different one) but the + // point is that the window is *not* the private one. + Assert.ok(Chat.findChromeWindowForChats(null) == window || + Chat.findChromeWindowForChats(null) == secondWindow, + "Private window isn't selected for new chats."); privateWindow.close(); secondWindow.close(); }); diff --git a/browser/base/content/test/chat/browser_focus.js b/browser/base/content/test/chat/browser_focus.js index 06118a7c8b6..58872d9a799 100644 --- a/browser/base/content/test/chat/browser_focus.js +++ b/browser/base/content/test/chat/browser_focus.js @@ -10,12 +10,16 @@ const CHAT_URL = "https://example.com/browser/browser/base/content/test/chat/cha // Is the currently opened tab focused? function isTabFocused() { let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab); - return Services.focus.focusedWindow == tabb.contentWindow; + // focus sucks in tests - our window may have lost focus. + let elt = Services.focus.getFocusedElementForWindow(window, false, {}); + return elt == tabb; } // Is the specified chat focused? function isChatFocused(chat) { - return chat.chatbar._isChatFocused(chat); + // focus sucks in tests - our window may have lost focus. + let elt = Services.focus.getFocusedElementForWindow(window, false, {}); + return elt == chat.content; } let chatbar = document.getElementById("pinnedchats"); diff --git a/browser/base/content/test/general/browser_readerMode.js b/browser/base/content/test/general/browser_readerMode.js index c8d1cc4b4ef..fb5d3bc89a7 100644 --- a/browser/base/content/test/general/browser_readerMode.js +++ b/browser/base/content/test/general/browser_readerMode.js @@ -32,19 +32,29 @@ add_task(function* test_reader_button() { TEST_PREFS.forEach(([name, value]) => { Services.prefs.setBoolPref(name, value); }); + Services.prefs.setBoolPref("browser.reader.detectedFirstArticle", false); let tab = gBrowser.selectedTab = gBrowser.addTab(); is_element_hidden(readerButton, "Reader mode button is not present on a new tab"); + ok(!UITour.isInfoOnTarget(window, "readerMode-urlBar"), + "Info panel shouldn't appear without the reader mode button"); + ok(!Services.prefs.getBoolPref("browser.reader.detectedFirstArticle"), + "Shouldn't have detected the first article"); // Point tab to a test page that is reader-able. let url = TEST_PATH + "readerModeArticle.html"; yield promiseTabLoadEvent(tab, url); yield promiseWaitForCondition(() => !readerButton.hidden); is_element_visible(readerButton, "Reader mode button is present on a reader-able page"); + ok(UITour.isInfoOnTarget(window, "readerMode-urlBar"), + "Info panel should be anchored at the reader mode button"); + ok(Services.prefs.getBoolPref("browser.reader.detectedFirstArticle"), + "Should have detected the first article"); // Switch page into reader mode. readerButton.click(); yield promiseTabLoadEvent(tab); + ok(!UITour.isInfoOnTarget(window, "readerMode-urlBar"), "Info panel should have closed"); let readerUrl = gBrowser.selectedBrowser.currentURI.spec; ok(readerUrl.startsWith("about:reader"), "about:reader loaded after clicking reader mode button"); diff --git a/browser/base/content/test/newtab/browser_newtab_block.js b/browser/base/content/test/newtab/browser_newtab_block.js index 9509786feec..47c645baac3 100644 --- a/browser/base/content/test/newtab/browser_newtab_block.js +++ b/browser/base/content/test/newtab/browser_newtab_block.js @@ -18,6 +18,8 @@ gDirectorySource = "data:application/json," + JSON.stringify({ }); function runTests() { + let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName; + DirectoryLinksProvider.getFrecentSitesName = () => ""; let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite; NewTabUtils.isTopPlacesSite = (site) => false; @@ -84,4 +86,5 @@ function runTests() { yield blockCell(1); yield addNewTabPageTab(); checkGrid("1,2,3,4,5,6,7,8,9"); + DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName; } diff --git a/browser/base/content/test/newtab/browser_newtab_enhanced.js b/browser/base/content/test/newtab/browser_newtab_enhanced.js index a2ff6cd551d..0750017923a 100644 --- a/browser/base/content/test/newtab/browser_newtab_enhanced.js +++ b/browser/base/content/test/newtab/browser_newtab_enhanced.js @@ -26,8 +26,11 @@ gDirectorySource = "data:application/json," + JSON.stringify({ }); function runTests() { + let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName; + DirectoryLinksProvider.getFrecentSitesName = () => ""; let origEnhanced = NewTabUtils.allPages.enhanced; registerCleanupFunction(() => { + DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName; Services.prefs.clearUserPref(PRELOAD_PREF); NewTabUtils.allPages.enhanced = origEnhanced; }); diff --git a/browser/components/loop/.eslintignore b/browser/components/loop/.eslintignore index 33359955167..8ac40f1ae3a 100644 --- a/browser/components/loop/.eslintignore +++ b/browser/components/loop/.eslintignore @@ -1,15 +1,14 @@ -# We still need to fix warnings in this file. -MozLoopWorker.js -# This file currently uses es7 features -MozLoopAPI.jsm +# This file currently uses a non-standard (and not on a standards track) +# if statement within catch. +modules/MozLoopWorker.js +# This file currently uses es7 features eslint issue: +# https://github.com/eslint/espree/issues/125 +modules/MozLoopAPI.jsm # Libs we don't need to check content/libs content/shared/libs standalone/content/libs standalone/node_modules -# We should look at turning these on when we fix the warnings -test/xpcshell -test/mochitest # Libs we don't need to check test/shared/vendor diff --git a/browser/components/loop/.eslintrc b/browser/components/loop/.eslintrc index 607babeaa46..783d58657e7 100644 --- a/browser/components/loop/.eslintrc +++ b/browser/components/loop/.eslintrc @@ -1,3 +1,5 @@ +// Note: there are extra allowances for files used solely in Firefox desktop, +// see content/js/.eslintrc and modules/.eslintrc { "plugins": [ "react" @@ -5,18 +7,6 @@ "ecmaFeatures": { "forOf": true, "jsx": true, - // These are on for this directory for .jsm and content/js files. - // If adding more items here, consider turning them off for the following - // files if they aren't supported by all browsers. - // content/shared/.eslintrc - // content/standalone/.eslintrc - "blockBindings": true, - "arrowFunctions": true, - "destructuring": true, - "generators": true, - "spread": true, - "restParams": true, - "objectLiteralShorthandMethods": true }, "env": { "browser": true, @@ -43,49 +33,50 @@ // problems they find, one at a time. // Eslint built-in rules are documented at - "camelcase": 0, - "comma-dangle": 0, - "comma-spacing": 0, - "consistent-return": 0, - "curly": 0, - "dot-notation": 0, - "eol-last": 0, - "eqeqeq": 0, - "global-strict": 0, - "key-spacing": 0, - "new-cap": 0, - "no-catch-shadow": 0, - "no-console": 0, - "no-empty": 0, - "no-extra-bind": 0, - "no-extra-boolean-cast": 0, - "no-extra-semi": 0, - "no-multi-spaces": 0, - "no-new": 0, - "no-redeclare": 0, - "no-return-assign": 0, - "no-shadow": 0, - "no-spaced-func": 0, - "no-trailing-spaces": 0, - "no-undef": 0, - "no-underscore-dangle": 0, - "no-unused-expressions": 0, - "no-unused-vars": 0, - "no-use-before-define": 0, - "no-wrap-func": 0, - "quotes": 0, - "semi": 0, - "semi-spacing": 0, - "space-infix-ops": 0, - "space-return-throw-case": 0, - "strict": 0, - "yoda": 0, + "camelcase": 0, // TODO: Remove (use default) + "comma-dangle": 0, // TODO: Remove (use default) + "comma-spacing": 0, // TODO: Remove (use default) + "consistent-return": 0, // TODO: Remove (use default) + "curly": 0, // TODO: Remove (use default) + "dot-notation": 0, // TODO: Remove (use default) + "eol-last": 0, // TODO: Remove (use default) + "eqeqeq": 0, // TBD. Might need to be separate for content & chrome + "global-strict": 0, // Leave as zero (this will be unsupported in eslint 1.0.0) + "key-spacing": 0, // TODO: Remove (use default) + "new-cap": 0, // TODO: Remove (use default) + "no-catch-shadow": 0, // TODO: Remove (use default) + "no-console": 0, // Leave as 0. We use console logging in content code. + "no-empty": 0, // TODO: Remove (use default) + "no-extra-bind": 0, // Leave as 0 + "no-extra-boolean-cast": 0, // TODO: Remove (use default) + "no-extra-semi": 0, // TODO: Remove (use default) + "no-multi-spaces": 0, // TBD. + "no-new": 0, // TODO: Remove (use default) + "no-redeclare": 0, // TODO: Remove (use default) + "no-return-assign": 0, // TODO: Remove (use default) + "no-shadow": 0, // TODO: Remove (use default) + "no-spaced-func": 0, // TODO: Remove (use default) + "no-trailing-spaces": 0, // TODO: Remove (use default) + "no-undef": 0, // TODO: Remove (use default) + "no-underscore-dangle": 0, // Leave as 0. Commonly used for private variables. + "no-unused-expressions": 0, // TODO: Remove (use default) + "no-unused-vars": 0, // TODO: Remove (use default) + "no-use-before-define": 0, // TODO: Remove (use default) + "no-wrap-func": 0, // TODO: Remove (use default) + "quotes": 0, // [2, "double", "avoid-escape"], + "semi": 0, // TODO: Remove (use default) + "semi-spacing": 0, // TODO: Remove (use default) + "space-infix-ops": 0, // TODO: Remove (use default) + "space-return-throw-case": 0, // TODO: Remove (use default) + "strict": 0, // [2, "function"], + "yoda": 0, // [2, "never"], // eslint-plugin-react rules. These are documented at // "react/jsx-quotes": [2, "double", "avoid-escape"], "react/jsx-no-undef": 2, // Need to fix instances where this is failing. "react/jsx-sort-props": 0, + "react/jsx-sort-prop-types": 0, "react/jsx-uses-vars": 2, // Need to fix the couple of instances which don't // currently pass this rule. @@ -101,6 +92,7 @@ "react/react-in-jsx-scope": 0, // These ones we don't want to ever enable "react/display-name": 0, + "react/jsx-boolean-value": 0, "react/no-multi-comp": 0 } } diff --git a/browser/components/loop/README.txt b/browser/components/loop/README.txt index 3bb638bad1a..45e14894087 100644 --- a/browser/components/loop/README.txt +++ b/browser/components/loop/README.txt @@ -54,7 +54,7 @@ If you install eslint and the react plugin globally: You can also run it by hand in the browser/components/loop directory: - eslint -ext .js -ext .jsx --ext .jsm . + eslint --ext .js --ext .jsx --ext .jsm . Front-End Unit Tests ==================== diff --git a/browser/components/loop/content/js/.eslintrc b/browser/components/loop/content/js/.eslintrc new file mode 100644 index 00000000000..bcce1c501c1 --- /dev/null +++ b/browser/components/loop/content/js/.eslintrc @@ -0,0 +1,15 @@ +{ + "ecmaFeatures": { + // These are on for this directory for .jsm and content/js files. + "blockBindings": true, + "arrowFunctions": true, + "destructuring": true, + "generators": true, + "spread": true, + "restParams": true, + "objectLiteralShorthandMethods": true + }, + "rules": { + "generator-star-spacing": [2, "after"] + } +} diff --git a/browser/components/loop/content/js/contacts.js b/browser/components/loop/content/js/contacts.js index 6fecc1808a8..bc6fcbb652f 100644 --- a/browser/components/loop/content/js/contacts.js +++ b/browser/components/loop/content/js/contacts.js @@ -222,7 +222,7 @@ loop.contacts = (function(_, mozL10n) { "disabled": !this.props.canEdit }), onClick: this.onItemClick, "data-action": "remove"}, React.createElement("i", {className: "icon icon-remove"}), - mozL10n.get("remove_contact_menu_button") + mozL10n.get("remove_contact_menu_button2") ) ) ); @@ -587,7 +587,7 @@ loop.contacts = (function(_, mozL10n) { React.createElement(ButtonGroup, null, React.createElement(Button, {caption: this.state.importBusy ? mozL10n.get("importing_contacts_progress_button") - : mozL10n.get("import_contacts_button"), + : mozL10n.get("import_contacts_button2"), disabled: this.state.importBusy, onClick: this.handleImportButtonClick}, React.createElement("div", {className: cx({"contact-import-spinner": true, diff --git a/browser/components/loop/content/js/contacts.jsx b/browser/components/loop/content/js/contacts.jsx index b78e60e6a99..ab53c1145ba 100644 --- a/browser/components/loop/content/js/contacts.jsx +++ b/browser/components/loop/content/js/contacts.jsx @@ -222,7 +222,7 @@ loop.contacts = (function(_, mozL10n) { "disabled": !this.props.canEdit })} onClick={this.onItemClick} data-action="remove"> - {mozL10n.get("remove_contact_menu_button")} + {mozL10n.get("remove_contact_menu_button2")} ); @@ -587,7 +587,7 @@ loop.contacts = (function(_, mozL10n) {