diff --git a/addon-sdk/source/lib/sdk/content/sandbox.js b/addon-sdk/source/lib/sdk/content/sandbox.js index d63ca8c54161..1676ebb3e333 100644 --- a/addon-sdk/source/lib/sdk/content/sandbox.js +++ b/addon-sdk/source/lib/sdk/content/sandbox.js @@ -74,7 +74,10 @@ const WorkerSandbox = Class({ * Mainly used by context-menu in order to avoid breaking it. */ emitSync: function emitSync(...args) { - return emitToContent(this, args); + // because the arguments could be also non JSONable values, + // we need to ensure the array instance is created from + // the content's sandbox + return emitToContent(this, new modelFor(this).sandbox.Array(...args)); }, /** diff --git a/addon-sdk/source/lib/sdk/panel/window.js b/addon-sdk/source/lib/sdk/panel/window.js index 47ca21d64f17..22a829e4c00a 100644 --- a/addon-sdk/source/lib/sdk/panel/window.js +++ b/addon-sdk/source/lib/sdk/panel/window.js @@ -35,10 +35,14 @@ function getWindow(anchor) { } // Check if the anchor is in a browser tab in this browser window. - let browser = enumWindow.gBrowser.getBrowserForDocument(anchorDocument); - if (browser) { - window = enumWindow; - break; + try { + let browser = enumWindow.gBrowser.getBrowserForDocument(anchorDocument); + if (browser) { + window = enumWindow; + break; + } + } + catch (e) { } // Look in other subdocuments (sidebar, etc.)? diff --git a/browser/components/customizableui/test/browser.ini b/browser/components/customizableui/test/browser.ini index b7f7a6075e31..00a09c2d5386 100644 --- a/browser/components/customizableui/test/browser.ini +++ b/browser/components/customizableui/test/browser.ini @@ -135,6 +135,7 @@ skip-if = os == "linux" [browser_989751_subviewbutton_class.js] [browser_987177_destroyWidget_xul.js] [browser_987177_xul_wrapper_updating.js] +[browser_987185_syncButton.js] [browser_987492_window_api.js] [browser_987640_charEncoding.js] [browser_992747_toggle_noncustomizable_toolbar.js] diff --git a/browser/components/customizableui/test/browser_987185_syncButton.js b/browser/components/customizableui/test/browser_987185_syncButton.js new file mode 100755 index 000000000000..71fac1e86f62 --- /dev/null +++ b/browser/components/customizableui/test/browser_987185_syncButton.js @@ -0,0 +1,69 @@ +/* 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/. + */ +"use strict"; + +let syncService = {}; +Components.utils.import("resource://services-sync/service.js", syncService); + +let needsSetup; +let originalSync; +let service = syncService.Service; +let syncWasCalled = false; + +add_task(function* testSyncButtonFunctionality() { + info("Check Sync button functionality"); + storeInitialValues(); + mockFunctions(); + + // add the Sync button to the panel + CustomizableUI.addWidgetToArea("sync-button", CustomizableUI.AREA_PANEL); + + // check the button's functionality + yield PanelUI.show(); + info("The panel menu was opened"); + + let syncButton = document.getElementById("sync-button"); + ok(syncButton, "The Sync button was added to the Panel Menu"); + syncButton.click(); + info("The sync button was clicked"); + + yield waitForCondition(() => syncWasCalled); +}); + +add_task(function* asyncCleanup() { + // reset the panel UI to the default state + yield resetCustomization(); + ok(CustomizableUI.inDefaultState, "The panel UI is in default state again."); + + if (isPanelUIOpen()) { + let panelHidePromise = promisePanelHidden(window); + PanelUI.hide(); + yield panelHidePromise; + } + + restoreValues(); +}); + +function mockFunctions() { + // mock needsSetup + gSyncUI._needsSetup = function() false; + + // mock service.errorHandler.syncAndReportErrors() + service.errorHandler.syncAndReportErrors = mocked_syncAndReportErrors; +} + +function mocked_syncAndReportErrors() { + syncWasCalled = true; +} + +function restoreValues() { + gSyncUI._needsSetup = needsSetup; + service.sync = originalSync; +} + +function storeInitialValues() { + needsSetup = gSyncUI._needsSetup; + originalSync = service.sync; +} diff --git a/browser/components/loop/content/js/panel.js b/browser/components/loop/content/js/panel.js index 58793f96d5c7..134747ecbb45 100644 --- a/browser/components/loop/content/js/panel.js +++ b/browser/components/loop/content/js/panel.js @@ -55,7 +55,9 @@ loop.panel = (function(_, mozL10n) { }, this); return ( React.DOM.div({className: "tab-view-container"}, - React.DOM.ul({className: "tab-view"}, tabButtons), + !this.props.buttonsHidden + ? React.DOM.ul({className: "tab-view"}, tabButtons) + : null, tabs ) ); @@ -439,6 +441,7 @@ loop.panel = (function(_, mozL10n) { // Mostly used for UI components showcase and unit tests callUrl: React.PropTypes.string, userProfile: React.PropTypes.object, + showTabButtons: React.PropTypes.bool, }, getInitialState: function() { @@ -475,7 +478,12 @@ loop.panel = (function(_, mozL10n) { }, _onStatusChanged: function() { - this.setState({userProfile: navigator.mozLoop.userProfile}); + var profile = navigator.mozLoop.userProfile; + if (profile != this.state.userProfile) { + // On profile change (login, logout), switch back to the default tab. + this.selectTab("call"); + } + this.setState({userProfile: profile}); this.updateServiceErrors(); }, @@ -508,7 +516,7 @@ loop.panel = (function(_, mozL10n) { React.DOM.div(null, NotificationListView({notifications: this.props.notifications, clearOnDocumentHidden: true}), - TabView({ref: "tabView"}, + TabView({ref: "tabView", buttonsHidden: !this.state.userProfile && !this.props.showTabButtons}, Tab({name: "call"}, React.DOM.div({className: "content-area"}, CallUrlResult({client: this.props.client, diff --git a/browser/components/loop/content/js/panel.jsx b/browser/components/loop/content/js/panel.jsx index 29f666f0544e..def5147c96f9 100644 --- a/browser/components/loop/content/js/panel.jsx +++ b/browser/components/loop/content/js/panel.jsx @@ -55,7 +55,9 @@ loop.panel = (function(_, mozL10n) { }, this); return (
- + {!this.props.buttonsHidden + ? + : null} {tabs}
); @@ -439,6 +441,7 @@ loop.panel = (function(_, mozL10n) { // Mostly used for UI components showcase and unit tests callUrl: React.PropTypes.string, userProfile: React.PropTypes.object, + showTabButtons: React.PropTypes.bool, }, getInitialState: function() { @@ -475,7 +478,12 @@ loop.panel = (function(_, mozL10n) { }, _onStatusChanged: function() { - this.setState({userProfile: navigator.mozLoop.userProfile}); + var profile = navigator.mozLoop.userProfile; + if (profile != this.state.userProfile) { + // On profile change (login, logout), switch back to the default tab. + this.selectTab("call"); + } + this.setState({userProfile: profile}); this.updateServiceErrors(); }, @@ -508,7 +516,7 @@ loop.panel = (function(_, mozL10n) {
- +
+ + @@ -198,6 +213,41 @@ if (aTranslation.state) this.state = aTranslation.state; + + const kWelcomePref = "browser.translation.ui.welcomeMessageShown"; + if (Services.prefs.prefHasUserValue(kWelcomePref)) + return; + + this.addEventListener("transitionend", function onShown() { + this.removeEventListener("transitionend", onShown); + + // These strings are hardcoded because they need to reach beta + // without riding the trains. + let localizedStrings = { + en: ["Hey look! It's something new!", + "Now the Web is even more accessible with our new in-page translation feature. Click the translate button to try it!", + "Learn more.", + "Thanks"] + }; + + let locale = Cc["@mozilla.org/chrome/chrome-registry;1"] + .getService(Ci.nsIXULChromeRegistry) + .getSelectedLocale("browser"); + if (!(locale in localizedStrings)) + locale = "en"; + let strings = localizedStrings[locale]; + + this._getAnonElt("welcomeHeadline").setAttribute("value", strings[0]); + this._getAnonElt("welcomeBody").textContent = strings[1]; + this._getAnonElt("learnMore").setAttribute("value", strings[2]); + this._getAnonElt("thanksButton").setAttribute("label", strings[3]); + + let panel = this._getAnonElt("welcomePanel"); + panel.openPopup(this._getAnonElt("messageImage"), + "bottomcenter topleft"); + + Services.prefs.setBoolPref(kWelcomePref, true); + }); ]]> diff --git a/browser/locales/en-US/chrome/browser/devtools/webide.properties b/browser/locales/en-US/chrome/browser/devtools/webide.properties index bc3b52e0fdee..23f15b93be3a 100644 --- a/browser/locales/en-US/chrome/browser/devtools/webide.properties +++ b/browser/locales/en-US/chrome/browser/devtools/webide.properties @@ -19,7 +19,7 @@ importPackagedApp_title=Select Directory importHostedApp_title=Open Hosted App importHostedApp_header=Enter Manifest URL -notification_showTroubleShooting_label=troubleshooting +notification_showTroubleShooting_label=Troubleshooting notification_showTroubleShooting_accesskey=t # LOCALIZATION NOTE (project_tab_loading): This is shown as a temporary tab diff --git a/browser/themes/shared/translation/infobar.inc.css b/browser/themes/shared/translation/infobar.inc.css index 1db332f4de07..7c5f3afbf72b 100644 --- a/browser/themes/shared/translation/infobar.inc.css +++ b/browser/themes/shared/translation/infobar.inc.css @@ -64,3 +64,28 @@ notification[value="translation"] menulist > .menulist-dropmarker { .translation-attribution > image { width: 70px; } + +.translation-welcome-panel { + width: 305px; +} + +.translation-welcome-logo { + height: 32px; + width: 32px; + list-style-image: url(chrome://browser/skin/translation-16@2x.png); + -moz-image-region: rect(0, 64px, 32px, 32px); +} + +.translation-welcome-content { + -moz-margin-start: 16px; +} + +.translation-welcome-headline { + font-size: larger; + font-weight: bold; +} + +.translation-welcome-body { + padding: 1em 0; + margin: 0 0; +} diff --git a/content/media/test/mochitest.ini b/content/media/test/mochitest.ini index f2955bb28fec..fc32db73419a 100644 --- a/content/media/test/mochitest.ini +++ b/content/media/test/mochitest.ini @@ -22,7 +22,7 @@ # do ok(true, "Type not supported") and stop the test. [DEFAULT] -skip-if = buildapp == 'mulet' || contentSandbox != 'off' # contentSandbox(Bug 1042735) +skip-if = buildapp == 'mulet' support-files = 320x240.ogv 320x240.ogv^headers^ diff --git a/content/media/webaudio/test/mochitest.ini b/content/media/webaudio/test/mochitest.ini index fb71d606a27c..7e7aaf1a1e0a 100644 --- a/content/media/webaudio/test/mochitest.ini +++ b/content/media/webaudio/test/mochitest.ini @@ -1,5 +1,5 @@ [DEFAULT] -skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && (toolkit != 'gonk' || debug)) || contentSandbox != 'off' #b2g-debug,b2g-desktop(bug 916135); contentSandbox(Bug 1042735) +skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && (toolkit != 'gonk' || debug)) #b2g-debug,b2g-desktop(bug 916135) support-files = audio-expected.wav audio-mono-expected-2.wav diff --git a/dom/media/tests/mochitest/mochitest.ini b/dom/media/tests/mochitest/mochitest.ini index 2bb64c79d1dc..056897f2b31e 100644 --- a/dom/media/tests/mochitest/mochitest.ini +++ b/dom/media/tests/mochitest/mochitest.ini @@ -1,5 +1,4 @@ [DEFAULT] -skip-if = contentSandbox != 'off' # contentSandbox(Bug 1042735) support-files = head.js constraints.js diff --git a/mobile/android/base/AndroidManifest.xml.in b/mobile/android/base/AndroidManifest.xml.in index 15abdc4a8cba..b8c34df1a5aa 100644 --- a/mobile/android/base/AndroidManifest.xml.in +++ b/mobile/android/base/AndroidManifest.xml.in @@ -23,10 +23,8 @@ #include ../search/manifests/SearchAndroidManifest_permissions.xml.in #endif -#ifndef RELEASE_BUILD -#endif diff --git a/mobile/android/base/home/TwoLinePageRow.java b/mobile/android/base/home/TwoLinePageRow.java index 7434e5c75cbd..0b989c43b8f2 100644 --- a/mobile/android/base/home/TwoLinePageRow.java +++ b/mobile/android/base/home/TwoLinePageRow.java @@ -7,7 +7,9 @@ package org.mozilla.gecko.home; import java.lang.ref.WeakReference; +import org.mozilla.gecko.AboutPages; import org.mozilla.gecko.R; +import org.mozilla.gecko.ReaderModeUtils; import org.mozilla.gecko.Tab; import org.mozilla.gecko.Tabs; import org.mozilla.gecko.db.BrowserContract.Combined; @@ -248,7 +250,12 @@ public class TwoLinePageRow extends LinearLayout // Blank the Favicon, so we don't show the wrong Favicon if we scroll and miss DB. mFavicon.clearImage(); Favicons.cancelFaviconLoad(mLoadFaviconJobId); - mLoadFaviconJobId = Favicons.getSizedFaviconForPageFromLocal(getContext(), url, mFaviconListener); + + // Displayed RecentTabsPanel urls may refer to pages openned in readermode, so we + // remove the about:reader prefix to ensure the Favicon loads properly. + final String pageURL = AboutPages.isAboutReader(url) ? + ReaderModeUtils.getUrlFromAboutReader(url) : url; + mLoadFaviconJobId = Favicons.getSizedFaviconForPageFromLocal(getContext(), pageURL, mFaviconListener); updateDisplayedUrl(url); } diff --git a/mobile/android/base/locales/Makefile.in b/mobile/android/base/locales/Makefile.in index 11466b4c955c..7851f5ad89e0 100644 --- a/mobile/android/base/locales/Makefile.in +++ b/mobile/android/base/locales/Makefile.in @@ -115,6 +115,7 @@ $(eval $(call generated_file_template,suggestedsites,suggestedsites.json)) $(suggestedsites-dstdir-raw)/suggestedsites.json: FORCE $(call py_action,generate_suggestedsites, \ + --verbose \ --android-package-name=$(ANDROID_PACKAGE_NAME) \ --resources=$(srcdir)/../resources \ $(if $(filter en-US,$(AB_CD)),,--srcdir=$(l10n-srcdir)) \ @@ -125,6 +126,7 @@ $(eval $(call generated_file_template,browsersearch,browsersearch.json)) $(browsersearch-dstdir-raw)/browsersearch.json: FORCE $(call py_action,generate_browsersearch, \ + --verbose \ $(if $(filter en-US,$(AB_CD)),,--srcdir=$(l10n-srcdir)) \ --srcdir=$(topsrcdir)/mobile/locales/en-US/chrome \ $@) diff --git a/mobile/android/chrome/content/aboutAddons.js b/mobile/android/chrome/content/aboutAddons.js index ba56c72094c9..9a3c66165bae 100644 --- a/mobile/android/chrome/content/aboutAddons.js +++ b/mobile/android/chrome/content/aboutAddons.js @@ -527,6 +527,21 @@ var Addons = { element.setAttribute("opType", "needs-restart"); }, + onInstalled: function(aAddon) { + let list = document.getElementById("addons-list"); + let element = this._getElementForAddon(aAddon.id); + if (!element) { + element = this._createItemForAddon(aAddon); + list.insertBefore(element, list.firstElementChild); + } + }, + + onUninstalled: function(aAddon) { + let list = document.getElementById("addons-list"); + let element = this._getElementForAddon(aAddon.id); + list.removeChild(element); + }, + onInstallFailed: function(aInstall) { }, diff --git a/mobile/android/chrome/content/aboutApps.xhtml b/mobile/android/chrome/content/aboutApps.xhtml index 9e457ee1347d..3dea232b88d5 100644 --- a/mobile/android/chrome/content/aboutApps.xhtml +++ b/mobile/android/chrome/content/aboutApps.xhtml @@ -35,7 +35,6 @@
&aboutApps.header;
-