Merge m-c to inbound a=merge CLOSED TREE

This commit is contained in:
Wes Kocher 2014-10-06 20:59:17 -07:00
commit 159b48d0cf
28 changed files with 348 additions and 32 deletions

View File

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

View File

@ -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.)?

View File

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

View File

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

View File

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

View File

@ -55,7 +55,9 @@ loop.panel = (function(_, mozL10n) {
}, this);
return (
<div className="tab-view-container">
<ul className="tab-view">{tabButtons}</ul>
{!this.props.buttonsHidden
? <ul className="tab-view">{tabButtons}</ul>
: null}
{tabs}
</div>
);
@ -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) {
<div>
<NotificationListView notifications={this.props.notifications}
clearOnDocumentHidden={true} />
<TabView ref="tabView">
<TabView ref="tabView" buttonsHidden={!this.state.userProfile && !this.props.showTabButtons}>
<Tab name="call">
<div className="content-area">
<CallUrlResult client={this.props.client}

View File

@ -140,7 +140,8 @@ describe("loop.panel", function() {
view = TestUtils.renderIntoDocument(loop.panel.PanelView({
notifications: notifications,
client: fakeClient
client: fakeClient,
showTabButtons: true,
}));
[callTab, contactsTab] =

View File

@ -32,8 +32,8 @@ this.Translation = {
serviceUnavailable: false,
supportedSourceLanguages: ["de", "en", "es", "fr", "ja", "ko", "pt", "ru", "zh"],
supportedTargetLanguages: ["de", "en", "es", "fr", "ja", "ko", "pl", "pt", "ru", "tr", "vi", "zh"],
supportedSourceLanguages: ["bg", "cs", "de", "en", "es", "fr", "ja", "ko", "nl", "no", "pl", "pt", "ru", "tr", "vi", "zh"],
supportedTargetLanguages: ["bg", "cs", "de", "en", "es", "fr", "ja", "ko", "nl", "no", "pl", "pt", "ru", "tr", "vi", "zh"],
_defaultTargetLanguage: "",
get defaultTargetLanguage() {

View File

@ -23,6 +23,21 @@
<xul:hbox anonid="details" align="center" flex="1">
<xul:image class="translate-infobar-element messageImage"
anonid="messageImage"/>
<xul:panel anonid="welcomePanel" class="translation-welcome-panel"
type="arrow" align="start">
<xul:image class="translation-welcome-logo"/>
<xul:vbox flex="1" class="translation-welcome-content">
<xul:description class="translation-welcome-headline"
anonid="welcomeHeadline"/>
<xul:description class="translation-welcome-body" anonid="welcomeBody"/>
<xul:hbox align="center">
<xul:label anonid="learnMore" class="plain text-link"/>
<xul:spacer flex="1"/>
<xul:button class="translate-infobar-element" anonid="thanksButton"
onclick="this.parentNode.parentNode.parentNode.hidePopup();"/>
</xul:hbox>
</xul:vbox>
</xul:panel>
<xul:deck anonid="translationStates" selectedIndex="0">
<!-- offer to translate -->
@ -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);
});
]]>
</body>
</method>

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = contentSandbox != 'off' # contentSandbox(Bug 1042735)
support-files =
head.js
constraints.js

View File

@ -23,10 +23,8 @@
#include ../search/manifests/SearchAndroidManifest_permissions.xml.in
#endif
#ifndef RELEASE_BUILD
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
#endif
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>

View File

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

View File

@ -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 \
$@)

View File

@ -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) {
},

View File

@ -35,7 +35,6 @@
<div class="header">
<div>&aboutApps.header;</div>
<div id="header-button" role="button" aria-label="&aboutApps.browseMarketplace;" pref="app.marketplaceURL"/>
</div>
<div id="main-container" class="hidden">

View File

@ -829,6 +829,13 @@ var BrowserApp = {
Services.prefs.setIntPref("plugin.default.state", Ci.nsIPluginTag.STATE_ENABLED);
Services.prefs.clearUserPref("plugins.click_to_play");
}
// Set the search activity default pref on app upgrade if it has not been set already.
if (this._startupStatus === "upgrade" &&
!Services.prefs.prefHasUserValue("searchActivity.default.migrated")) {
Services.prefs.setBoolPref("searchActivity.default.migrated", true);
SearchEngines.migrateSearchActivityDefaultPref();
}
},
shutdown: function shutdown() {
@ -6909,6 +6916,10 @@ var SearchEngines = {
}
},
migrateSearchActivityDefaultPref: function migrateSearchActivityDefaultPref() {
Services.search.init(() => this._setSearchActivityDefaultPref(Services.search.defaultEngine));
},
// Updates the search activity pref when the default engine changes.
_setSearchActivityDefaultPref: function _setSearchActivityDefaultPref(engine) {
// Helper function copied from nsSearchService.js. This is the logic that is used

View File

@ -6,13 +6,6 @@
background-color: #febc2b;
}
#header-button {
background-image: url("chrome://browser/skin/images/marketplace-logo.png"), url("chrome://browser/skin/images/chevron.png");
background-size: 32px 32px, 8px 20px;
background-position: left, right 0.5em center;
-moz-padding-start: 2.5em;
}
#main-container {
padding: 2em;
background-color: #EEF2F5;

View File

@ -23,6 +23,7 @@ PYTHON_UNIT_TESTS += [
'mozbuild/dumbmake/test/test_dumbmake.py',
'mozbuild/mozbuild/test/__init__.py',
'mozbuild/mozbuild/test/action/test_buildlist.py',
'mozbuild/mozbuild/test/action/test_generate_browsersearch.py',
'mozbuild/mozbuild/test/backend/__init__.py',
'mozbuild/mozbuild/test/backend/common.py',
'mozbuild/mozbuild/test/backend/test_android_eclipse.py',

View File

@ -22,9 +22,13 @@ browsersearch.json in the locale-specific raw resource directory
e.g. raw/browsersearch.json, raw-pt-rBR/browsersearch.json.
'''
from __future__ import print_function
from __future__ import (
print_function,
unicode_literals,
)
import argparse
import codecs
import json
import re
import sys
@ -72,8 +76,9 @@ def main(args):
engines = properties.get_list('browser.search.order')
if opts.verbose:
print('Read {len} engines: {engines}'.format(len=len(engines), engines=engines))
print("Default engine is '{default}'.".format(default=default))
writer = codecs.getwriter('utf-8')(sys.stdout)
print('Read {len} engines: {engines}'.format(len=len(engines), engines=engines), file=writer)
print("Default engine is '{default}'.".format(default=default), file=writer)
browsersearch = {}
browsersearch['default'] = default

View File

@ -0,0 +1,12 @@
# A region.properties file with invalid unicode byte sequences. The
# sequences were cribbed from Markus Kuhn's "UTF-8 decoder capability
# and stress test", available at
# http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
# 3.5 Impossible bytes |
# |
# The following two bytes cannot appear in a correct UTF-8 string |
# |
# 3.5.1 fe = "þ" |
# 3.5.2 ff = "ÿ" |
# 3.5.3 fe fe ff ff = "þþÿÿ" |

View File

@ -0,0 +1,37 @@
# 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/.
# Default search engine
browser.search.defaultenginename=百度
# Search engine order (order displayed in the search bar dropdown)s
browser.search.order.1=百度
browser.search.order.2=Google
# This is the default set of web based feed handlers shown in the reader
# selection UI
browser.contentHandlers.types.0.title=Bloglines
browser.contentHandlers.types.0.uri=http://www.bloglines.com/login?r=/sub/%s
# increment this number when anything gets changed in the list below. This will
# cause Firefox to re-read these prefs and inject any new handlers into the
# profile database. Note that "new" is defined as "has a different URL"; this
# means that it's not possible to update the name of existing handler, so
# don't make any spelling errors here.
gecko.handlerService.defaultHandlersVersion=3
# The default set of protocol handlers for webcal:
gecko.handlerService.schemes.webcal.0.name=30 Boxes
gecko.handlerService.schemes.webcal.0.uriTemplate=https://30boxes.com/external/widget?refer=ff&url=%s
# The default set of protocol handlers for mailto:
gecko.handlerService.schemes.mailto.0.name=Yahoo! 邮件
gecko.handlerService.schemes.mailto.0.uriTemplate=https://compose.mail.yahoo.com/?To=%s
gecko.handlerService.schemes.mailto.1.name=Gmail
gecko.handlerService.schemes.mailto.1.uriTemplate=https://mail.google.com/mail/?extsrc=mailto&url=%s
# This is the default set of web based feed handlers shown in the reader
# selection UI
browser.contentHandlers.types.0.title=My Yahoo!
browser.contentHandlers.types.0.uri=http://www.bloglines.com/login?r=/sub/%s

View File

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
from __future__ import unicode_literals
import json
import os
import unittest
import mozunit
import mozbuild.action.generate_browsersearch as generate_browsersearch
from mozfile.mozfile import (
NamedTemporaryFile,
TemporaryDirectory,
)
import mozpack.path as mozpath
test_data_path = mozpath.abspath(mozpath.dirname(__file__))
test_data_path = mozpath.join(test_data_path, 'data')
class TestGenerateBrowserSearch(unittest.TestCase):
"""
Unit tests for generate_browsersearch.py.
"""
def _test_one(self, name):
with TemporaryDirectory() as tmpdir:
with NamedTemporaryFile(mode='r+') as temp:
srcdir = os.path.join(test_data_path, name)
generate_browsersearch.main([
'--verbose',
'--srcdir', srcdir,
temp.name])
return json.load(temp)
def test_valid_unicode(self):
o = self._test_one('valid-zh-CN')
self.assertEquals(o['default'], '百度')
self.assertEquals(o['engines'], ['百度', 'Google'])
def test_invalid_unicode(self):
with self.assertRaises(UnicodeDecodeError):
self._test_one('invalid')
if __name__ == '__main__':
mozunit.main()

View File

@ -64,6 +64,7 @@ const SearchAutocompleteProviderInternal = {
case "engine-added":
case "engine-changed":
case "engine-removed":
case "engine-current":
this._refresh();
}
},

View File

@ -31,5 +31,17 @@ add_task(function*() {
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "mozzarella cheese", searchQuery: "mozzarella cheese"}), title: "MozSearch" }, ]
});
do_log_info("search engine, after current engine has changed");
Services.search.addEngineWithDetails("MozSearch2", "", "", "", "GET",
"http://s.example.com/search2");
engine = Services.search.getEngineByName("MozSearch2");
notEqual(Services.search.currentEngine, engine, "New engine shouldn't be the current engine yet");
Services.search.currentEngine = engine;
yield check_autocomplete({
search: "mozilla",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch2", input: "mozilla", searchQuery: "mozilla"}), title: "MozSearch2" }, ]
});
yield cleanup();
});