Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2014-07-28 16:04:12 +02:00
commit 110f1073fd
1358 changed files with 4183 additions and 2171 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1016529 - Updating Android SDK to include Google Play Services
Multiple bugs that happened to trigger bug 1042115.

View File

@ -200,6 +200,7 @@ MAKE_SYM_STORE_ARGS := -c --vcs-info
DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms
MAKE_SYM_STORE_PATH := $(DIST)/bin
endif
MAKE_SYM_STORE_ARGS += --install-manifest=$(DEPTH)/_build_manifests/install/dist_include,$(DIST)/include
SYM_STORE_SOURCE_DIRS := $(topsrcdir)

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dd42afb7d6d66a6c2bd999692fec6b6d553d23de"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dd42afb7d6d66a6c2bd999692fec6b6d553d23de"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="999e945b85c578c503ad445c2285940f16aacdae">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dd42afb7d6d66a6c2bd999692fec6b6d553d23de"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dd42afb7d6d66a6c2bd999692fec6b6d553d23de"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dd42afb7d6d66a6c2bd999692fec6b6d553d23de"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "3762f6bf4b014e34e62162e84c6acf7deebbbcfa",
"revision": "97a95feb1d1505c9d179266fee891e600ad8760b",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dd42afb7d6d66a6c2bd999692fec6b6d553d23de"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dd42afb7d6d66a6c2bd999692fec6b6d553d23de"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dd42afb7d6d66a6c2bd999692fec6b6d553d23de"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11f01789444d4ebe97581c31d8756d773e18356f"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dd42afb7d6d66a6c2bd999692fec6b6d553d23de"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="295967a0b824a355ae9d57fb08f3632ed2ad18dd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1405723700000">
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1406149943000">
<emItems>
<emItem blockID="i454" id="sqlmoz@facebook.com">
<versionRange minVersion="0" maxVersion="*" severity="3">
@ -38,6 +38,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i646" id="{e1aaa9f8-4500-47f1-9a0a-b02bd60e4076}">
<versionRange minVersion="178.7.0" maxVersion="178.7.0" severity="3">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i107" os="WINNT" id="{ABDE892B-13A8-4d1b-88E6-365A6E755758}">
<versionRange minVersion="0" maxVersion="15.0.5" severity="1">
@ -123,8 +129,8 @@
<prefs>
</prefs>
</emItem>
<emItem blockID="i660" id="youplayer@addons.mozilla.org">
<versionRange minVersion="79.9.8" maxVersion="208.0.1" severity="3">
<emItem blockID="i674" id="crossriderapp12555@crossrider.com">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
<prefs>
</prefs>
@ -457,6 +463,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i672" id="/^(saamazon@mybrowserbar\.com)|(saebay@mybrowserbar\.com)$/">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i543" id="{badea1ae-72ed-4f6a-8c37-4db9a4ac7bc9}">
<versionRange minVersion="0" maxVersion="*" severity="1">
@ -739,8 +751,8 @@
<prefs>
</prefs>
</emItem>
<emItem blockID="i642" id="{bee6eb20-01e0-ebd1-da83-080329fb9a3a}">
<versionRange minVersion="40.10.1" maxVersion="44.10.1" severity="3">
<emItem blockID="i660" id="youplayer@addons.mozilla.org">
<versionRange minVersion="79.9.8" maxVersion="208.0.1" severity="3">
</versionRange>
<prefs>
</prefs>
@ -757,8 +769,8 @@
<prefs>
</prefs>
</emItem>
<emItem blockID="i646" id="{e1aaa9f8-4500-47f1-9a0a-b02bd60e4076}">
<versionRange minVersion="178.7.0" maxVersion="178.7.0" severity="3">
<emItem blockID="i678" id="{C4A4F5A0-4B89-4392-AFAC-D58010E349AF}">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
<prefs>
</prefs>
@ -1245,8 +1257,8 @@
<prefs>
</prefs>
</emItem>
<emItem blockID="i540" id="/^(ffxtlbr@mixidj\.com|{c0c2693d-2ee8-47b4-9df7-b67a0ee31988}|{67097627-fd8e-4f6b-af4b-ecb65e50112e}|{f6f0f973-a4a3-48cf-9a7a-b7a69c30d71a}|{a3d0e35f-f1da-4ccb-ae77-e9d27777e68d}|{1122b43d-30ee-403f-9bfa-3cc99b0caddd})$/">
<versionRange minVersion="0" maxVersion="*" severity="3">
<emItem blockID="i676" id="SpecialSavings@SpecialSavings.com">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
<prefs>
</prefs>
@ -1426,6 +1438,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i642" id="{bee6eb20-01e0-ebd1-da83-080329fb9a3a}">
<versionRange minVersion="40.10.1" maxVersion="44.10.1" severity="3">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i586" id="jid1-0xtMKhXFEs4jIg@jetpack">
<versionRange minVersion="0" maxVersion="*" severity="3">
@ -1844,6 +1862,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i540" id="/^(ffxtlbr@mixidj\.com|{c0c2693d-2ee8-47b4-9df7-b67a0ee31988}|{67097627-fd8e-4f6b-af4b-ecb65e50112e}|{f6f0f973-a4a3-48cf-9a7a-b7a69c30d71a}|{a3d0e35f-f1da-4ccb-ae77-e9d27777e68d}|{1122b43d-30ee-403f-9bfa-3cc99b0caddd})$/">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i455" id="7d51fb17-b199-4d8f-894e-decaff4fc36a@a298838b-7f50-4c7c-9277-df6abbd42a0c.com">
<versionRange minVersion="0" maxVersion="*" severity="3">

View File

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100">
<g fill="#85898C">
<circle cx="50" cy="50" r="44" style="stroke: #85898C; stroke-width: 11; fill: transparent;"/>
<g fill="#424E5A">
<circle cx="50" cy="50" r="44" style="stroke: #424E5A; stroke-width: 11; fill: transparent;"/>
<circle cx="50" cy="24.6" r="6.4"/>
<rect x="45" y="39.9" width="10.1" height="41.8"/>
</g>

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 348 B

View File

@ -5604,7 +5604,7 @@ var OfflineApps = {
// OfflineApps Implementation Methods
// XXX: _getBrowserWindowForContentWindow and _getBrowserForContentWindow
// were taken from browser/components/feeds/src/WebContentConverter.
// were taken from browser/components/feeds/WebContentConverter.
_getBrowserWindowForContentWindow: function(aContentWindow) {
return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)

View File

@ -19,9 +19,9 @@ IS_COMPONENT = True
LOCAL_INCLUDES += [
'../about',
'../dirprovider',
'../feeds/src',
'../migration/src',
'../shell/src',
'../feeds',
'../migration',
'../shell',
]
USE_LIBS += [

View File

@ -6,7 +6,26 @@
PARALLEL_DIRS += [
'content',
'src',
]
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
EXTRA_JS_MODULES += [
'DragPositionManager.jsm',
'ScrollbarSampler.jsm',
]
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1
EXTRA_PP_JS_MODULES += [
'CustomizableUI.jsm',
'CustomizableWidgets.jsm',
'CustomizeMode.jsm',
'PanelWideWidgetTracker.jsm',
]

View File

@ -1,25 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXTRA_JS_MODULES += [
'DragPositionManager.jsm',
'ScrollbarSampler.jsm',
]
DEFINES['E10S_TESTING_ONLY'] = CONFIG['E10S_TESTING_ONLY']
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1
EXTRA_PP_JS_MODULES += [
'CustomizableUI.jsm',
'CustomizableWidgets.jsm',
'CustomizeMode.jsm',
'PanelWideWidgetTracker.jsm',
]

View File

@ -4,14 +4,19 @@
# 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/.
DIRS += ['src']
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
XPCSHELL_TESTS_MANIFESTS += [
'test/unit/xpcshell.ini',
JAR_MANIFESTS += ['jar.mn']
EXTRA_COMPONENTS += [
'BrowserDownloads.manifest',
'DownloadsStartup.js',
'DownloadsUI.js',
]
BROWSER_CHROME_MANIFESTS += [
'test/browser/browser.ini',
EXTRA_JS_MODULES += [
'DownloadsCommon.jsm',
'DownloadsLogger.jsm',
'DownloadsTaskbar.jsm',
]
JAR_MANIFESTS += ['jar.mn']

View File

@ -1,18 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXTRA_COMPONENTS += [
'BrowserDownloads.manifest',
'DownloadsStartup.js',
'DownloadsUI.js',
]
EXTRA_JS_MODULES += [
'DownloadsCommon.jsm',
'DownloadsLogger.jsm',
'DownloadsTaskbar.jsm',
]

View File

@ -4,18 +4,38 @@
# 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/.
DIRS += ['public', 'src']
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
MOCHITEST_CHROME_MANIFESTS += ['test/chrome/chrome.ini']
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
XPCSHELL_TESTS_MANIFESTS += [
'test/unit/xpcshell.ini',
JAR_MANIFESTS += ['jar.mn']
XPIDL_SOURCES += [
'nsIFeedResultService.idl',
'nsIWebContentConverterRegistrar.idl',
]
MOCHITEST_CHROME_MANIFESTS += [
'test/chrome/chrome.ini',
XPIDL_MODULE = 'browser-feeds'
SOURCES += [
'nsFeedSniffer.cpp',
]
MOCHITEST_MANIFESTS += [
'test/mochitest.ini'
EXTRA_COMPONENTS += [
'BrowserFeeds.manifest',
'FeedConverter.js',
'WebContentConverter.js',
]
JAR_MANIFESTS += ['jar.mn']
EXTRA_PP_COMPONENTS += [
'FeedWriter.js',
]
FINAL_LIBRARY = 'browsercomps'
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
DEFINES[var] = CONFIG[var]
LOCAL_INCLUDES += [
'../build',
]

View File

@ -1,13 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
XPIDL_SOURCES += [
'nsIFeedResultService.idl',
'nsIWebContentConverterRegistrar.idl',
]
XPIDL_MODULE = 'browser-feeds'

View File

@ -1,29 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
SOURCES += [
'nsFeedSniffer.cpp',
]
EXTRA_COMPONENTS += [
'BrowserFeeds.manifest',
'FeedConverter.js',
'WebContentConverter.js',
]
EXTRA_PP_COMPONENTS += [
'FeedWriter.js',
]
FINAL_LIBRARY = 'browsercomps'
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
DEFINES[var] = CONFIG[var]
LOCAL_INCLUDES += [
'../../build',
]

View File

@ -82,7 +82,15 @@ loop.Client = (function($) {
* @param {Function} cb Callback(err)
*/
_ensureRegistered: function(cb) {
this.mozLoop.ensureRegistered(cb);
this.mozLoop.ensureRegistered(function(error) {
if (error) {
console.log("Error registering with Loop server, code: " + error);
cb(error);
return;
} else {
cb(null);
}
});
},
/**
@ -125,6 +133,45 @@ loop.Client = (function($) {
});
},
/**
* Block call URL based on the token identifier
*
* @param {string} token Conversation identifier used to block the URL
* @param {function} cb Callback function used for handling an error
* response. XXX The incoming call panel does not
* exist after the block button is clicked therefore
* it does not make sense to display an error.
**/
deleteCallUrl: function(token, cb) {
this._ensureRegistered(function(err) {
if (err) {
cb(err);
return;
}
this._deleteCallUrlInternal(token, cb);
}.bind(this));
},
_deleteCallUrlInternal: function(token, cb) {
this.mozLoop.hawkRequest("/call-url/" + token, "DELETE", null,
(error, responseText) => {
if (error) {
this._failureHandler(cb, error);
return;
}
try {
cb(null);
this.mozLoop.noteCallUrlExpiry((new Date()).getTime() / 1000);
} catch (err) {
console.log("Error deleting call info", err);
cb(err);
}
});
},
/**
* Requests a call URL from the Loop server. It will note the
* expiry time for the url with the mozLoop api.
@ -142,7 +189,6 @@ loop.Client = (function($) {
requestCallUrl: function(nickname, cb) {
this._ensureRegistered(function(err) {
if (err) {
console.log("Error registering with Loop server, code: " + err);
cb(err);
return;
}

View File

@ -27,6 +27,27 @@ loop.conversation = (function(OT, mozL10n) {
model: React.PropTypes.func.isRequired
},
getInitialState: function() {
return {showDeclineMenu: false};
},
componentDidMount: function() {
window.addEventListener('click', this.clickHandler);
window.addEventListener('blur', this._hideDeclineMenu);
},
componentWillUnmount: function() {
window.removeEventListener('click', this.clickHandler);
window.removeEventListener('blur', this._hideDeclineMenu);
},
clickHandler: function(e) {
var target = e.target;
if (!target.classList.contains('btn-chevron')) {
this._hideDeclineMenu();
}
},
/**
* Used for adding different styles to the panel
* @returns {String} Corresponds to the client platform
@ -55,19 +76,56 @@ loop.conversation = (function(OT, mozL10n) {
this.props.model.trigger("decline");
},
_handleDeclineBlock: function(e) {
this.props.model.trigger("declineAndBlock");
/* Prevent event propagation
* stop the click from reaching parent element */
return false;
},
_toggleDeclineMenu: function() {
var currentState = this.state.showDeclineMenu;
this.setState({showDeclineMenu: !currentState});
},
_hideDeclineMenu: function() {
this.setState({showDeclineMenu: false});
},
render: function() {
/* jshint ignore:start */
var btnClassAccept = "btn btn-error btn-decline";
var btnClassDecline = "btn btn-success btn-accept";
var btnClassAccept = "btn btn-success btn-accept";
var btnClassBlock = "btn btn-error btn-block";
var btnClassDecline = "btn btn-error btn-decline";
var conversationPanelClass = "incoming-call " + this._getTargetPlatform();
var cx = React.addons.classSet;
var declineDropdownMenuClasses = cx({
"native-dropdown-menu": true,
"decline-block-menu": true,
"visually-hidden": !this.state.showDeclineMenu
});
return (
React.DOM.div( {className:conversationPanelClass},
React.DOM.h2(null, __("incoming_call")),
React.DOM.div( {className:"button-group"},
React.DOM.button( {className:btnClassAccept, onClick:this._handleDecline},
__("incoming_call_decline_button")
),
React.DOM.button( {className:btnClassDecline, onClick:this._handleAccept},
React.DOM.div({className: conversationPanelClass},
React.DOM.h2(null, __("incoming_call")),
React.DOM.div({className: "button-group incoming-call-action-group"},
React.DOM.div({className: "button-chevron-menu-group"},
React.DOM.div({className: "button-group-chevron"},
React.DOM.div({className: "button-group"},
React.DOM.button({className: btnClassDecline, onClick: this._handleDecline},
__("incoming_call_decline_button")
),
React.DOM.div({className: "btn-chevron",
onClick: this._toggleDeclineMenu}
)
),
React.DOM.ul({className: declineDropdownMenuClasses},
React.DOM.li({className: "btn-block", onClick: this._handleDeclineBlock},
__("incoming_call_decline_and_block_button")
)
)
)
),
React.DOM.button({className: btnClassAccept, onClick: this._handleAccept},
__("incoming_call_answer_button")
)
)
@ -116,7 +174,8 @@ loop.conversation = (function(OT, mozL10n) {
"call/accept": "accept",
"call/decline": "decline",
"call/ongoing": "conversation",
"call/ended": "ended"
"call/ended": "ended",
"call/declineAndBlock": "declineAndBlock"
},
/**
@ -148,6 +207,9 @@ loop.conversation = (function(OT, mozL10n) {
this._conversation.once("decline", function() {
this.navigate("call/decline", {trigger: true});
}.bind(this));
this._conversation.once("declineAndBlock", function() {
this.navigate("call/declineAndBlock", {trigger: true});
}.bind(this));
this.loadReactComponent(loop.conversation.IncomingCallView({
model: this._conversation
}));
@ -173,6 +235,24 @@ loop.conversation = (function(OT, mozL10n) {
window.close();
},
/**
* Decline and block an incoming call
* @note:
* - loopToken is the callUrl identifier. It gets set in the panel
* after a callUrl is received
*/
declineAndBlock: function() {
window.navigator.mozLoop.stopAlerting();
var token = navigator.mozLoop.getLoopCharPref('loopToken');
var client = new loop.Client();
client.deleteCallUrl(token, function(error) {
// XXX The conversation window will be closed when this cb is triggered
// figure out if there is a better way to report the error to the user
console.log(error);
});
window.close();
},
/**
* conversation is the route when the conversation is active. The start
* route should be navigated to first.

View File

@ -27,6 +27,27 @@ loop.conversation = (function(OT, mozL10n) {
model: React.PropTypes.func.isRequired
},
getInitialState: function() {
return {showDeclineMenu: false};
},
componentDidMount: function() {
window.addEventListener('click', this.clickHandler);
window.addEventListener('blur', this._hideDeclineMenu);
},
componentWillUnmount: function() {
window.removeEventListener('click', this.clickHandler);
window.removeEventListener('blur', this._hideDeclineMenu);
},
clickHandler: function(e) {
var target = e.target;
if (!target.classList.contains('btn-chevron')) {
this._hideDeclineMenu();
}
},
/**
* Used for adding different styles to the panel
* @returns {String} Corresponds to the client platform
@ -55,19 +76,56 @@ loop.conversation = (function(OT, mozL10n) {
this.props.model.trigger("decline");
},
_handleDeclineBlock: function(e) {
this.props.model.trigger("declineAndBlock");
/* Prevent event propagation
* stop the click from reaching parent element */
return false;
},
_toggleDeclineMenu: function() {
var currentState = this.state.showDeclineMenu;
this.setState({showDeclineMenu: !currentState});
},
_hideDeclineMenu: function() {
this.setState({showDeclineMenu: false});
},
render: function() {
/* jshint ignore:start */
var btnClassAccept = "btn btn-error btn-decline";
var btnClassDecline = "btn btn-success btn-accept";
var btnClassAccept = "btn btn-success btn-accept";
var btnClassBlock = "btn btn-error btn-block";
var btnClassDecline = "btn btn-error btn-decline";
var conversationPanelClass = "incoming-call " + this._getTargetPlatform();
var cx = React.addons.classSet;
var declineDropdownMenuClasses = cx({
"native-dropdown-menu": true,
"decline-block-menu": true,
"visually-hidden": !this.state.showDeclineMenu
});
return (
<div className={conversationPanelClass}>
<h2>{__("incoming_call")}</h2>
<div className="button-group">
<button className={btnClassAccept} onClick={this._handleDecline}>
{__("incoming_call_decline_button")}
</button>
<button className={btnClassDecline} onClick={this._handleAccept}>
<div className="button-group incoming-call-action-group">
<div className="button-chevron-menu-group">
<div className="button-group-chevron">
<div className="button-group">
<button className={btnClassDecline} onClick={this._handleDecline}>
{__("incoming_call_decline_button")}
</button>
<div className="btn-chevron"
onClick={this._toggleDeclineMenu}>
</div>
</div>
<ul className={declineDropdownMenuClasses}>
<li className="btn-block" onClick={this._handleDeclineBlock}>
{__("incoming_call_decline_and_block_button")}
</li>
</ul>
</div>
</div>
<button className={btnClassAccept} onClick={this._handleAccept}>
{__("incoming_call_answer_button")}
</button>
</div>
@ -116,7 +174,8 @@ loop.conversation = (function(OT, mozL10n) {
"call/accept": "accept",
"call/decline": "decline",
"call/ongoing": "conversation",
"call/ended": "ended"
"call/ended": "ended",
"call/declineAndBlock": "declineAndBlock"
},
/**
@ -148,6 +207,9 @@ loop.conversation = (function(OT, mozL10n) {
this._conversation.once("decline", function() {
this.navigate("call/decline", {trigger: true});
}.bind(this));
this._conversation.once("declineAndBlock", function() {
this.navigate("call/declineAndBlock", {trigger: true});
}.bind(this));
this.loadReactComponent(loop.conversation.IncomingCallView({
model: this._conversation
}));
@ -173,6 +235,24 @@ loop.conversation = (function(OT, mozL10n) {
window.close();
},
/**
* Decline and block an incoming call
* @note:
* - loopToken is the callUrl identifier. It gets set in the panel
* after a callUrl is received
*/
declineAndBlock: function() {
window.navigator.mozLoop.stopAlerting();
var token = navigator.mozLoop.getLoopCharPref('loopToken');
var client = new loop.Client();
client.deleteCallUrl(token, function(error) {
// XXX The conversation window will be closed when this cb is triggered
// figure out if there is a better way to report the error to the user
console.log(error);
});
window.close();
},
/**
* conversation is the route when the conversation is active. The start
* route should be navigated to first.

View File

@ -77,22 +77,22 @@ loop.panel = (function(_, mozL10n) {
__("display_name_available_status");
return (
React.DOM.div( {className:"footer component-spacer"},
React.DOM.div( {className:"do-not-disturb"},
React.DOM.p( {className:"dnd-status", onClick:this.showDropdownMenu},
React.DOM.span(null, availabilityText),
React.DOM.i( {className:availabilityStatus})
),
React.DOM.ul( {className:availabilityDropdown,
onMouseLeave:this.hideDropdownMenu},
React.DOM.li( {onClick:this.changeAvailability("available"),
className:"dnd-menu-item dnd-make-available"},
React.DOM.i( {className:"status status-available"}),
React.DOM.div({className: "footer component-spacer"},
React.DOM.div({className: "do-not-disturb"},
React.DOM.p({className: "dnd-status", onClick: this.showDropdownMenu},
React.DOM.span(null, availabilityText),
React.DOM.i({className: availabilityStatus})
),
React.DOM.ul({className: availabilityDropdown,
onMouseLeave: this.hideDropdownMenu},
React.DOM.li({onClick: this.changeAvailability("available"),
className: "dnd-menu-item dnd-make-available"},
React.DOM.i({className: "status status-available"}),
React.DOM.span(null, __("display_name_available_status"))
),
React.DOM.li( {onClick:this.changeAvailability("do-not-disturb"),
className:"dnd-menu-item dnd-make-unavailable"},
React.DOM.i( {className:"status status-dnd"}),
),
React.DOM.li({onClick: this.changeAvailability("do-not-disturb"),
className: "dnd-menu-item dnd-make-unavailable"},
React.DOM.i({className: "status status-dnd"}),
React.DOM.span(null, __("display_name_dnd_status"))
)
)
@ -115,10 +115,10 @@ loop.panel = (function(_, mozL10n) {
if (this.state.seenToS == "unseen") {
navigator.mozLoop.setLoopCharPref('seenToS', 'seen');
return React.DOM.p( {className:"terms-service",
dangerouslySetInnerHTML:{__html: tosHTML}});
return React.DOM.p({className: "terms-service",
dangerouslySetInnerHTML: {__html: tosHTML}});
} else {
return React.DOM.div(null );
return React.DOM.div(null);
}
}
});
@ -130,11 +130,11 @@ loop.panel = (function(_, mozL10n) {
render: function() {
return (
React.DOM.div( {className:"component-spacer share generate-url"},
React.DOM.div( {className:"description"},
React.DOM.p( {className:"description-content"}, this.props.summary)
),
React.DOM.div( {className:"action"},
React.DOM.div({className: "component-spacer share generate-url"},
React.DOM.div({className: "description"},
React.DOM.p({className: "description-content"}, this.props.summary)
),
React.DOM.div({className: "action"},
this.props.children
)
)
@ -155,6 +155,10 @@ loop.panel = (function(_, mozL10n) {
* Returns a random 5 character string used to identify
* the conversation.
* XXX this will go away once the backend changes
* @note:
* - When we get back a callUrl we use setLoopCharPref to store the token
* (the last fragment of the URL) so that it can be used to ignore&block
* the call. The preference is used by the conversation router.
*/
conversationIdentifier: function() {
return Math.random().toString(36).substring(5);
@ -167,22 +171,28 @@ loop.panel = (function(_, mozL10n) {
},
_onCallUrlReceived: function(err, callUrlData) {
// XXX this initializer is a bug, as it will cause
// setState to set the callUrl to false if one is not returned.
// Should decide on an implement correct behavior and state
// (eg set widget as disabled, state.callUrl == '')
//
var callUrl = false;
this.props.notifier.clear();
if (err) {
this.props.notifier.errorL10n("unable_retrieve_url");
this.setState({pending: false});
} else {
callUrl = callUrlData.callUrl || callUrlData.call_url;
}
try {
var callUrl = new window.URL(callUrlData.callUrl ||
callUrlData.call_url);
// XXX the current server vers does not implement the callToken field
// but it exists in the API. This workaround should be removed in the future
var token = callUrlData.callToken ||
callUrl.pathname.split('/').pop();
this.setState({pending: false, callUrl: callUrl});
navigator.mozLoop.setLoopCharPref('loopToken', token);
this.setState({pending: false, callUrl: callUrl.href});
} catch(e) {
console.log(e);
this.props.notifier.errorL10n("unable_retrieve_url");
this.setState({pending: false});
}
}
},
render: function() {
@ -192,10 +202,10 @@ loop.panel = (function(_, mozL10n) {
// from the react lib.
var cx = React.addons.classSet;
return (
PanelLayout( {summary:__("share_link_header_text")},
React.DOM.div( {className:"invite"},
React.DOM.input( {type:"url", value:this.state.callUrl, readOnly:"true",
className:cx({'pending': this.state.pending})} )
PanelLayout({summary: __("share_link_header_text")},
React.DOM.div({className: "invite"},
React.DOM.input({type: "url", value: this.state.callUrl, readOnly: "true",
className: cx({'pending': this.state.pending})})
)
)
);
@ -214,10 +224,10 @@ loop.panel = (function(_, mozL10n) {
render: function() {
return (
React.DOM.div(null,
CallUrlResult( {client:this.props.client,
notifier:this.props.notifier} ),
ToSView(null ),
AvailabilityDropdown(null )
CallUrlResult({client: this.props.client,
notifier: this.props.notifier}),
ToSView(null),
AvailabilityDropdown(null)
)
);
}
@ -284,8 +294,8 @@ loop.panel = (function(_, mozL10n) {
var client = new loop.Client({
baseServerUrl: navigator.mozLoop.serverUrl
});
this.loadReactComponent(PanelView( {client:client,
notifier:this._notifier} ));
this.loadReactComponent(PanelView({client: client,
notifier: this._notifier}));
}
});

View File

@ -155,6 +155,10 @@ loop.panel = (function(_, mozL10n) {
* Returns a random 5 character string used to identify
* the conversation.
* XXX this will go away once the backend changes
* @note:
* - When we get back a callUrl we use setLoopCharPref to store the token
* (the last fragment of the URL) so that it can be used to ignore&block
* the call. The preference is used by the conversation router.
*/
conversationIdentifier: function() {
return Math.random().toString(36).substring(5);
@ -167,22 +171,28 @@ loop.panel = (function(_, mozL10n) {
},
_onCallUrlReceived: function(err, callUrlData) {
// XXX this initializer is a bug, as it will cause
// setState to set the callUrl to false if one is not returned.
// Should decide on an implement correct behavior and state
// (eg set widget as disabled, state.callUrl == '')
//
var callUrl = false;
this.props.notifier.clear();
if (err) {
this.props.notifier.errorL10n("unable_retrieve_url");
this.setState({pending: false});
} else {
callUrl = callUrlData.callUrl || callUrlData.call_url;
}
try {
var callUrl = new window.URL(callUrlData.callUrl ||
callUrlData.call_url);
// XXX the current server vers does not implement the callToken field
// but it exists in the API. This workaround should be removed in the future
var token = callUrlData.callToken ||
callUrl.pathname.split('/').pop();
this.setState({pending: false, callUrl: callUrl});
navigator.mozLoop.setLoopCharPref('loopToken', token);
this.setState({pending: false, callUrl: callUrl.href});
} catch(e) {
console.log(e);
this.props.notifier.errorL10n("unable_retrieve_url");
this.setState({pending: false});
}
}
},
render: function() {

View File

@ -53,6 +53,10 @@ img {
display: none;
}
.visually-hidden {
visibility: hidden;
}
.tc {
text-align: center;
}
@ -73,57 +77,111 @@ img {
padding: 0 0.5em;
border-radius: 2px;
cursor: pointer;
font-size: .9em;
text-align: center;
}
.btn-info {
background: #0096dd;
background-color: #0096dd;
border: 1px solid #0095dd;
}
.btn-info:hover {
background: #008acb;
background-color: #008acb;
border: 1px solid #008acb;
}
.btn-info:active {
background: #006b9d;
background-color: #006b9d;
border: 1px solid #006b9d;
}
.btn-success {
background: #74bf43;
background-color: #74bf43;
border: 1px solid #74bf43;
}
.btn-success:hover {
background: #6cb23e;
background-color: #6cb23e;
border: 1px solid #6cb23e;
}
.btn-success:active {
background: #64a43a;
background-color: #64a43a;
border: 1px solid #64a43a;
}
.btn-warning {
background: #f0ad4e;
background-color: #f0ad4e;
}
.btn-error {
background: #d74345;
.btn-error,
.btn-error + .btn-chevron {
background-color: #d74345;
border: 1px solid #d74345;
}
.btn-error:hover {
background: #c53436;
.btn-error:hover,
.btn-error + .btn-chevron:hover {
background-color: #c53436;
border: 1px solid #c53436;
}
.btn-error:active {
background: #ae2325;
.btn-error:active,
.btn-error + .btn-chevron:active {
background-color: #ae2325;
border: 1px solid #ae2325;
}
.btn-chevron {
width: 26px;
height: 26px;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
/* Groups together a button and a chevron */
.button-group-chevron {
display: flex;
flex-direction: column;
flex: 1;
}
/* Groups together a button-group-chevron
* and the dropdown menu */
.button-chevron-menu-group {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
flex: 1;
}
.button-group-chevron .btn {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
flex: 2;
}
.btn + .btn-chevron,
.btn + .btn-chevron:hover,
.btn + .btn-chevron:active {
border-left: 1px solid rgba(255,255,255,.4);
background-image: url("../img/dropdown-inverse.png");
background-repeat: no-repeat;
background-position: center;
background-size: 10px;
}
@media (min-resolution: 2dppx) {
.btn-chevron {
background-image: url(../img/dropdown-inverse@2x.png);
background-position: center;
background-size: 10px;
background-repeat: no-repeat;
}
}
.disabled, button[disabled] {
cursor: not-allowed;
pointer-events: none;
@ -133,12 +191,10 @@ img {
.button-group {
display: flex;
width: 100%;
padding: 1em;
}
.button-group .btn {
flex: 1;
margin: 0 .3em;
}
/* Alerts */

View File

@ -177,8 +177,46 @@
min-height: 264px;
}
.incoming-call-action-group {
padding: 2.5em 1em;
}
.incoming-call-action-group .button-chevron-menu-group {
margin-right: .5em;
}
.incoming-call-action-group > .btn {
margin-left: .5em;
}
.incoming-call h2 {
font-size: 1.5em;
font-weight: normal;
}
/* Block incoming call */
.native-dropdown-menu {
/* Should match a native select menu */
padding: 0;
position: absolute; /* element can be wider than the parent */
background: #fff;
margin: 0;
box-shadow: 0 4px 5px rgba(30, 30, 30, .3);
border-style: solid;
border-width: 1px 1px 1px 2px;
border-color: #aaa #111 #111 #aaa;
}
.decline-block-menu li {
padding: 0 10px 0 5px;
list-style: none;
font-size: .9em;
color: #000;
cursor: pointer;
}
.decline-block-menu li:hover {
color: #FFF;
background: #111;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

View File

@ -138,9 +138,11 @@ loop.shared.views = (function(_, OT, l10n) {
render: function() {
return (
React.DOM.button( {className:this._getClasses(),
title:this._getTitle(),
onClick:this.handleClick})
/* jshint ignore:start */
React.DOM.button({className: this._getClasses(),
title: this._getTitle(),
onClick: this.handleClick})
/* jshint ignore:end */
);
}
});
@ -176,19 +178,21 @@ loop.shared.views = (function(_, OT, l10n) {
},
render: function() {
/* jshint ignore:start */
return (
React.DOM.ul( {className:"controls"},
React.DOM.li(null, React.DOM.button( {className:"btn btn-hangup",
onClick:this.handleClickHangup,
title:__("hangup_button_title")})),
React.DOM.li(null, MediaControlButton( {action:this.handleToggleVideo,
enabled:this.props.video.enabled,
scope:"local", type:"video"} )),
React.DOM.li(null, MediaControlButton( {action:this.handleToggleAudio,
enabled:this.props.audio.enabled,
scope:"local", type:"audio"} ))
React.DOM.ul({className: "controls"},
React.DOM.li(null, React.DOM.button({className: "btn btn-hangup",
onClick: this.handleClickHangup,
title: __("hangup_button_title")})),
React.DOM.li(null, MediaControlButton({action: this.handleToggleVideo,
enabled: this.props.video.enabled,
scope: "local", type: "video"})),
React.DOM.li(null, MediaControlButton({action: this.handleToggleAudio,
enabled: this.props.audio.enabled,
scope: "local", type: "audio"}))
)
);
/* jshint ignore:end */
}
});
@ -200,8 +204,8 @@ loop.shared.views = (function(_, OT, l10n) {
model: React.PropTypes.object.isRequired
},
// height set to "auto" to fix video layout on Google Chrome
// @see https://bugzilla.mozilla.org/show_bug.cgi?id=991122
// height set to 100%" to fix video layout on Google Chrome
// @see https://bugzilla.mozilla.org/show_bug.cgi?id=1020445
publisherConfig: {
insertMode: "append",
width: "100%",
@ -329,20 +333,22 @@ loop.shared.views = (function(_, OT, l10n) {
},
render: function() {
/* jshint ignore:start */
return (
React.DOM.div( {className:"conversation"},
ConversationToolbar( {video:this.state.video,
audio:this.state.audio,
publishStream:this.publishStream,
hangup:this.hangup} ),
React.DOM.div( {className:"media nested"},
React.DOM.div( {className:"video_wrapper remote_wrapper"},
React.DOM.div( {className:"video_inner remote"})
),
React.DOM.div( {className:"local"})
React.DOM.div({className: "conversation"},
ConversationToolbar({video: this.state.video,
audio: this.state.audio,
publishStream: this.publishStream,
hangup: this.hangup}),
React.DOM.div({className: "media nested"},
React.DOM.div({className: "video_wrapper remote_wrapper"},
React.DOM.div({className: "video_inner remote"})
),
React.DOM.div({className: "local"})
)
)
);
/* jshint ignore:end */
}
});

View File

@ -35,6 +35,8 @@ browser.jar:
content/browser/loop/shared/img/mute-inverse-14x14@2x.png (content/shared/img/mute-inverse-14x14@2x.png)
content/browser/loop/shared/img/video-inverse-14x14.png (content/shared/img/video-inverse-14x14.png)
content/browser/loop/shared/img/video-inverse-14x14@2x.png (content/shared/img/video-inverse-14x14@2x.png)
content/browser/loop/shared/img/dropdown-inverse.png (content/shared/img/dropdown-inverse.png)
content/browser/loop/shared/img/dropdown-inverse@2x.png (content/shared/img/dropdown-inverse@2x.png)
# Shared scripts
content/browser/loop/shared/js/models.js (content/shared/js/models.js)

View File

@ -14,7 +14,7 @@ start_call=Start the call
welcome=Welcome to the Loop web client.
incompatible_browser=Incompatible Browser
powered_by_webrtc=The audio and video components of Loop are powered by WebRTC.
use_latest_firefox.innerHTML=To use Loop, please use the latest version of <a href="{{ff_url}}">Firefox</a>.
use_latest_firefox.innerHTML=Please try this link in a WebRTC-enabled browser, such as <a href="{{ff_url}}">Firefox</a>.
incompatible_device=Incompatible device
sorry_device_unsupported=Sorry, Loop does not currently support your device.
use_firefox_windows_mac_linux=Please open this page using the latest Firefox on Windows, Android, Mac or Linux.
@ -37,7 +37,7 @@ start_call=Démarrer l'appel
welcome=Bienvenue sur Loop.
incompatible_browser=Navigateur non supporté
powered_by_webrtc=Les fonctionnalités audio et vidéo de Loop utilisent WebRTC.
use_latest_firefox.innerHTML=Pour utiliser Loop, merci d'utiliser la dernière version de <a href="{{ff_url}}">Firefox</a>.
use_latest_firefox.innerHTML=Veuillez essayer ce lien dans un navigateur acceptant WebRTC, par exemple <a href="{{ff_url}}">Firefox</a>.
incompatible_device=Plateforme non supportée
sorry_device_unsupported=Désolé, Loop ne fonctionne actuellement pas sur votre appareil.
use_firefox_windows_mac_linux=Merci d'ouvrir cette page avec une version récente de Firefox pour Windows, Android, Mac ou Linux.

View File

@ -2,7 +2,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/. */
/*global loop, sinon, it, beforeEach, afterEach, describe, hawk */
/*global loop, sinon, it, beforeEach, afterEach, describe */
var expect = chai.expect;
@ -48,6 +48,70 @@ describe("loop.Client", function() {
});
describe("loop.Client", function() {
describe("#deleteCallUrl", function() {
it("should ensure loop is registered", function() {
client.deleteCallUrl("fakeToken", callback);
sinon.assert.calledOnce(mozLoop.ensureRegistered);
});
it("should send an error when registration fails", function() {
mozLoop.ensureRegistered.callsArgWith(0, "offline");
client.deleteCallUrl("fakeToken", callback);
sinon.assert.calledOnce(callback);
sinon.assert.calledWithExactly(callback, "offline");
});
it("should make a delete call to /call-url/{fakeToken}", function() {
client.deleteCallUrl(fakeToken, callback);
sinon.assert.calledOnce(hawkRequestStub);
sinon.assert.calledWith(hawkRequestStub,
"/call-url/" + fakeToken, "DELETE");
});
it("should call the callback with null when the request succeeds",
function() {
// Sets up the hawkRequest stub to trigger the callback with no error
// and the url.
hawkRequestStub.callsArgWith(3, null);
client.deleteCallUrl(fakeToken, callback);
sinon.assert.calledWithExactly(callback, null);
});
it("should reset all url expiry when the request succeeds", function() {
// Sets up the hawkRequest stub to trigger the callback with no error
// and the url.
var dateInMilliseconds = new Date(2014,7,20).getTime();
hawkRequestStub.callsArgWith(3, null);
sandbox.useFakeTimers(dateInMilliseconds);
client.deleteCallUrl(fakeToken, callback);
sinon.assert.calledOnce(mozLoop.noteCallUrlExpiry);
sinon.assert.calledWithExactly(mozLoop.noteCallUrlExpiry,
dateInMilliseconds / 1000);
});
it("should send an error when the request fails", function() {
// Sets up the hawkRequest stub to trigger the callback with
// an error
hawkRequestStub.callsArgWith(3, fakeErrorRes);
client.deleteCallUrl(fakeToken, callback);
sinon.assert.calledOnce(callback);
sinon.assert.calledWithMatch(callback, sinon.match(function(err) {
return /400.*invalid token/.test(err.message);
}));
});
});
describe("#requestCallUrl", function() {
it("should ensure loop is registered", function() {
client.requestCallUrl("foo", callback);
@ -72,39 +136,41 @@ describe("loop.Client", function() {
"/call-url/", "POST", {callerId: "foo"});
});
it("should call the callback with the url when the request succeeds", function() {
var callUrlData = {
"callUrl": "fakeCallUrl",
"expiresAt": 60
};
it("should call the callback with the url when the request succeeds",
function() {
var callUrlData = {
"callUrl": "fakeCallUrl",
"expiresAt": 60
};
// Sets up the hawkRequest stub to trigger the callback with no error
// and the url.
hawkRequestStub.callsArgWith(3, null,
JSON.stringify(callUrlData));
// Sets up the hawkRequest stub to trigger the callback with no error
// and the url.
hawkRequestStub.callsArgWith(3, null,
JSON.stringify(callUrlData));
client.requestCallUrl("foo", callback);
client.requestCallUrl("foo", callback);
sinon.assert.calledWithExactly(callback, null, callUrlData);
});
sinon.assert.calledWithExactly(callback, null, callUrlData);
});
it("should note the call url expiry when the request succeeds", function() {
var callUrlData = {
"callUrl": "fakeCallUrl",
"expiresAt": 6000
};
it("should note the call url expiry when the request succeeds",
function() {
var callUrlData = {
"callUrl": "fakeCallUrl",
"expiresAt": 6000
};
// Sets up the hawkRequest stub to trigger the callback with no error
// and the url.
hawkRequestStub.callsArgWith(3, null,
JSON.stringify(callUrlData));
// Sets up the hawkRequest stub to trigger the callback with no error
// and the url.
hawkRequestStub.callsArgWith(3, null,
JSON.stringify(callUrlData));
client.requestCallUrl("foo", callback);
client.requestCallUrl("foo", callback);
sinon.assert.calledOnce(mozLoop.noteCallUrlExpiry);
sinon.assert.calledWithExactly(mozLoop.noteCallUrlExpiry,
6000);
});
sinon.assert.calledOnce(mozLoop.noteCallUrlExpiry);
sinon.assert.calledWithExactly(mozLoop.noteCallUrlExpiry,
6000);
});
it("should send an error when the request fails", function() {
// Sets up the hawkRequest stub to trigger the callback with

View File

@ -37,7 +37,8 @@ describe("loop.conversation", function() {
setLoopCharPref: sandbox.stub(),
getLoopCharPref: sandbox.stub(),
startAlerting: function() {},
stopAlerting: function() {}
stopAlerting: function() {},
ensureRegistered: function() {}
};
// XXX These stubs should be hoisted in a common file
@ -252,6 +253,44 @@ describe("loop.conversation", function() {
// close connections nicely
it("should close the window");
});
describe("#blocked", function() {
it("should call mozLoop.stopAlerting", function() {
sandbox.stub(window.navigator.mozLoop, "stopAlerting");
router.declineAndBlock();
sinon.assert.calledOnce(window.navigator.mozLoop.stopAlerting);
});
it("should call delete call", function() {
var deleteCallUrl = sandbox.stub(loop.Client.prototype, "deleteCallUrl");
router.declineAndBlock();
sinon.assert.calledOnce(deleteCallUrl);
});
it("should trigger error handling in case of error", function() {
// XXX just logging to console for now
var log = sandbox.stub(console, "log");
var fakeError = {
error: true
};
sandbox.stub(loop.Client.prototype, "deleteCallUrl", function(_, cb) {
cb(fakeError);
});
router.declineAndBlock();
sinon.assert.calledOnce(log);
sinon.assert.calledWithExactly(log, fakeError);
});
it("should close the window", function() {
sandbox.stub(window, "close");
router.declineAndBlock();
sinon.assert.calledOnce(window.close);
});
});
});
describe("Events", function() {
@ -351,5 +390,16 @@ describe("loop.conversation", function() {
sinon.assert.calledWith(model.trigger, "decline");
});
});
describe("click event on .btn-block", function() {
it("should trigger a 'block' conversation model event", function() {
var buttonBlock = view.getDOMNode().querySelector(".btn-block");
TestUtils.Simulate.click(buttonBlock);
sinon.assert.calledOnce(model.trigger);
sinon.assert.calledWith(model.trigger, "declineAndBlock");
});
});
});
});

View File

@ -229,7 +229,7 @@ describe("loop.panel", function() {
beforeEach(function() {
callUrlData = {
call_url: "http://call.invalid/",
call_url: "http://call.invalid/fakeToken",
expiresAt: 1000
};
@ -303,6 +303,12 @@ describe("loop.panel", function() {
sinon.assert.calledWithExactly(notifier.errorL10n,
"unable_retrieve_url");
});
it("should set 'loopToken' with the callUrl token", function() {
sinon.assert.calledOnce(navigator.mozLoop.setLoopCharPref);
sinon.assert.calledWithExactly(navigator.mozLoop.setLoopCharPref,
"loopToken", "fakeToken");
});
});
});

View File

@ -4,10 +4,51 @@
# 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/.
DIRS += ['public', 'src']
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
XPCSHELL_TESTS_MANIFESTS += [
'tests/unit/xpcshell.ini',
JAR_MANIFESTS += ['jar.mn']
XPIDL_SOURCES += [
'nsIBrowserProfileMigrator.idl',
]
JAR_MANIFESTS += ['jar.mn']
XPIDL_MODULE = 'migration'
if CONFIG['OS_ARCH'] == 'WINNT':
SOURCES += [
'nsIEHistoryEnumerator.cpp',
]
EXTRA_COMPONENTS += [
'FirefoxProfileMigrator.js',
'ProfileMigrator.js',
]
if CONFIG['OS_ARCH'] == 'WINNT':
EXTRA_COMPONENTS += [
'IEProfileMigrator.js',
]
DEFINES['HAS_IE_MIGRATOR'] = True
EXTRA_PP_COMPONENTS += [
'BrowserProfileMigrators.manifest',
'ChromeProfileMigrator.js',
]
if CONFIG['OS_ARCH'] == 'WINNT':
EXTRA_PP_COMPONENTS += [
'SafariProfileMigrator.js',
]
DEFINES['HAS_SAFARI_MIGRATOR'] = True
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
EXTRA_PP_COMPONENTS += [
'SafariProfileMigrator.js',
]
DEFINES['HAS_SAFARI_MIGRATOR'] = True
EXTRA_PP_JS_MODULES += [
'MigrationUtils.jsm',
]
FINAL_LIBRARY = 'browsercomps'

View File

@ -1,12 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
XPIDL_SOURCES += [
'nsIBrowserProfileMigrator.idl',
]
XPIDL_MODULE = 'migration'

View File

@ -1,44 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
if CONFIG['OS_ARCH'] == 'WINNT':
SOURCES += [
'nsIEHistoryEnumerator.cpp',
]
EXTRA_COMPONENTS += [
'FirefoxProfileMigrator.js',
'ProfileMigrator.js',
]
if CONFIG['OS_ARCH'] == 'WINNT':
EXTRA_COMPONENTS += [
'IEProfileMigrator.js',
]
DEFINES['HAS_IE_MIGRATOR'] = True
EXTRA_PP_COMPONENTS += [
'BrowserProfileMigrators.manifest',
'ChromeProfileMigrator.js',
]
if CONFIG['OS_ARCH'] == 'WINNT':
EXTRA_PP_COMPONENTS += [
'SafariProfileMigrator.js',
]
DEFINES['HAS_SAFARI_MIGRATOR'] = True
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
EXTRA_PP_COMPONENTS += [
'SafariProfileMigrator.js',
]
DEFINES['HAS_SAFARI_MIGRATOR'] = True
EXTRA_PP_JS_MODULES += [
'MigrationUtils.jsm',
]
FINAL_LIBRARY = 'browsercomps'

View File

@ -4,18 +4,17 @@
# 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/.
DIRS += ['src']
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
XPCSHELL_TESTS_MANIFESTS += [
'tests/unit/xpcshell.ini',
JAR_MANIFESTS += ['jar.mn']
EXTRA_COMPONENTS += [
'BrowserPlaces.manifest',
'PlacesProtocolHandler.js',
]
MOCHITEST_CHROME_MANIFESTS += [
'tests/chrome/chrome.ini'
EXTRA_PP_JS_MODULES += [
'PlacesUIUtils.jsm',
]
BROWSER_CHROME_MANIFESTS += [
'tests/browser/browser.ini',
]
JAR_MANIFESTS += ['jar.mn']

View File

@ -1,15 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXTRA_COMPONENTS += [
'BrowserPlaces.manifest',
'PlacesProtocolHandler.js',
]
EXTRA_PP_JS_MODULES += [
'PlacesUIUtils.jsm',
]

View File

@ -4,7 +4,10 @@
# 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/.
DIRS += ['src']
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
JAR_MANIFESTS += ['jar.mn']
XPIDL_SOURCES += [
'nsISessionStartup.idl',
@ -13,12 +16,38 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'sessionstore'
XPCSHELL_TESTS_MANIFESTS += [
'test/unit/xpcshell.ini',
EXTRA_COMPONENTS += [
'nsSessionStartup.js',
'nsSessionStore.js',
'nsSessionStore.manifest',
]
BROWSER_CHROME_MANIFESTS += [
'test/browser.ini',
JS_MODULES_PATH = 'modules/sessionstore'
EXTRA_JS_MODULES = [
'ContentRestore.jsm',
'DocShellCapabilities.jsm',
'FrameTree.jsm',
'GlobalState.jsm',
'PageStyle.jsm',
'PrivacyFilter.jsm',
'PrivacyLevel.jsm',
'RecentlyClosedTabsAndWindowsMenuUtils.jsm',
'SessionCookies.jsm',
'SessionFile.jsm',
'SessionHistory.jsm',
'SessionMigration.jsm',
'SessionStorage.jsm',
'SessionWorker.js',
'SessionWorker.jsm',
'TabAttributes.jsm',
'TabState.jsm',
'TabStateCache.jsm',
'Utils.jsm',
]
EXTRA_PP_JS_MODULES += [
'SessionSaver.jsm',
'SessionStore.jsm',
]
JAR_MANIFESTS += ['jar.mn']

Some files were not shown because too many files have changed in this diff Show More