mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Merge m-c to inbound a=merge
This commit is contained in:
commit
d947cf32a0
1
.hgtags
1
.hgtags
@ -104,3 +104,4 @@ cfde3603b0206e119abea76fdd6e134b634348f1 FIREFOX_AURORA_31_BASE
|
||||
16f3cac5e8fe471e12f76d6a94a477b14e78df7c FIREFOX_AURORA_32_BASE
|
||||
dc23164ba2a289a8b22902e30990c77d9677c214 FIREFOX_AURORA_33_BASE
|
||||
c360f3d1c00d73b0c1fb0a2c0da525cb55e58b83 FIREFOX_AURORA_34_BASE
|
||||
cec1a116c4f9a3e887d52e9a26e8bbec200fe162 FIREFOX_AURORA_35_BASE
|
||||
|
2
CLOBBER
2
CLOBBER
@ -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 1080922 - Removal of a test manifest that the build system isn't picking up.
|
||||
Merge day clobber
|
@ -5,7 +5,7 @@ support-files =
|
||||
event/**
|
||||
fixtures/**
|
||||
loader/**
|
||||
libs/**
|
||||
lib/**
|
||||
modules/**
|
||||
private-browsing/**
|
||||
sidebar/**
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -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="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
@ -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="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
|
||||
@ -134,7 +134,7 @@
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d259117b4976decbe2f76eeed85218bf0109190f"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9f28c4faea3b2f01db227b2467b08aeba96d9bec"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
|
||||
<project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
|
||||
</manifest>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -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="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
@ -151,7 +151,7 @@
|
||||
<project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
|
||||
<project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
|
||||
<project name="platform/system/core" path="system/core" revision="350eac5403124dacb2a5fd9e28ac290a59fc3b8e"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
|
||||
<project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/>
|
||||
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/>
|
||||
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="7704e16da545f4207812e593743d6743e1afb9c5"/>
|
||||
|
@ -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="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
|
||||
@ -145,7 +145,7 @@
|
||||
<project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
|
||||
<project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
|
||||
<project name="platform/system/core" path="system/core" revision="adc485d8755af6a61641d197de7cfef667722580"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
|
||||
<project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
|
||||
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
|
||||
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "69b4d72a6b80008de044e535d9ff785631bd7f2b",
|
||||
"revision": "291b607f32e6173d8fe225c644cc7397cdf82fa5",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -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="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -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="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -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="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
|
||||
@ -129,7 +129,7 @@
|
||||
<project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
|
||||
<project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
||||
<project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>
|
||||
|
@ -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="2a536e4df82410178d8440cc710d8f838a95a0b9"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -5,7 +5,7 @@
|
||||
MOZ_APP_BASENAME=B2G
|
||||
MOZ_APP_VENDOR=Mozilla
|
||||
|
||||
MOZ_APP_VERSION=35.0a1
|
||||
MOZ_APP_VERSION=36.0a1
|
||||
MOZ_APP_UA_NAME=Firefox
|
||||
|
||||
MOZ_UA_OS_AGNOSTIC=1
|
||||
|
@ -1552,7 +1552,7 @@ 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");
|
||||
pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v2/links/fetch/%LOCALE%");
|
||||
|
||||
// endpoint to send newtab click and view pings
|
||||
pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v2/links/");
|
||||
|
@ -61,6 +61,10 @@ input[type=button] {
|
||||
right: auto;
|
||||
}
|
||||
|
||||
#newtab-scrollbox[page-disabled] #newtab-intro-what {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#newtab-intro-panel {
|
||||
color: #6a7b86;
|
||||
font-size: 15px;
|
||||
|
@ -391,7 +391,8 @@ loop.conversation = (function(mozL10n) {
|
||||
if (progressData.state !== "terminated")
|
||||
return;
|
||||
|
||||
if (progressData.reason === "cancel") {
|
||||
if (progressData.reason === "cancel" ||
|
||||
progressData.reason === "closed") {
|
||||
this._abortIncomingCall();
|
||||
return;
|
||||
}
|
||||
|
@ -391,7 +391,8 @@ loop.conversation = (function(mozL10n) {
|
||||
if (progressData.state !== "terminated")
|
||||
return;
|
||||
|
||||
if (progressData.reason === "cancel") {
|
||||
if (progressData.reason === "cancel" ||
|
||||
progressData.reason === "closed") {
|
||||
this._abortIncomingCall();
|
||||
return;
|
||||
}
|
||||
|
@ -23,6 +23,9 @@ body,
|
||||
background: #fff;
|
||||
border: 1px solid #E7E7E7;
|
||||
box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.03);
|
||||
background-image: url("../shared/img/beta-ribbon.svg#beta-ribbon");
|
||||
background-size: 5rem 5rem;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.header-box {
|
||||
|
@ -283,7 +283,11 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var callState = mozL10n.get("call_progress_" + this.state.callState + "_description");
|
||||
var callStateStringEntityName = "call_progress_" + this.state.callState + "_description";
|
||||
var callState = mozL10n.get(callStateStringEntityName);
|
||||
document.title = mozL10n.get("standalone_title_with_status",
|
||||
{clientShortname: mozL10n.get("clientShortname2"),
|
||||
currentStatus: mozL10n.get(callStateStringEntityName)});
|
||||
return (
|
||||
React.DOM.div({className: "container"},
|
||||
React.DOM.div({className: "container-box"},
|
||||
@ -519,6 +523,9 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
},
|
||||
|
||||
render: function() {
|
||||
document.title = mozL10n.get("standalone_title_with_status",
|
||||
{clientShortname: mozL10n.get("clientShortname2"),
|
||||
currentStatus: mozL10n.get("status_conversation_ended")});
|
||||
return (
|
||||
React.DOM.div({className: "ended-conversation"},
|
||||
sharedViews.FeedbackView({
|
||||
@ -539,6 +546,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
|
||||
var StartConversationView = React.createClass({displayName: 'StartConversationView',
|
||||
render: function() {
|
||||
document.title = mozL10n.get("clientShortname2");
|
||||
return this.transferPropsTo(
|
||||
InitiateConversationView({
|
||||
title: mozL10n.get("initiate_call_button_label2"),
|
||||
@ -549,6 +557,9 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
|
||||
var FailedConversationView = React.createClass({displayName: 'FailedConversationView',
|
||||
render: function() {
|
||||
document.title = mozL10n.get("standalone_title_with_status",
|
||||
{clientShortname: mozL10n.get("clientShortname2"),
|
||||
currentStatus: mozL10n.get("status_error")});
|
||||
return this.transferPropsTo(
|
||||
InitiateConversationView({
|
||||
title: mozL10n.get("call_failed_title"),
|
||||
@ -636,6 +647,9 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
return PendingConversationView({websocket: this._websocket});
|
||||
}
|
||||
case "connected": {
|
||||
document.title = mozL10n.get("standalone_title_with_status",
|
||||
{clientShortname: mozL10n.get("clientShortname2"),
|
||||
currentStatus: mozL10n.get("status_in_conversation")});
|
||||
return (
|
||||
sharedViews.ConversationView({
|
||||
initiate: true,
|
||||
|
@ -283,7 +283,11 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var callState = mozL10n.get("call_progress_" + this.state.callState + "_description");
|
||||
var callStateStringEntityName = "call_progress_" + this.state.callState + "_description";
|
||||
var callState = mozL10n.get(callStateStringEntityName);
|
||||
document.title = mozL10n.get("standalone_title_with_status",
|
||||
{clientShortname: mozL10n.get("clientShortname2"),
|
||||
currentStatus: mozL10n.get(callStateStringEntityName)});
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="container-box">
|
||||
@ -519,6 +523,9 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
},
|
||||
|
||||
render: function() {
|
||||
document.title = mozL10n.get("standalone_title_with_status",
|
||||
{clientShortname: mozL10n.get("clientShortname2"),
|
||||
currentStatus: mozL10n.get("status_conversation_ended")});
|
||||
return (
|
||||
<div className="ended-conversation">
|
||||
<sharedViews.FeedbackView
|
||||
@ -539,6 +546,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
|
||||
var StartConversationView = React.createClass({
|
||||
render: function() {
|
||||
document.title = mozL10n.get("clientShortname2");
|
||||
return this.transferPropsTo(
|
||||
<InitiateConversationView
|
||||
title={mozL10n.get("initiate_call_button_label2")}
|
||||
@ -549,6 +557,9 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
|
||||
var FailedConversationView = React.createClass({
|
||||
render: function() {
|
||||
document.title = mozL10n.get("standalone_title_with_status",
|
||||
{clientShortname: mozL10n.get("clientShortname2"),
|
||||
currentStatus: mozL10n.get("status_error")});
|
||||
return this.transferPropsTo(
|
||||
<InitiateConversationView
|
||||
title={mozL10n.get("call_failed_title")}
|
||||
@ -636,6 +647,9 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
return <PendingConversationView websocket={this._websocket} />;
|
||||
}
|
||||
case "connected": {
|
||||
document.title = mozL10n.get("standalone_title_with_status",
|
||||
{clientShortname: mozL10n.get("clientShortname2"),
|
||||
currentStatus: mozL10n.get("status_in_conversation")});
|
||||
return (
|
||||
<sharedViews.ConversationView
|
||||
initiate={true}
|
||||
|
@ -119,3 +119,12 @@ rooms_room_join_label=Join the conversation
|
||||
brand_website=https://www.mozilla.org/firefox/
|
||||
privacy_website=https://www.mozilla.org/privacy/
|
||||
legal_website=/legal/terms/
|
||||
|
||||
## LOCALIZATION_NOTE(standalone_title_with_status): {{clientShortname}} will be
|
||||
## replaced by the brand name and {{currentStatus}} will be replaced
|
||||
## by the current call status (Connecting, Ringing, etc.)
|
||||
standalone_title_with_status={{clientShortname}} — {{currentStatus}}
|
||||
status_in_conversation=In conversation
|
||||
status_conversation_ended=Conversation ended
|
||||
status_error=Something went wrong
|
||||
|
||||
|
@ -406,6 +406,46 @@ describe("loop.conversation", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("progress - terminated - closed", function() {
|
||||
it("should stop alerting", function(done) {
|
||||
promise.then(function() {
|
||||
icView._websocket.trigger("progress", {
|
||||
state: "terminated",
|
||||
reason: "closed"
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(navigator.mozLoop.stopAlerting);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should close the websocket", function(done) {
|
||||
promise.then(function() {
|
||||
icView._websocket.trigger("progress", {
|
||||
state: "terminated",
|
||||
reason: "closed"
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(icView._websocket.close);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should close the window", function(done) {
|
||||
promise.then(function() {
|
||||
icView._websocket.trigger("progress", {
|
||||
state: "terminated",
|
||||
reason: "closed"
|
||||
});
|
||||
|
||||
sandbox.clock.tick(1);
|
||||
|
||||
sinon.assert.calledOnce(window.close);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("progress - terminated - timeout (previousState = alerting)", function() {
|
||||
it("should stop alerting", function(done) {
|
||||
promise.then(function() {
|
||||
|
@ -1,45 +0,0 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["RevivableWindows"];
|
||||
|
||||
// List of closed windows that we can revive when closing
|
||||
// windows in succession until the browser quits.
|
||||
let closedWindows = [];
|
||||
|
||||
/**
|
||||
* This module keeps track of closed windows that are revivable. On Windows
|
||||
* and Linux we can revive windows before saving to disk - i.e. moving them
|
||||
* from state._closedWindows[] to state.windows[] so that they're opened
|
||||
* automatically on next startup. This feature lets us properly support
|
||||
* closing windows in succession until the browser quits.
|
||||
*
|
||||
* The length of the list is not capped by max_undo_windows unlike
|
||||
* state._closedWindows[].
|
||||
*/
|
||||
this.RevivableWindows = Object.freeze({
|
||||
// Returns whether there are windows to revive.
|
||||
get isEmpty() {
|
||||
return closedWindows.length == 0;
|
||||
},
|
||||
|
||||
// Add a window to the list.
|
||||
add(winState) {
|
||||
#ifndef XP_MACOSX
|
||||
closedWindows.push(winState);
|
||||
#endif
|
||||
},
|
||||
|
||||
// Get the list of revivable windows.
|
||||
get() {
|
||||
return [...closedWindows];
|
||||
},
|
||||
|
||||
// Clear the list of revivable windows.
|
||||
clear() {
|
||||
closedWindows.length = 0;
|
||||
}
|
||||
});
|
@ -19,8 +19,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
"resource://gre/modules/devtools/Console.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivacyFilter",
|
||||
"resource:///modules/sessionstore/PrivacyFilter.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RevivableWindows",
|
||||
"resource:///modules/sessionstore/RevivableWindows.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
|
||||
"resource:///modules/sessionstore/SessionStore.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SessionFile",
|
||||
@ -207,24 +205,23 @@ let SessionSaverInternal = {
|
||||
delete state.deferredInitialState;
|
||||
}
|
||||
|
||||
// We want to revive closed windows that have been closed in succession
|
||||
// without any user action in between closing those. This happens here in
|
||||
// the SessionSaver because we only want to revive when saving to disk.
|
||||
// On Mac OS X this list will always be empty.
|
||||
let windowsToRevive = RevivableWindows.get();
|
||||
state.windows.unshift(...windowsToRevive);
|
||||
let revivedWindows = state._closedWindows.splice(0, windowsToRevive.length);
|
||||
#ifdef DEBUG
|
||||
// Check that the windows to revive equal the windows
|
||||
// that we removed from the list of closed windows.
|
||||
let match = revivedWindows.every((win, idx) => {
|
||||
return win == windowsToRevive[windowsToRevive.length - 1 - idx];
|
||||
});
|
||||
#ifndef XP_MACOSX
|
||||
// We want to restore closed windows that are marked with _shouldRestore.
|
||||
// We're doing this here because we want to control this only when saving
|
||||
// the file.
|
||||
while (state._closedWindows.length) {
|
||||
let i = state._closedWindows.length - 1;
|
||||
|
||||
if (!match) {
|
||||
throw new Error("SessionStore: revived windows didn't match closed windows");
|
||||
if (!state._closedWindows[i]._shouldRestore) {
|
||||
// We only need to go until _shouldRestore
|
||||
// is falsy since we're going in reverse.
|
||||
break;
|
||||
}
|
||||
|
||||
delete state._closedWindows[i]._shouldRestore;
|
||||
state.windows.unshift(state._closedWindows.pop());
|
||||
}
|
||||
#endif DEBUG
|
||||
#endif
|
||||
|
||||
stopWatchFinish("COLLECT_DATA_MS", "COLLECT_DATA_LONGEST_OP_MS");
|
||||
return this._writeState(state);
|
||||
|
@ -107,8 +107,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "GlobalState",
|
||||
"resource:///modules/sessionstore/GlobalState.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivacyFilter",
|
||||
"resource:///modules/sessionstore/PrivacyFilter.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RevivableWindows",
|
||||
"resource:///modules/sessionstore/RevivableWindows.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RunState",
|
||||
"resource:///modules/sessionstore/RunState.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ScratchpadManager",
|
||||
@ -703,9 +701,7 @@ let SessionStoreInternal = {
|
||||
this.saveStateDelayed(win);
|
||||
break;
|
||||
}
|
||||
|
||||
// Any event handled here indicates a user action.
|
||||
RevivableWindows.clear();
|
||||
this._clearRestoringWindows();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1017,6 +1013,12 @@ let SessionStoreInternal = {
|
||||
SessionCookies.update([winData]);
|
||||
}
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
// Until we decide otherwise elsewhere, this window is part of a series
|
||||
// of closing windows to quit.
|
||||
winData._shouldRestore = true;
|
||||
#endif
|
||||
|
||||
// Store the window's close date to figure out when each individual tab
|
||||
// was closed. This timestamp should allow re-arranging data based on how
|
||||
// recently something was closed.
|
||||
@ -1037,8 +1039,9 @@ let SessionStoreInternal = {
|
||||
// with tabs we deem not worth saving then we might end up with a
|
||||
// random closed or even a pop-up window re-opened. To prevent that
|
||||
// we explicitly allow saving an "empty" window state.
|
||||
let numOpenWindows = Object.keys(this._windows).length;
|
||||
let isLastWindow = numOpenWindows == 1 && RevivableWindows.isEmpty;
|
||||
let isLastWindow =
|
||||
Object.keys(this._windows).length == 1 &&
|
||||
!this._closedWindows.some(win => win._shouldRestore || false);
|
||||
|
||||
if (hasSaveableTabs || isLastWindow) {
|
||||
// we don't want to save the busy state
|
||||
@ -1047,10 +1050,6 @@ let SessionStoreInternal = {
|
||||
this._closedWindows.unshift(winData);
|
||||
this._capClosedWindows();
|
||||
}
|
||||
|
||||
// Until we decide otherwise elsewhere, this window
|
||||
// is part of a series of closing windows to quit.
|
||||
RevivableWindows.add(winData);
|
||||
}
|
||||
|
||||
// clear this window from the list
|
||||
@ -1156,11 +1155,8 @@ let SessionStoreInternal = {
|
||||
delete this._windows[ix];
|
||||
}
|
||||
}
|
||||
|
||||
// also clear all data about closed windows
|
||||
this._closedWindows = [];
|
||||
RevivableWindows.clear();
|
||||
|
||||
// give the tabbrowsers a chance to clear their histories first
|
||||
var win = this._getMostRecentBrowserWindow();
|
||||
if (win) {
|
||||
@ -1168,6 +1164,8 @@ let SessionStoreInternal = {
|
||||
} else if (RunState.isRunning) {
|
||||
SessionSaver.run();
|
||||
}
|
||||
|
||||
this._clearRestoringWindows();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1221,12 +1219,11 @@ let SessionStoreInternal = {
|
||||
}
|
||||
}
|
||||
|
||||
// Purging domain data indicates a user action.
|
||||
RevivableWindows.clear();
|
||||
|
||||
if (RunState.isRunning) {
|
||||
SessionSaver.run();
|
||||
}
|
||||
|
||||
this._clearRestoringWindows();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -3349,6 +3346,21 @@ let SessionStoreInternal = {
|
||||
this._closedWindows.splice(spliceTo, this._closedWindows.length);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears the set of windows that are "resurrected" before writing to disk to
|
||||
* make closing windows one after the other until shutdown work as expected.
|
||||
*
|
||||
* This function should only be called when we are sure that there has been
|
||||
* a user action that indicates the browser is actively being used and all
|
||||
* windows that have been closed before are not part of a series of closing
|
||||
* windows.
|
||||
*/
|
||||
_clearRestoringWindows: function ssi_clearRestoringWindows() {
|
||||
for (let i = 0; i < this._closedWindows.length; i++) {
|
||||
delete this._closedWindows[i]._shouldRestore;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset state to prepare for a new session state to be restored.
|
||||
*/
|
||||
|
@ -46,7 +46,6 @@ EXTRA_JS_MODULES.sessionstore = [
|
||||
]
|
||||
|
||||
EXTRA_PP_JS_MODULES.sessionstore += [
|
||||
'RevivableWindows.jsm',
|
||||
'SessionSaver.jsm',
|
||||
'SessionStore.jsm',
|
||||
]
|
||||
|
@ -81,7 +81,6 @@ skip-if = buildapp == 'mulet'
|
||||
[browser_merge_closed_tabs.js]
|
||||
[browser_pageStyle.js]
|
||||
[browser_privatetabs.js]
|
||||
[browser_revive_windows.js]
|
||||
[browser_scrollPositions.js]
|
||||
[browser_sessionHistory.js]
|
||||
skip-if = e10s
|
||||
|
@ -1,160 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const IS_MAC = ("nsILocalFileMac" in Ci);
|
||||
const URL_PREFIX = "about:mozilla?t=browser_revive_windows&r=";
|
||||
const PREF_MAX_UNDO = "browser.sessionstore.max_windows_undo";
|
||||
|
||||
const URL_MAIN_WINDOW = URL_PREFIX + Math.random();
|
||||
const URL_ADD_WINDOW1 = URL_PREFIX + Math.random();
|
||||
const URL_ADD_WINDOW2 = URL_PREFIX + Math.random();
|
||||
const URL_CLOSED_WINDOW = URL_PREFIX + Math.random();
|
||||
|
||||
add_task(function* setup() {
|
||||
registerCleanupFunction(() => Services.prefs.clearUserPref(PREF_MAX_UNDO));
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensure that when closing windows in succession until the browser
|
||||
* quits we are able to revive more windows than we keep around for the
|
||||
* "Undo Close Window" feature.
|
||||
*/
|
||||
add_task(function* test_revive_windows() {
|
||||
// We can restore a single window max.
|
||||
Services.prefs.setIntPref(PREF_MAX_UNDO, 1);
|
||||
|
||||
// Clear list of closed windows.
|
||||
forgetClosedWindows();
|
||||
|
||||
let windows = [];
|
||||
|
||||
// Create three windows.
|
||||
for (let i = 0; i < 3; i++) {
|
||||
let win = yield promiseNewWindow();
|
||||
windows.push(win);
|
||||
|
||||
let tab = win.gBrowser.addTab("about:mozilla");
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
}
|
||||
|
||||
// Create a private window.
|
||||
// This window must not be revived.
|
||||
{
|
||||
let win = yield promiseNewWindow({private: true});
|
||||
windows.push(win);
|
||||
|
||||
let tab = win.gBrowser.addTab("about:mozilla");
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
}
|
||||
|
||||
// Close all windows.
|
||||
for (let win of windows) {
|
||||
yield promiseWindowClosed(win);
|
||||
}
|
||||
|
||||
is(ss.getClosedWindowCount(), 1, "one window restorable");
|
||||
|
||||
// Save to disk and read.
|
||||
let state = JSON.parse(yield promiseRecoveryFileContents());
|
||||
|
||||
// Check number of windows.
|
||||
if (IS_MAC) {
|
||||
is(state.windows.length, 1, "one open window");
|
||||
is(state._closedWindows.length, 1, "one closed window");
|
||||
} else {
|
||||
is(state.windows.length, 4, "four open windows");
|
||||
is(state._closedWindows.length, 0, "closed windows");
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures that when closing windows one after the other until the
|
||||
* browser shuts down (on Windows and Linux) we revive closed windows in the
|
||||
* right order.
|
||||
*/
|
||||
add_task(function* test_revive_windows_order() {
|
||||
// We can restore up to three windows max.
|
||||
Services.prefs.setIntPref(PREF_MAX_UNDO, 3);
|
||||
|
||||
// Clear list of closed windows.
|
||||
forgetClosedWindows();
|
||||
|
||||
let tab = gBrowser.addTab(URL_MAIN_WINDOW);
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
TabState.flush(tab.linkedBrowser);
|
||||
registerCleanupFunction(() => gBrowser.removeTab(tab));
|
||||
|
||||
let win0 = yield promiseNewWindow();
|
||||
let tab0 = win0.gBrowser.addTab(URL_CLOSED_WINDOW);
|
||||
yield promiseBrowserLoaded(tab0.linkedBrowser);
|
||||
|
||||
yield promiseWindowClosed(win0);
|
||||
let data = ss.getClosedWindowData();
|
||||
ok(data.contains(URL_CLOSED_WINDOW), "window is restorable");
|
||||
|
||||
let win1 = yield promiseNewWindow();
|
||||
let tab1 = win1.gBrowser.addTab(URL_ADD_WINDOW1);
|
||||
yield promiseBrowserLoaded(tab1.linkedBrowser);
|
||||
|
||||
let win2 = yield promiseNewWindow();
|
||||
let tab2 = win2.gBrowser.addTab(URL_ADD_WINDOW2);
|
||||
yield promiseBrowserLoaded(tab2.linkedBrowser);
|
||||
|
||||
// Close both windows so that |win1| will be opened first and would be
|
||||
// behind |win2| that was closed later.
|
||||
yield promiseWindowClosed(win1);
|
||||
yield promiseWindowClosed(win2);
|
||||
|
||||
// Repeat the checks once.
|
||||
for (let i = 0; i < 2; i++) {
|
||||
info(`checking window data, iteration #${i}`);
|
||||
let contents = yield promiseRecoveryFileContents();
|
||||
let {windows, _closedWindows: closedWindows} = JSON.parse(contents);
|
||||
|
||||
if (IS_MAC) {
|
||||
// Check number of windows.
|
||||
is(windows.length, 1, "one open window");
|
||||
is(closedWindows.length, 3, "three closed windows");
|
||||
|
||||
// Check open window.
|
||||
ok(JSON.stringify(windows).contains(URL_MAIN_WINDOW),
|
||||
"open window is correct");
|
||||
|
||||
// Check closed windows.
|
||||
ok(JSON.stringify(closedWindows[0]).contains(URL_ADD_WINDOW2),
|
||||
"correct first additional window");
|
||||
ok(JSON.stringify(closedWindows[1]).contains(URL_ADD_WINDOW1),
|
||||
"correct second additional window");
|
||||
ok(JSON.stringify(closedWindows[2]).contains(URL_CLOSED_WINDOW),
|
||||
"correct main window");
|
||||
} else {
|
||||
// Check number of windows.
|
||||
is(windows.length, 3, "three open windows");
|
||||
is(closedWindows.length, 1, "one closed window");
|
||||
|
||||
// Check closed window.
|
||||
ok(JSON.stringify(closedWindows).contains(URL_CLOSED_WINDOW),
|
||||
"closed window is correct");
|
||||
|
||||
// Check that windows are in the right order.
|
||||
ok(JSON.stringify(windows[0]).contains(URL_ADD_WINDOW1),
|
||||
"correct first additional window");
|
||||
ok(JSON.stringify(windows[1]).contains(URL_ADD_WINDOW2),
|
||||
"correct second additional window");
|
||||
ok(JSON.stringify(windows[2]).contains(URL_MAIN_WINDOW),
|
||||
"correct main window");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function promiseNewWindow(opts = {private: false}) {
|
||||
return new Promise(resolve => whenNewWindowLoaded(opts, resolve));
|
||||
}
|
||||
|
||||
function forgetClosedWindows() {
|
||||
while (ss.getClosedWindowCount()) {
|
||||
ss.forgetClosedWindow(0);
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
35.0a1
|
||||
36.0a1
|
||||
|
@ -14,6 +14,7 @@ skip-if = true
|
||||
[browser_layoutview_update-after-navigation.js]
|
||||
[browser_layoutview_update-after-reload.js]
|
||||
[browser_layoutview_update-in-iframes.js]
|
||||
skip-if = true # Bug 1020038 layout-view updates for iframe elements changes
|
||||
[browser_editablemodel.js]
|
||||
# [browser_editablemodel_allproperties.js]
|
||||
# Disabled for too many intermittent failures (bug 1009322)
|
||||
|
@ -108,3 +108,8 @@ panic-button.tooltiptext = Forget about some browsing history
|
||||
|
||||
web-apps-button.label = Apps
|
||||
web-apps-button.tooltiptext = Discover Apps
|
||||
|
||||
# LOCALIZATION NOTE(devtools-webide-button.label, devtools-webide-button.tooltiptext):
|
||||
# widget is only visible after WebIDE has been started once (Tools > Web Developers > WebIDE)
|
||||
devtools-webide-button.label = WebIDE
|
||||
devtools-webide-button.tooltiptext = Open WebIDE
|
||||
|
@ -183,6 +183,9 @@ let DirectoryLinksProvider = {
|
||||
},
|
||||
|
||||
_fetchAndCacheLinks: function DirectoryLinksProvider_fetchAndCacheLinks(uri) {
|
||||
// Replace with the same display locale used for selecting links data
|
||||
uri = uri.replace("%LOCALE%", this.locale);
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let xmlHttp = new XMLHttpRequest();
|
||||
|
||||
@ -206,14 +209,12 @@ let DirectoryLinksProvider = {
|
||||
};
|
||||
|
||||
try {
|
||||
xmlHttp.open('POST', uri);
|
||||
xmlHttp.open("GET", uri);
|
||||
// Override the type so XHR doesn't complain about not well-formed XML
|
||||
xmlHttp.overrideMimeType(DIRECTORY_LINKS_TYPE);
|
||||
// Set the appropriate request type for servers that require correct types
|
||||
xmlHttp.setRequestHeader("Content-Type", DIRECTORY_LINKS_TYPE);
|
||||
xmlHttp.send(JSON.stringify({
|
||||
locale: this.locale,
|
||||
}));
|
||||
xmlHttp.send();
|
||||
} catch (e) {
|
||||
deferred.reject("Error fetching " + uri);
|
||||
Cu.reportError(e);
|
||||
|
@ -53,11 +53,11 @@ Services.prefs.setBoolPref(kNewtabEnhancedPref, true);
|
||||
const kHttpHandlerData = {};
|
||||
kHttpHandlerData[kExamplePath] = {"en-US": [{"url":"http://example.com","title":"RemoteSource"}]};
|
||||
|
||||
const expectedBodyObject = {locale: DirectoryLinksProvider.locale};
|
||||
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
|
||||
"nsIBinaryInputStream",
|
||||
"setInputStream");
|
||||
|
||||
let gLastRequestPath;
|
||||
function getHttpHandler(path) {
|
||||
let code = 200;
|
||||
let body = JSON.stringify(kHttpHandlerData[path]);
|
||||
@ -65,10 +65,7 @@ function getHttpHandler(path) {
|
||||
code = 204;
|
||||
}
|
||||
return function(aRequest, aResponse) {
|
||||
let bodyStream = new BinaryInputStream(aRequest.bodyInputStream);
|
||||
let bodyObject = JSON.parse(NetUtil.readInputStreamToString(bodyStream, bodyStream.available()));
|
||||
isIdentical(bodyObject, expectedBodyObject);
|
||||
|
||||
gLastRequestPath = aRequest.path;
|
||||
aResponse.setStatusLine(null, code);
|
||||
aResponse.setHeader("Content-Type", "application/json");
|
||||
aResponse.write(body);
|
||||
@ -131,7 +128,9 @@ function promiseDirectoryDownloadOnPrefChange(pref, newValue) {
|
||||
let observer = new LinksChangeObserver();
|
||||
DirectoryLinksProvider.addObserver(observer);
|
||||
Services.prefs.setCharPref(pref, newValue);
|
||||
return observer.deferred.promise;
|
||||
return observer.deferred.promise.then(() => {
|
||||
DirectoryLinksProvider.removeObserver(observer);
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
@ -296,7 +295,8 @@ add_task(function test_fetchAndCacheLinks_remote() {
|
||||
yield DirectoryLinksProvider.init();
|
||||
yield cleanJsonFile();
|
||||
// this must trigger directory links json download and save it to cache file
|
||||
yield DirectoryLinksProvider._fetchAndCacheLinks(kExampleURL);
|
||||
yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, kExampleURL + "%LOCALE%");
|
||||
do_check_eq(gLastRequestPath, kExamplePath + "en-US");
|
||||
let data = yield readJsonFile();
|
||||
isIdentical(data, kHttpHandlerData[kExamplePath]);
|
||||
});
|
||||
@ -336,7 +336,8 @@ add_task(function test_fetchAndCacheLinks_unknownHost() {
|
||||
add_task(function test_fetchAndCacheLinks_non200Status() {
|
||||
yield DirectoryLinksProvider.init();
|
||||
yield cleanJsonFile();
|
||||
yield DirectoryLinksProvider._fetchAndCacheLinks(kFailURL);
|
||||
yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, kFailURL);
|
||||
do_check_eq(gLastRequestPath, kFailPath);
|
||||
let data = yield readJsonFile();
|
||||
isIdentical(data, {});
|
||||
});
|
||||
@ -508,6 +509,7 @@ add_task(function test_DirectoryLinksProvider_fetchDirectoryOnPrefChange() {
|
||||
yield promiseDirectoryDownloadOnPrefChange(kSourceUrlPref, kExampleURL);
|
||||
// then wait for testObserver to fire and test that json is downloaded
|
||||
yield testObserver.deferred.promise;
|
||||
do_check_eq(gLastRequestPath, kExamplePath);
|
||||
let data = yield readJsonFile();
|
||||
isIdentical(data, kHttpHandlerData[kExamplePath]);
|
||||
|
||||
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
35.0a1
|
||||
36.0a1
|
||||
|
@ -950,6 +950,11 @@ MobileConnectionService.prototype = {
|
||||
} catch (e) {}
|
||||
},
|
||||
|
||||
_broadcastCdmaInfoRecordSystemMessage: function(aMessage) {
|
||||
// TODO: Bug 1072808, Broadcast System Message with proxy.
|
||||
gSystemMessenger.broadcastMessage("cdma-info-rec-received", aMessage);
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIMobileConnectionService interface.
|
||||
*/
|
||||
@ -1167,6 +1172,111 @@ MobileConnectionService.prototype = {
|
||||
aServiceClass);
|
||||
},
|
||||
|
||||
notifyCdmaInfoRecDisplay: function(aClientId, aDisplay) {
|
||||
this._broadcastCdmaInfoRecordSystemMessage({
|
||||
clientId: aClientId,
|
||||
display: aDisplay
|
||||
});
|
||||
},
|
||||
|
||||
notifyCdmaInfoRecCalledPartyNumber: function(aClientId, aType, aPlan, aNumber,
|
||||
aPi, aSi) {
|
||||
this._broadcastCdmaInfoRecordSystemMessage({
|
||||
clientId: aClientId,
|
||||
calledNumber: {
|
||||
type: aType,
|
||||
plan: aPlan,
|
||||
number: aNumber,
|
||||
pi: aPi,
|
||||
si: aSi
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
notifyCdmaInfoRecCallingPartyNumber: function(aClientId, aType, aPlan, aNumber,
|
||||
aPi, aSi) {
|
||||
this._broadcastCdmaInfoRecordSystemMessage({
|
||||
clientId: aClientId,
|
||||
callingNumber: {
|
||||
type: aType,
|
||||
plan: aPlan,
|
||||
number: aNumber,
|
||||
pi: aPi,
|
||||
si: aSi
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
notifyCdmaInfoRecConnectedPartyNumber: function(aClientId, aType, aPlan, aNumber,
|
||||
aPi, aSi) {
|
||||
this._broadcastCdmaInfoRecordSystemMessage({
|
||||
clientId: aClientId,
|
||||
connectedNumber: {
|
||||
type: aType,
|
||||
plan: aPlan,
|
||||
number: aNumber,
|
||||
pi: aPi,
|
||||
si: aSi
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
notifyCdmaInfoRecSignal: function(aClientId, aType, aAlertPitch, aSignal){
|
||||
this._broadcastCdmaInfoRecordSystemMessage({
|
||||
clientId: aClientId,
|
||||
signal: {
|
||||
type: aType,
|
||||
alertPitch: aAlertPitch,
|
||||
signal: aSignal
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
notifyCdmaInfoRecRedirectingNumber: function(aClientId, aType, aPlan, aNumber,
|
||||
aPi, aSi, aReason) {
|
||||
this._broadcastCdmaInfoRecordSystemMessage({
|
||||
clientId: aClientId,
|
||||
redirect: {
|
||||
type: aType,
|
||||
plan: aPlan,
|
||||
number: aNumber,
|
||||
pi: aPi,
|
||||
si: aSi,
|
||||
reason: aReason
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
notifyCdmaInfoRecLineControl: function(aClientId, aPolarityIncluded, aToggle,
|
||||
aReverse, aPowerDenial) {
|
||||
this._broadcastCdmaInfoRecordSystemMessage({
|
||||
clientId: aClientId,
|
||||
lineControl: {
|
||||
polarityIncluded: aPolarityIncluded,
|
||||
toggle: aToggle,
|
||||
reverse: aReverse,
|
||||
powerDenial: aPowerDenial
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
notifyCdmaInfoRecClir: function(aClientId, aCause) {
|
||||
this._broadcastCdmaInfoRecordSystemMessage({
|
||||
clientId: aClientId,
|
||||
clirCause: aCause
|
||||
});
|
||||
},
|
||||
|
||||
notifyCdmaInfoRecAudioControl: function(aClientId, aUplink, aDownLink) {
|
||||
this._broadcastCdmaInfoRecordSystemMessage({
|
||||
clientId: aClientId,
|
||||
audioControl: {
|
||||
upLink: aUplink,
|
||||
downLink: aDownLink
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIObserver interface.
|
||||
*/
|
||||
|
@ -9,7 +9,7 @@
|
||||
"@mozilla.org/mobileconnection/gonkmobileconnectionservice;1"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(b0310517-e7f6-4fa5-a52e-fa6ff35c8fc1)]
|
||||
[scriptable, uuid(2d574f0e-4a02-11e4-b1b3-cbc14b7608ce)]
|
||||
interface nsIGonkMobileConnectionService : nsIMobileConnectionService
|
||||
{
|
||||
void notifyNetworkInfoChanged(in unsigned long clientId, in jsval networkInfo);
|
||||
@ -53,4 +53,205 @@ interface nsIGonkMobileConnectionService : nsIMobileConnectionService
|
||||
in DOMString number,
|
||||
in unsigned short timeSeconds,
|
||||
in unsigned short serviceClass);
|
||||
|
||||
/**
|
||||
* Notify Display Info from received Cdma-Info-Record.
|
||||
* See 3.7.4.1 Display in 3GPP2 C.S0005-F.
|
||||
*
|
||||
* @param clientId
|
||||
* The ID of radioInterface where this info is notified from.
|
||||
* @param display
|
||||
The string to be displayed.
|
||||
*/
|
||||
void notifyCdmaInfoRecDisplay(in unsigned long clientId,
|
||||
in DOMString display);
|
||||
|
||||
/**
|
||||
* Notify Called Party Number from received Cdma-Info-Record.
|
||||
* See 3.7.4.2 Called Party Number in 3GPP2 C.S0005-F.
|
||||
*
|
||||
* @param clientId
|
||||
* The ID of radioInterface where this info is notified from.
|
||||
* @param type
|
||||
* The type of number. (3-bit binary)
|
||||
* See Table 2.7.1.3.2.4-2 in 3GPP2 C.S0005-F.
|
||||
* @param plan
|
||||
* The numbering plan. (4-bit binary)
|
||||
* See Table 2.7.1.3.2.4-3 in 3GPP2 C.S0005-F.
|
||||
* @param number
|
||||
* The string presentation of the number.
|
||||
* @param pi (2-bit binary)
|
||||
* The Presentation indicator of the number.
|
||||
* See Table 2.7.4.4-1 in 3GPP2 C.S0005-F.
|
||||
* @param si (2-bit binary)
|
||||
* The Screening Indicator of the number.
|
||||
* See Table 2.7.4.4-2 in 3GPP2 C.S0005-F.
|
||||
*/
|
||||
void notifyCdmaInfoRecCalledPartyNumber(in unsigned long clientId,
|
||||
in unsigned short type,
|
||||
in unsigned short plan,
|
||||
in DOMString number,
|
||||
in unsigned short pi,
|
||||
in unsigned short si);
|
||||
|
||||
/**
|
||||
* Notify Calling Party Number from received Cdma-Info-Record.
|
||||
* See 3.7.4.3 Calling Party Number in 3GPP2 C.S0005-F.
|
||||
*
|
||||
* @param clientId
|
||||
* The ID of radioInterface where this info is notified from.
|
||||
* @param type
|
||||
* The type of number. (3-bit binary)
|
||||
* See Table 2.7.1.3.2.4-2 in 3GPP2 C.S0005-F.
|
||||
* @param plan
|
||||
* The numbering plan. (4-bit binary)
|
||||
* See Table 2.7.1.3.2.4-3 in 3GPP2 C.S0005-F.
|
||||
* @param number
|
||||
* The string presentation of the number.
|
||||
* @param pi (2-bit binary)
|
||||
* The Presentation indicator of the number.
|
||||
* See Table 2.7.4.4-1 in 3GPP2 C.S0005-F.
|
||||
* @param si (2-bit binary)
|
||||
* The Screening Indicator of the number.
|
||||
* See Table 2.7.4.4-2 in 3GPP2 C.S0005-F.
|
||||
*/
|
||||
void notifyCdmaInfoRecCallingPartyNumber(in unsigned long clientId,
|
||||
in unsigned short type,
|
||||
in unsigned short plan,
|
||||
in DOMString number,
|
||||
in unsigned short pi,
|
||||
in unsigned short si);
|
||||
|
||||
/**
|
||||
* Notify Connected Party Number from received Cdma-Info-Record.
|
||||
* See 3.7.4.4 Connected Party Number in 3GPP2 C.S0005-F.
|
||||
*
|
||||
* @param clientId
|
||||
* The ID of radioInterface where this info is notified from.
|
||||
* @param type
|
||||
* The type of number. (3-bit binary)
|
||||
* See Table 2.7.1.3.2.4-2 in 3GPP2 C.S0005-F.
|
||||
* @param plan
|
||||
* The numbering plan. (4-bit binary)
|
||||
* See Table 2.7.1.3.2.4-3 in 3GPP2 C.S0005-F.
|
||||
* @param number
|
||||
* The string presentation of the number.
|
||||
* @param pi (2-bit binary)
|
||||
* The Presentation indicator of the number.
|
||||
* See Table 2.7.4.4-1 in 3GPP2 C.S0005-F.
|
||||
* @param si (2-bit binary)
|
||||
* The Screening Indicator of the number.
|
||||
* See Table 2.7.4.4-2 in 3GPP2 C.S0005-F.
|
||||
*/
|
||||
void notifyCdmaInfoRecConnectedPartyNumber(in unsigned long clientId,
|
||||
in unsigned short type,
|
||||
in unsigned short plan,
|
||||
in DOMString number,
|
||||
in unsigned short pi,
|
||||
in unsigned short si);
|
||||
|
||||
/**
|
||||
* Notify Signal Info from received Cdma-Info-Record.
|
||||
* See 3.7.4.5 Signal in 3GPP2 C.S0005-F.
|
||||
*
|
||||
* @param clientId
|
||||
* The ID of radioInterface where this info is notified from.
|
||||
* @param type
|
||||
* The signal type. (2-bit binary)
|
||||
* See Table 3.7.5.5-1 in 3GPP2 C.S0005-F.
|
||||
* @param alertPitch
|
||||
* The pitch of the alerting signal. (2-bit binary)
|
||||
* See Table 3.7.5.5-2 in 3GPP2 C.S0005-F.
|
||||
* @param signal
|
||||
* The signal code. (6-bit binary)
|
||||
* See Table 3.7.5.5-3, 3.7.5.5-4, 3.7.5.5-5 in 3GPP2 C.S0005-F.
|
||||
*/
|
||||
void notifyCdmaInfoRecSignal(in unsigned long clientId,
|
||||
in unsigned short type,
|
||||
in unsigned short alertPitch,
|
||||
in unsigned short signal);
|
||||
|
||||
/**
|
||||
* Notify Redirecting Number from received Cdma-Info-Record.
|
||||
* See 3.7.4.11 Redirecting Number in 3GPP2 C.S0005-F.
|
||||
*
|
||||
* @param clientId
|
||||
* The ID of radioInterface where this info is notified from.
|
||||
* @param type
|
||||
* The type of number. (3-bit binary)
|
||||
* See Table 2.7.1.3.2.4-2 in 3GPP2 C.S0005-F.
|
||||
* @param plan
|
||||
* The numbering plan. (4-bit binary)
|
||||
* See Table 2.7.1.3.2.4-3 in 3GPP2 C.S0005-F.
|
||||
* @param number
|
||||
* The string presentation of the number.
|
||||
* @param pi (2-bit binary)
|
||||
* The Presentation indicator of the number.
|
||||
* See Table 2.7.4.4-1 in 3GPP2 C.S0005-F.
|
||||
* @param si (2-bit binary)
|
||||
* The Screening Indicator of the number.
|
||||
* See Table 2.7.4.4-2 in 3GPP2 C.S0005-F.
|
||||
* @param reason (4-bit binary)
|
||||
* The redirection reason.
|
||||
* See Table 3.7.5.11-1 in 3GPP2 C.S0005-F.
|
||||
*/
|
||||
void notifyCdmaInfoRecRedirectingNumber(in unsigned long clientId,
|
||||
in unsigned short type,
|
||||
in unsigned short plan,
|
||||
in DOMString number,
|
||||
in unsigned short pi,
|
||||
in unsigned short si,
|
||||
in unsigned short reason);
|
||||
|
||||
/**
|
||||
* Notify Line Control from received Cdma-Info-Record.
|
||||
* See 3.7.4.15 Line Control in 3GPP2 C.S0005-F.
|
||||
*
|
||||
* @param clientId
|
||||
* The ID of radioInterface where this info is notified from.
|
||||
* @param polarityIncluded (1-bit)
|
||||
* Polarity parameter included.
|
||||
* @param toggle (1-bit)
|
||||
* Toggle mode.
|
||||
* @param reverse (1-bit)
|
||||
* Reverse polarity.
|
||||
* @param powerDenial (8-bit)
|
||||
* Power denial timeout.
|
||||
*/
|
||||
void notifyCdmaInfoRecLineControl(in unsigned long clientId,
|
||||
in unsigned short polarityIncluded,
|
||||
in unsigned short toggle,
|
||||
in unsigned short reverse,
|
||||
in unsigned short powerDenial);
|
||||
|
||||
/**
|
||||
* Notify CLIR from received Cdma-Info-Record.
|
||||
* See 'ANNEX 1 Country-Specific Record Type for Japan' in T53.
|
||||
* http://www.arib.or.jp/english/html/overview/doc/T53v6_5_pdf/5_ANNEX_v6_5.pdf
|
||||
*
|
||||
* @param clientId
|
||||
* The ID of radioInterface where this info is notified from.
|
||||
* @param cause
|
||||
* Reason code. (8-bit binary)
|
||||
* See Table A 1.1-1 in T53.
|
||||
*/
|
||||
void notifyCdmaInfoRecClir(in unsigned long clientId,
|
||||
in unsigned short cause);
|
||||
|
||||
/**
|
||||
* Notify Audio Control from received Cdma-Info-Record.
|
||||
*
|
||||
* Note: No information from ARIB about Audio Control.
|
||||
* It seems obsolete according to ANNEX 1 in T53.
|
||||
* upLink/downLink are 'byte' value according to ril.h.
|
||||
* Treat them as 'signed short' to preserve the flexibility when needed.
|
||||
*
|
||||
* @param clientId
|
||||
* The ID of radioInterface where this info is notified from.
|
||||
* @param upLink
|
||||
* @param downLink
|
||||
*/
|
||||
void notifyCdmaInfoRecAudioControl(in unsigned long clientId,
|
||||
in short upLink,
|
||||
in short downLink);
|
||||
};
|
||||
|
@ -396,13 +396,6 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function() {
|
||||
}
|
||||
},
|
||||
|
||||
sendMobileConnectionMessage: function(message, clientId, data) {
|
||||
this._sendTargetMessage("mobileconnection", message, {
|
||||
clientId: clientId,
|
||||
data: data
|
||||
});
|
||||
},
|
||||
|
||||
sendIccMessage: function(message, clientId, data) {
|
||||
this._sendTargetMessage("icc", message, {
|
||||
clientId: clientId,
|
||||
@ -1163,7 +1156,7 @@ DataConnectionHandler.prototype = {
|
||||
_compareDataCallOptions: function(dataCall, newDataCall) {
|
||||
return dataCall.apnProfile.apn == newDataCall.apn &&
|
||||
dataCall.apnProfile.user == newDataCall.user &&
|
||||
dataCall.apnProfile.password == newDataCall.password &&
|
||||
dataCall.apnProfile.password == newDataCall.passwd &&
|
||||
dataCall.chappap == newDataCall.chappap &&
|
||||
dataCall.pdptype == newDataCall.pdptype;
|
||||
},
|
||||
@ -2091,8 +2084,7 @@ RadioInterface.prototype = {
|
||||
gMessageManager.sendIccMessage("RIL:StkSessionEnd", this.clientId, null);
|
||||
break;
|
||||
case "cdma-info-rec-received":
|
||||
if (DEBUG) this.debug("cdma-info-rec-received: " + JSON.stringify(message));
|
||||
gSystemMessenger.broadcastMessage("cdma-info-rec-received", message);
|
||||
this.handleCdmaInformationRecords(message.records);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Don't know about this message type: " +
|
||||
@ -2920,6 +2912,99 @@ RadioInterface.prototype = {
|
||||
hasEtwsInfo ? etwsInfo.popup : false);
|
||||
},
|
||||
|
||||
handleCdmaInformationRecords: function(aRecords) {
|
||||
if (DEBUG) this.debug("cdma-info-rec-received: " + JSON.stringify(aRecords));
|
||||
|
||||
let clientId = this.clientId;
|
||||
|
||||
aRecords.forEach(function(aRecord) {
|
||||
if (aRecord.display) {
|
||||
gMobileConnectionService
|
||||
.notifyCdmaInfoRecDisplay(clientId, aRecord.display);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRecord.calledNumber) {
|
||||
gMobileConnectionService
|
||||
.notifyCdmaInfoRecCalledPartyNumber(clientId,
|
||||
aRecord.calledNumber.type,
|
||||
aRecord.calledNumber.plan,
|
||||
aRecord.calledNumber.number,
|
||||
aRecord.calledNumber.pi,
|
||||
aRecord.calledNumber.si);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRecord.callingNumber) {
|
||||
gMobileConnectionService
|
||||
.notifyCdmaInfoRecCallingPartyNumber(clientId,
|
||||
aRecord.callingNumber.type,
|
||||
aRecord.callingNumber.plan,
|
||||
aRecord.callingNumber.number,
|
||||
aRecord.callingNumber.pi,
|
||||
aRecord.callingNumber.si);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRecord.connectedNumber) {
|
||||
gMobileConnectionService
|
||||
.notifyCdmaInfoRecConnectedPartyNumber(clientId,
|
||||
aRecord.connectedNumber.type,
|
||||
aRecord.connectedNumber.plan,
|
||||
aRecord.connectedNumber.number,
|
||||
aRecord.connectedNumber.pi,
|
||||
aRecord.connectedNumber.si);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRecord.signal) {
|
||||
gMobileConnectionService
|
||||
.notifyCdmaInfoRecSignal(clientId,
|
||||
aRecord.signal.type,
|
||||
aRecord.signal.alertPitch,
|
||||
aRecord.signal.signal);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRecord.redirect) {
|
||||
gMobileConnectionService
|
||||
.notifyCdmaInfoRecRedirectingNumber(clientId,
|
||||
aRecord.redirect.type,
|
||||
aRecord.redirect.plan,
|
||||
aRecord.redirect.number,
|
||||
aRecord.redirect.pi,
|
||||
aRecord.redirect.si,
|
||||
aRecord.redirect.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRecord.lineControl) {
|
||||
gMobileConnectionService
|
||||
.notifyCdmaInfoRecLineControl(clientId,
|
||||
aRecord.lineControl.polarityIncluded,
|
||||
aRecord.lineControl.toggle,
|
||||
aRecord.lineControl.reverse,
|
||||
aRecord.lineControl.powerDenial);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRecord.clirCause) {
|
||||
gMobileConnectionService
|
||||
.notifyCdmaInfoRecClir(clientId,
|
||||
aRecord.clirCause);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRecord.audioControl) {
|
||||
gMobileConnectionService
|
||||
.notifyCdmaInfoRecAudioControl(clientId,
|
||||
aRecord.audioControl.upLink,
|
||||
aRecord.audioControl.downLink);
|
||||
return;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
|
@ -6920,9 +6920,10 @@ RilObject.prototype[UNSOLICITED_CDMA_OTA_PROVISION_STATUS] = function UNSOLICITE
|
||||
status: status});
|
||||
};
|
||||
RilObject.prototype[UNSOLICITED_CDMA_INFO_REC] = function UNSOLICITED_CDMA_INFO_REC(length) {
|
||||
let record = this.context.CdmaPDUHelper.decodeInformationRecord();
|
||||
record.rilMessageType = "cdma-info-rec-received";
|
||||
this.sendChromeMessage(record);
|
||||
this.sendChromeMessage({
|
||||
rilMessageType: "cdma-info-rec-received",
|
||||
records: this.context.CdmaPDUHelper.decodeInformationRecord()
|
||||
});
|
||||
};
|
||||
RilObject.prototype[UNSOLICITED_OEM_HOOK_RAW] = null;
|
||||
RilObject.prototype[UNSOLICITED_RINGBACK_TONE] = null;
|
||||
@ -9987,11 +9988,13 @@ CdmaPDUHelperObject.prototype = {
|
||||
*/
|
||||
decodeInformationRecord: function() {
|
||||
let Buf = this.context.Buf;
|
||||
let record = {};
|
||||
let records = [];
|
||||
let numOfRecords = Buf.readInt32();
|
||||
|
||||
let type;
|
||||
let record;
|
||||
for (let i = 0; i < numOfRecords; i++) {
|
||||
record = {};
|
||||
type = Buf.readInt32();
|
||||
|
||||
switch (type) {
|
||||
@ -9999,6 +10002,7 @@ CdmaPDUHelperObject.prototype = {
|
||||
* Every type is encaped by ril, except extended display
|
||||
*/
|
||||
case PDU_CDMA_INFO_REC_TYPE_DISPLAY:
|
||||
case PDU_CDMA_INFO_REC_TYPE_EXTENDED_DISPLAY:
|
||||
record.display = Buf.readString();
|
||||
break;
|
||||
case PDU_CDMA_INFO_REC_TYPE_CALLED_PARTY_NUMBER:
|
||||
@ -10027,7 +10031,10 @@ CdmaPDUHelperObject.prototype = {
|
||||
break;
|
||||
case PDU_CDMA_INFO_REC_TYPE_SIGNAL:
|
||||
record.signal = {};
|
||||
record.signal.present = Buf.readInt32();
|
||||
if (!Buf.readInt32()) { // Non-zero if signal is present.
|
||||
Buf.seekIncoming(3 * Buf.UINT32_SIZE);
|
||||
continue;
|
||||
}
|
||||
record.signal.type = Buf.readInt32();
|
||||
record.signal.alertPitch = Buf.readInt32();
|
||||
record.signal.signal = Buf.readInt32();
|
||||
@ -10045,40 +10052,11 @@ CdmaPDUHelperObject.prototype = {
|
||||
record.lineControl = {};
|
||||
record.lineControl.polarityIncluded = Buf.readInt32();
|
||||
record.lineControl.toggle = Buf.readInt32();
|
||||
record.lineControl.recerse = Buf.readInt32();
|
||||
record.lineControl.reverse = Buf.readInt32();
|
||||
record.lineControl.powerDenial = Buf.readInt32();
|
||||
break;
|
||||
case PDU_CDMA_INFO_REC_TYPE_EXTENDED_DISPLAY:
|
||||
let length = Buf.readInt32();
|
||||
/*
|
||||
* Extended display is still in format defined in
|
||||
* C.S0005-F v1.0, 3.7.5.16
|
||||
*/
|
||||
record.extendedDisplay = {};
|
||||
|
||||
let headerByte = Buf.readInt32();
|
||||
length--;
|
||||
// Based on spec, headerByte must be 0x80 now
|
||||
record.extendedDisplay.indicator = (headerByte >> 7);
|
||||
record.extendedDisplay.type = (headerByte & 0x7F);
|
||||
record.extendedDisplay.records = [];
|
||||
|
||||
while (length > 0) {
|
||||
let display = {};
|
||||
|
||||
display.tag = Buf.readInt32();
|
||||
length--;
|
||||
if (display.tag !== INFO_REC_EXTENDED_DISPLAY_BLANK &&
|
||||
display.tag !== INFO_REC_EXTENDED_DISPLAY_SKIP) {
|
||||
display.content = Buf.readString();
|
||||
length -= (display.content.length + 1);
|
||||
}
|
||||
|
||||
record.extendedDisplay.records.push(display);
|
||||
}
|
||||
break;
|
||||
case PDU_CDMA_INFO_REC_TYPE_T53_CLIR:
|
||||
record.cause = Buf.readInt32();
|
||||
record.clirCause = Buf.readInt32();
|
||||
break;
|
||||
case PDU_CDMA_INFO_REC_TYPE_T53_AUDIO_CONTROL:
|
||||
record.audioControl = {};
|
||||
@ -10088,11 +10066,13 @@ CdmaPDUHelperObject.prototype = {
|
||||
case PDU_CDMA_INFO_REC_TYPE_T53_RELEASE:
|
||||
// Fall through
|
||||
default:
|
||||
throw new Error("UNSOLICITED_CDMA_INFO_REC(), Unsupported information record type " + record.type + "\n");
|
||||
throw new Error("UNSOLICITED_CDMA_INFO_REC(), Unsupported information record type " + type + "\n");
|
||||
}
|
||||
|
||||
records.push(record);
|
||||
}
|
||||
|
||||
return record;
|
||||
return records;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -36,6 +36,10 @@ function newWorkerWithParcel(parcelBuf) {
|
||||
return buf[index++];
|
||||
};
|
||||
|
||||
context.Buf.seekIncoming = function(offset) {
|
||||
index += offset / context.Buf.UINT32_SIZE;
|
||||
};
|
||||
|
||||
return worker;
|
||||
}
|
||||
|
||||
@ -53,9 +57,9 @@ add_test(function test_display() {
|
||||
0x6F, 0x00]);
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let helper = context.CdmaPDUHelper;
|
||||
let record = helper.decodeInformationRecord();
|
||||
let records = helper.decodeInformationRecord();
|
||||
|
||||
do_check_eq(record.display, "Test Info");
|
||||
do_check_eq(records[0].display, "Test Info");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
@ -67,27 +71,19 @@ add_test(function test_extended_display() {
|
||||
let worker = newWorkerWithParcel([
|
||||
0x01, // one inforemation record
|
||||
0x07, // type: extended display
|
||||
0x0E, // length: 14
|
||||
0x80, // header byte
|
||||
0x80, // Blank
|
||||
0x81, // Skip
|
||||
0x9B, // Text
|
||||
0x09, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E,
|
||||
0x66, 0x6F, 0x00]);
|
||||
0x12, // length: 18
|
||||
0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x78, 0x74,
|
||||
0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x49, 0x6E,
|
||||
0x66, 0x6F, 0x00, 0x00]);
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let helper = context.CdmaPDUHelper;
|
||||
let record = helper.decodeInformationRecord();
|
||||
let records = helper.decodeInformationRecord();
|
||||
|
||||
do_check_eq(record.extendedDisplay.indicator, 1);
|
||||
do_check_eq(record.extendedDisplay.type, 0);
|
||||
do_check_eq(record.extendedDisplay.records.length, 3);
|
||||
do_check_eq(record.extendedDisplay.records[0].tag, 0x80);
|
||||
do_check_eq(record.extendedDisplay.records[1].tag, 0x81);
|
||||
do_check_eq(record.extendedDisplay.records[2].tag, 0x9B);
|
||||
do_check_eq(record.extendedDisplay.records[2].content, "Test Info");
|
||||
do_check_eq(records[0].display, "Test Extended Info");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
/**
|
||||
* Verify decoder for mixed type
|
||||
*/
|
||||
@ -95,29 +91,144 @@ add_test(function test_mixed() {
|
||||
let worker = newWorkerWithParcel([
|
||||
0x02, // two inforemation record
|
||||
0x00, // type: display
|
||||
0x09, // length: 9
|
||||
0x0B, // length: 11
|
||||
0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
|
||||
0x6F, 0x00,
|
||||
0x6F, 0x20, 0x31, 0x00,
|
||||
0x07, // type: extended display
|
||||
0x0E, // length: 14
|
||||
0x80, // header byte
|
||||
0x80, // Blank
|
||||
0x81, // Skip
|
||||
0x9B, // Text
|
||||
0x09, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E,
|
||||
0x66, 0x6F, 0x00]);
|
||||
0x0B, // length: 11
|
||||
0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
|
||||
0x6F, 0x20, 0x32, 0x00]);
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let helper = context.CdmaPDUHelper;
|
||||
let record = helper.decodeInformationRecord();
|
||||
let records = helper.decodeInformationRecord();
|
||||
|
||||
do_check_eq(record.display, "Test Info");
|
||||
do_check_eq(record.extendedDisplay.indicator, 1);
|
||||
do_check_eq(record.extendedDisplay.type, 0);
|
||||
do_check_eq(record.extendedDisplay.records.length, 3);
|
||||
do_check_eq(record.extendedDisplay.records[0].tag, 0x80);
|
||||
do_check_eq(record.extendedDisplay.records[1].tag, 0x81);
|
||||
do_check_eq(record.extendedDisplay.records[2].tag, 0x9B);
|
||||
do_check_eq(record.extendedDisplay.records[2].content, "Test Info");
|
||||
do_check_eq(records[0].display, "Test Info 1");
|
||||
do_check_eq(records[1].display, "Test Info 2");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
/**
|
||||
* Verify decoder for multiple types
|
||||
*/
|
||||
add_test(function test_multiple() {
|
||||
let worker = newWorkerWithParcel([
|
||||
0x02, // two inforemation record
|
||||
0x00, // type: display
|
||||
0x0B, // length: 11
|
||||
0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
|
||||
0x6F, 0x20, 0x31, 0x00,
|
||||
0x00, // type: display
|
||||
0x0B, // length: 11
|
||||
0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
|
||||
0x6F, 0x20, 0x32, 0x00]);
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let helper = context.CdmaPDUHelper;
|
||||
let records = helper.decodeInformationRecord();
|
||||
|
||||
do_check_eq(records[0].display, "Test Info 1");
|
||||
do_check_eq(records[1].display, "Test Info 2");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
/**
|
||||
* Verify decoder for Signal Type
|
||||
*/
|
||||
add_test(function test_signal() {
|
||||
let worker = newWorkerWithParcel([
|
||||
0x01, // one inforemation record
|
||||
0x04, // type: signal
|
||||
0x01, // isPresent: non-zero
|
||||
0x00, // signalType: Tone signal (00)
|
||||
0x01, // alertPitch: High pitch
|
||||
0x03]); // signal: Abbreviated intercept (000011)
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let helper = context.CdmaPDUHelper;
|
||||
let records = helper.decodeInformationRecord();
|
||||
|
||||
do_check_eq(records[0].signal.type, 0x00);
|
||||
do_check_eq(records[0].signal.alertPitch, 0x01);
|
||||
do_check_eq(records[0].signal.signal, 0x03);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
/**
|
||||
* Verify decoder for Signal Type for Not Presented
|
||||
*/
|
||||
add_test(function test_signal_not_present() {
|
||||
let worker = newWorkerWithParcel([
|
||||
0x01, // one inforemation record
|
||||
0x04, // type: signal
|
||||
0x00, // isPresent: zero
|
||||
0x00, // signalType: Tone signal (00)
|
||||
0x01, // alertPitch: High pitch
|
||||
0x03]); // signal: Abbreviated intercept (000011)
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let helper = context.CdmaPDUHelper;
|
||||
let records = helper.decodeInformationRecord();
|
||||
|
||||
do_check_eq(records.length, 0);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
/**
|
||||
* Verify decoder for Line Control
|
||||
*/
|
||||
add_test(function test_line_control() {
|
||||
let worker = newWorkerWithParcel([
|
||||
0x01, // one inforemation record
|
||||
0x06, // type: line control
|
||||
0x01, // polarity included
|
||||
0x00, // not toggled
|
||||
0x01, // reversed
|
||||
0xFF]); // Power denial timeout: 255 * 5 ms
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let helper = context.CdmaPDUHelper;
|
||||
let records = helper.decodeInformationRecord();
|
||||
|
||||
do_check_eq(records[0].lineControl.polarityIncluded, 1);
|
||||
do_check_eq(records[0].lineControl.toggle, 0);
|
||||
do_check_eq(records[0].lineControl.reverse, 1);
|
||||
do_check_eq(records[0].lineControl.powerDenial, 255);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
/**
|
||||
* Verify decoder for CLIR Cause
|
||||
*/
|
||||
add_test(function test_clir() {
|
||||
let worker = newWorkerWithParcel([
|
||||
0x01, // one inforemation record
|
||||
0x08, // type: clir
|
||||
0x01]); // cause: Rejected by user
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let helper = context.CdmaPDUHelper;
|
||||
let records = helper.decodeInformationRecord();
|
||||
|
||||
do_check_eq(records[0].clirCause, 1);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
/**
|
||||
* Verify decoder for Audio Control
|
||||
*/
|
||||
add_test(function test_clir() {
|
||||
let worker = newWorkerWithParcel([
|
||||
0x01, // one inforemation record
|
||||
0x0A, // type: audio control
|
||||
0x01, // uplink
|
||||
0xFF]); // downlink
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let helper = context.CdmaPDUHelper;
|
||||
let records = helper.decodeInformationRecord();
|
||||
|
||||
do_check_eq(records[0].audioControl.upLink, 1);
|
||||
do_check_eq(records[0].audioControl.downLink, 255);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
@ -227,13 +227,6 @@ WifiCertService::Start(nsIWifiEventListener* aListener)
|
||||
{
|
||||
MOZ_ASSERT(aListener);
|
||||
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(mRequestThread));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Certn't create wifi control thread");
|
||||
Shutdown();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mListener = aListener;
|
||||
|
||||
return NS_OK;
|
||||
@ -243,10 +236,6 @@ NS_IMETHODIMP
|
||||
WifiCertService::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mRequestThread) {
|
||||
mRequestThread->Shutdown();
|
||||
mRequestThread = nullptr;
|
||||
}
|
||||
|
||||
mListener = nullptr;
|
||||
|
||||
|
@ -27,7 +27,6 @@ public:
|
||||
private:
|
||||
WifiCertService();
|
||||
~WifiCertService();
|
||||
nsCOMPtr<nsIThread> mRequestThread;
|
||||
nsCOMPtr<nsIWifiEventListener> mListener;
|
||||
};
|
||||
|
||||
|
@ -1859,7 +1859,7 @@ function WifiWorker() {
|
||||
var pub = new Network(ssid, security, password);
|
||||
if (net.identity)
|
||||
pub.identity = dequote(net.identity);
|
||||
if (net.netId)
|
||||
if ("netId" in net)
|
||||
pub.known = true;
|
||||
if (net.scan_ssid === 1)
|
||||
pub.hidden = true;
|
||||
|
@ -2760,7 +2760,7 @@ public class BrowserApp extends GeckoApp
|
||||
share.setVisible(shareEnabled);
|
||||
share.setEnabled(StringUtils.isShareableUrl(url) && shareEnabled);
|
||||
MenuUtils.safeSetEnabled(aMenu, R.id.apps, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_INSTALL_APPS));
|
||||
MenuUtils.safeSetEnabled(aMenu, R.id.addons, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_INSTALL_EXTENSIONS));
|
||||
MenuUtils.safeSetEnabled(aMenu, R.id.addons, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_INSTALL_EXTENSION));
|
||||
MenuUtils.safeSetEnabled(aMenu, R.id.downloads, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_DOWNLOADS));
|
||||
|
||||
// NOTE: Use MenuUtils.safeSetEnabled because some actions might
|
||||
|
@ -81,6 +81,7 @@ import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.os.StrictMode;
|
||||
@ -978,6 +979,12 @@ public abstract class GeckoApp
|
||||
image = BitmapUtils.decodeByteArray(imgBuffer);
|
||||
}
|
||||
if (image != null) {
|
||||
// Some devices don't have a DCIM folder and the Media.insertImage call will fail.
|
||||
File dcimDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
||||
if (!dcimDir.mkdirs() && !dcimDir.isDirectory()) {
|
||||
Toast.makeText((Context) this, R.string.set_image_path_fail, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
String path = Media.insertImage(getContentResolver(),image, null, null);
|
||||
if (path == null) {
|
||||
Toast.makeText((Context) this, R.string.set_image_path_fail, Toast.LENGTH_SHORT).show();
|
||||
|
@ -55,14 +55,16 @@ public class RestrictedProfiles {
|
||||
*/
|
||||
public static enum Restriction {
|
||||
DISALLOW_DOWNLOADS(1, "no_download_files"),
|
||||
DISALLOW_INSTALL_EXTENSIONS(2, "no_install_extensions"),
|
||||
DISALLOW_INSTALL_EXTENSION(2, "no_install_extensions"),
|
||||
DISALLOW_INSTALL_APPS(3, "no_install_apps"), // UserManager.DISALLOW_INSTALL_APPS
|
||||
DISALLOW_BROWSE_FILES(4, "no_browse_files"),
|
||||
DISALLOW_SHARE(5, "no_share"),
|
||||
DISALLOW_BOOKMARK(6, "no_bookmark"),
|
||||
DISALLOW_ADD_CONTACTS(7, "no_add_contacts"),
|
||||
DISALLOW_SET_IMAGE(8, "no_set_image"),
|
||||
DISALLOW_MODIFY_ACCOUNTS(9, "no_modify_accounts"); // UserManager.DISALLOW_MODIFY_ACCOUNTS
|
||||
DISALLOW_MODIFY_ACCOUNTS(9, "no_modify_accounts"), // UserManager.DISALLOW_MODIFY_ACCOUNTS
|
||||
DISALLOW_REMOTE_DEBUGGING(10, "no_remote_debugging"),
|
||||
DISALLOW_IMPORT_SETTINGS(11, "no_import_settings");
|
||||
|
||||
public final int id;
|
||||
public final String name;
|
||||
|
@ -10,7 +10,10 @@ import org.mozilla.gecko.animation.BounceAnimator;
|
||||
import org.mozilla.gecko.animation.BounceAnimator.Attributes;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.support.v4.view.PagerTabStrip;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
@ -37,8 +40,11 @@ class HomePagerTabStrip extends PagerTabStrip {
|
||||
private static final int BOUNCE4_MS = 100;
|
||||
private static final int INIT_OFFSET = 100;
|
||||
|
||||
private final Paint shadowPaint;
|
||||
private final int shadowSize;
|
||||
|
||||
public HomePagerTabStrip(Context context) {
|
||||
super(context);
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public HomePagerTabStrip(Context context, AttributeSet attrs) {
|
||||
@ -50,6 +56,13 @@ class HomePagerTabStrip extends PagerTabStrip {
|
||||
|
||||
setTabIndicatorColor(color);
|
||||
|
||||
final Resources res = getResources();
|
||||
shadowSize = res.getDimensionPixelSize(R.dimen.tabs_strip_shadow_size);
|
||||
|
||||
shadowPaint = new Paint();
|
||||
shadowPaint.setColor(res.getColor(R.color.url_bar_shadow));
|
||||
shadowPaint.setStrokeWidth(0.0f);
|
||||
|
||||
getViewTreeObserver().addOnPreDrawListener(new PreDrawListener());
|
||||
}
|
||||
|
||||
@ -61,6 +74,14 @@ class HomePagerTabStrip extends PagerTabStrip {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
super.draw(canvas);
|
||||
|
||||
final int height = getHeight();
|
||||
canvas.drawRect(0, height - shadowSize, getWidth(), height, shadowPaint);
|
||||
}
|
||||
|
||||
private void animateTitles() {
|
||||
final View prevTextView = getChildAt(0);
|
||||
final View nextTextView = getChildAt(getChildCount() - 1);
|
||||
|
@ -8,12 +8,31 @@ package org.mozilla.gecko.home;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
|
||||
import org.mozilla.gecko.home.TwoLinePageRow;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class ReadingListRow extends LinearLayout {
|
||||
|
||||
private final Resources resources;
|
||||
|
||||
private final TextView title;
|
||||
private final TextView excerpt;
|
||||
private final TextView readTime;
|
||||
|
||||
// Average reading speed in words per minute.
|
||||
private static final int AVERAGE_READING_SPEED = 250;
|
||||
|
||||
// Length of average word.
|
||||
private static final float AVERAGE_WORD_LENGTH = 5.1f;
|
||||
|
||||
public class ReadingListRow extends TwoLinePageRow {
|
||||
|
||||
public ReadingListRow(Context context) {
|
||||
this(context, null);
|
||||
@ -21,22 +40,48 @@ public class ReadingListRow extends TwoLinePageRow {
|
||||
|
||||
public ReadingListRow(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.reading_list_row_view, this);
|
||||
|
||||
setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
resources = context.getResources();
|
||||
|
||||
title = (TextView) findViewById(R.id.title);
|
||||
excerpt = (TextView) findViewById(R.id.excerpt);
|
||||
readTime = (TextView) findViewById(R.id.read_time);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateDisplayedUrl() {
|
||||
String pageUrl = getUrl();
|
||||
public void updateFromCursor(Cursor cursor) {
|
||||
if (cursor == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isPrivate = Tabs.getInstance().getSelectedTab().isPrivate();
|
||||
Tab tab = Tabs.getInstance().getFirstReaderTabForUrl(pageUrl, isPrivate);
|
||||
final int titleIndex = cursor.getColumnIndexOrThrow(ReadingListItems.TITLE);
|
||||
title.setText(cursor.getString(titleIndex));
|
||||
|
||||
if (tab != null) {
|
||||
setUrl(R.string.switch_to_tab);
|
||||
setSwitchToTabIcon(R.drawable.ic_url_bar_tab);
|
||||
final int excerptIndex = cursor.getColumnIndexOrThrow(ReadingListItems.EXCERPT);
|
||||
excerpt.setText(cursor.getString(excerptIndex));
|
||||
|
||||
final int lengthIndex = cursor.getColumnIndexOrThrow(ReadingListItems.LENGTH);
|
||||
final int minutes = getEstimatedReadTime(cursor.getInt(lengthIndex));
|
||||
if (minutes <= 60) {
|
||||
readTime.setText(resources.getString(R.string.reading_list_time_minutes, minutes));
|
||||
} else {
|
||||
setUrl(pageUrl);
|
||||
setSwitchToTabIcon(NO_ICON);
|
||||
readTime.setText(resources.getString(R.string.reading_list_time_over_an_hour));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the estimated time to read an article based on its length.
|
||||
*
|
||||
* @param length of the article (in characters)
|
||||
* @return estimated time to read the article (in minutes)
|
||||
*/
|
||||
private static int getEstimatedReadTime(int length) {
|
||||
final int minutes = (int) Math.ceil((length / AVERAGE_WORD_LENGTH) / AVERAGE_READING_SPEED);
|
||||
|
||||
// Minimum of one minute.
|
||||
return Math.max(minutes, 1);
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
@ -52,10 +51,14 @@ public class RemoteTabsPanel extends HomeFragment {
|
||||
|
||||
// A lazily-populated cache of fragments corresponding to the possible
|
||||
// system account states. We don't want to re-create panels unnecessarily,
|
||||
// because that can cause flickering. Be aware that null is a valid key; it
|
||||
// corresponds to "no Account, neither Firefox nor Legacy Sync."
|
||||
// because that can cause flickering. `null` is not a valid key.
|
||||
private final Map<Action, Fragment> mFragmentCache = new EnumMap<>(Action.class);
|
||||
|
||||
// The fragment that corresponds to the null action -- "no Account,
|
||||
// neither Firefox nor Legacy Sync."
|
||||
// Lazily populated.
|
||||
private Fragment mFallbackFragment;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.home_remote_tabs_panel, container, false);
|
||||
@ -175,12 +178,20 @@ public class RemoteTabsPanel extends HomeFragment {
|
||||
private Fragment getFragmentNeeded(Account account) {
|
||||
final Action actionNeeded = getActionNeeded(account);
|
||||
|
||||
// We use containsKey rather than get because null is a valid key.
|
||||
if (!mFragmentCache.containsKey(actionNeeded)) {
|
||||
final Fragment fragment = makeFragmentForAction(actionNeeded);
|
||||
if (actionNeeded == null) {
|
||||
if (mFallbackFragment == null) {
|
||||
mFallbackFragment = makeFragmentForAction(null);
|
||||
}
|
||||
return mFallbackFragment;
|
||||
}
|
||||
|
||||
Fragment fragment = mFragmentCache.get(actionNeeded);
|
||||
if (fragment == null) {
|
||||
fragment = makeFragmentForAction(actionNeeded);
|
||||
mFragmentCache.put(actionNeeded, fragment);
|
||||
}
|
||||
return mFragmentCache.get(actionNeeded);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,8 +8,10 @@ package org.mozilla.gecko.home;
|
||||
import org.mozilla.gecko.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
@ -35,16 +37,35 @@ public class TabMenuStrip extends HorizontalScrollView
|
||||
private final int titleOffset;
|
||||
private final TabMenuStripLayout layout;
|
||||
|
||||
private final Paint shadowPaint;
|
||||
private final int shadowSize;
|
||||
|
||||
public TabMenuStrip(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
// Disable the scroll bar.
|
||||
setHorizontalScrollBarEnabled(false);
|
||||
|
||||
titleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
|
||||
final Resources res = getResources();
|
||||
|
||||
titleOffset = (int) (TITLE_OFFSET_DIPS * res.getDisplayMetrics().density);
|
||||
|
||||
layout = new TabMenuStripLayout(context, attrs);
|
||||
addView(layout, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
|
||||
shadowSize = res.getDimensionPixelSize(R.dimen.tabs_strip_shadow_size);
|
||||
|
||||
shadowPaint = new Paint();
|
||||
shadowPaint.setColor(res.getColor(R.color.url_bar_shadow));
|
||||
shadowPaint.setStrokeWidth(0.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
super.draw(canvas);
|
||||
|
||||
final int height = getHeight();
|
||||
canvas.drawRect(0, height - shadowSize, getWidth(), height, shadowPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -364,6 +364,12 @@ size. -->
|
||||
<!ENTITY reading_list_failed "Failed to add page to your Reading List">
|
||||
<!ENTITY reading_list_duplicate "Page already in your Reading List">
|
||||
|
||||
<!-- Localization note (reading_list_time_minutes) : This string is used in the "Reading List"
|
||||
panel on the home page to give the user an estimate of how many minutes it will take to
|
||||
read an article. The word "minute" should be abbreviated if possible. -->
|
||||
<!ENTITY reading_list_time_minutes "&formatD;min">
|
||||
<!ENTITY reading_list_time_over_an_hour "Over an hour">
|
||||
|
||||
<!-- Localization note : These strings are used as alternate text for accessibility.
|
||||
They are not visible in the UI. -->
|
||||
<!ENTITY page_action_dropmarker_description "Additional Actions">
|
||||
|
@ -7,19 +7,31 @@ package org.mozilla.gecko.preferences;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.RestrictedProfiles;
|
||||
import org.mozilla.gecko.RestrictedProfiles.Restriction;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
class AndroidImportPreference extends MultiPrefMultiChoicePreference {
|
||||
private static final String LOGTAG = "AndroidImport";
|
||||
public static final String PREF_KEY = "android.not_a_preference.import_android";
|
||||
private static final String PREF_KEY_PREFIX = "import_android.data.";
|
||||
private final Context mContext;
|
||||
|
||||
public static class Handler implements GeckoPreferences.PrefHandler {
|
||||
public boolean setupPref(Context context, Preference pref) {
|
||||
return RestrictedProfiles.isAllowed(Restriction.DISALLOW_IMPORT_SETTINGS);
|
||||
}
|
||||
|
||||
public void onChange(Context context, Preference pref, Object newValue) { }
|
||||
}
|
||||
|
||||
public AndroidImportPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
|
@ -19,12 +19,13 @@ public class ClearOnShutdownPref implements GeckoPreferences.PrefHandler {
|
||||
public static final String PREF = GeckoPreferences.NON_PREF_PREFIX + "history.clear_on_exit";
|
||||
|
||||
@Override
|
||||
public void setupPref(Context context, Preference pref) {
|
||||
public boolean setupPref(Context context, Preference pref) {
|
||||
// The pref is initialized asynchronously. Read the pref explicitly
|
||||
// here to make sure we have the data.
|
||||
final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
|
||||
final Set<String> clearItems = PrefUtils.getStringSet(prefs, PREF, new HashSet<String>());
|
||||
((ListCheckboxPreference) pref).setChecked(clearItems.size() > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -700,6 +700,12 @@ OnSharedPreferenceChangeListener
|
||||
i--;
|
||||
continue;
|
||||
} else if (PREFS_DEVTOOLS_REMOTE_ENABLED.equals(key)) {
|
||||
if (!RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_REMOTE_DEBUGGING)) {
|
||||
preferences.removePreference(pref);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
final Context thisContext = this;
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
@ -744,7 +750,11 @@ OnSharedPreferenceChangeListener
|
||||
continue;
|
||||
} else if (handlers.containsKey(key)) {
|
||||
PrefHandler handler = handlers.get(key);
|
||||
handler.setupPref(this, pref);
|
||||
if (!handler.setupPref(this, pref)) {
|
||||
preferences.removePreference(pref);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Some Preference UI elements are not actually preferences,
|
||||
@ -1026,13 +1036,16 @@ OnSharedPreferenceChangeListener
|
||||
}
|
||||
|
||||
public interface PrefHandler {
|
||||
public void setupPref(Context context, Preference pref);
|
||||
// Allows the pref to do any initialization it needs. Return false to have the pref removed
|
||||
// from the prefs screen entirely.
|
||||
public boolean setupPref(Context context, Preference pref);
|
||||
public void onChange(Context context, Preference pref, Object newValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private final Map<String, PrefHandler> handlers = new HashMap<String, PrefHandler>() {{
|
||||
put(ClearOnShutdownPref.PREF, new ClearOnShutdownPref());
|
||||
put(AndroidImportPreference.PREF_KEY, new AndroidImportPreference.Handler());
|
||||
}};
|
||||
|
||||
@Override
|
||||
|
@ -14,7 +14,7 @@
|
||||
android:background="@android:color/white">
|
||||
|
||||
<org.mozilla.gecko.home.TabMenuStrip android:layout_width="match_parent"
|
||||
android:layout_height="32dip"
|
||||
android:layout_height="@dimen/tabs_strip_height"
|
||||
android:background="@color/background_light"
|
||||
android:layout_gravity="top"
|
||||
gecko:strip="@drawable/home_tab_menu_strip"/>
|
||||
|
@ -14,7 +14,7 @@
|
||||
android:background="@android:color/white">
|
||||
|
||||
<org.mozilla.gecko.home.HomePagerTabStrip android:layout_width="match_parent"
|
||||
android:layout_height="40dip"
|
||||
android:layout_height="@dimen/tabs_strip_height"
|
||||
android:layout_gravity="top"
|
||||
android:gravity="center_vertical"
|
||||
android:background="@color/background_light"
|
||||
|
@ -16,5 +16,5 @@
|
||||
<org.mozilla.gecko.home.HomeListView android:id="@+id/list"
|
||||
style="@style/Widget.ReadingListView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
||||
|
@ -6,5 +6,5 @@
|
||||
<org.mozilla.gecko.home.ReadingListRow xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/Widget.BookmarkItemView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/page_row_height"
|
||||
android:minHeight="@dimen/page_row_height"/>
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp"/>
|
||||
|
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
style="@style/Widget.ReadingListRow.Title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/read_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
style="@style/Widget.ReadingListRow.ReadTime" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/excerpt"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.ReadingListRow.Description" />
|
||||
|
||||
</merge>
|
@ -71,9 +71,4 @@
|
||||
<item name="android:layout_gravity">center</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Home.HomeList">
|
||||
<item name="topDivider">true</item>
|
||||
<item name="android:scrollbarStyle">outsideOverlay</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -17,6 +17,12 @@
|
||||
<item name="android:fontFamily">sans-serif-light</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.ReadingListRow.ReadTime">
|
||||
<item name="android:textStyle">italic</item>
|
||||
<item name="android:textColor">#FF9400</item>
|
||||
<item name="android:fontFamily">sans-serif-condensed</item>
|
||||
</style>
|
||||
|
||||
<style name="OnboardStartTextAppearance.Subtext">
|
||||
<item name="android:textSize">18sp</item>
|
||||
<item name="android:fontFamily">sans-serif-light</item>
|
||||
|
@ -19,11 +19,6 @@
|
||||
<item name="android:verticalSpacing">20dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Home.HomeList">
|
||||
<item name="android:scrollbarStyle">outsideOverlay</item>
|
||||
<item name="topDivider">true</item>
|
||||
</style>
|
||||
|
||||
<!-- Tabs panel -->
|
||||
<style name="TabsPanelFrame.RemoteTabs" parent="TabsPanelFrameBase">
|
||||
<item name="android:paddingLeft">0dp</item>
|
||||
|
@ -16,11 +16,6 @@
|
||||
<item name="android:layout_height">48dip</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Home.HomeList">
|
||||
<item name="android:scrollbarStyle">outsideOverlay</item>
|
||||
<item name="topDivider">true</item>
|
||||
</style>
|
||||
|
||||
<!-- Tabs panel -->
|
||||
<style name="TabsPanelFrame.RemoteTabs" parent="TabsPanelFrameBase">
|
||||
<item name="android:paddingLeft">212dp</item>
|
||||
|
@ -105,8 +105,10 @@
|
||||
<dimen name="tabs_panel_list_padding">16dip</dimen>
|
||||
<dimen name="tabs_list_divider_height">2dp</dimen>
|
||||
<dimen name="tabs_sidebar_width">200dp</dimen>
|
||||
<dimen name="tabs_strip_height">40dp</dimen>
|
||||
<dimen name="tabs_strip_button_width">100dp</dimen>
|
||||
<dimen name="tabs_strip_button_padding">18dp</dimen>
|
||||
<dimen name="tabs_strip_shadow_size">1dp</dimen>
|
||||
<dimen name="tabs_tray_horizontal_height">156dp</dimen>
|
||||
<dimen name="text_selection_handle_width">47dp</dimen>
|
||||
<dimen name="text_selection_handle_height">58dp</dimen>
|
||||
|
@ -63,10 +63,6 @@
|
||||
</style>
|
||||
|
||||
<style name="Widget.Home.HomeList">
|
||||
<item name="android:paddingTop">0dip</item>
|
||||
<item name="android:paddingRight">0dip</item>
|
||||
<item name="android:paddingLeft">0dip</item>
|
||||
<item name="topDivider">true</item>
|
||||
<item name="android:scrollbarStyle">outsideOverlay</item>
|
||||
</style>
|
||||
|
||||
@ -131,6 +127,25 @@
|
||||
<item name="android:ellipsize">middle</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.ReadingListRow" />
|
||||
|
||||
<style name="Widget.ReadingListRow.Title">
|
||||
<item name="android:textAppearance">@style/TextAppearance.Widget.Home.ItemTitle</item>
|
||||
<item name="android:maxLines">2</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.ReadingListRow.Description">
|
||||
<item name="android:textAppearance">@style/TextAppearance.Widget.Home.ItemDescription</item>
|
||||
<item name="android:maxLines">4</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.ReadingListRow.ReadTime">
|
||||
<item name="android:textStyle">italic</item>
|
||||
<item name="android:textColor">@color/text_color_highlight</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLinePageRow.Title">
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:ellipsize">none</item>
|
||||
@ -229,7 +244,7 @@
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">32dp</item>
|
||||
<item name="android:textAppearance">@style/TextAppearance.Widget.Home.Header</item>
|
||||
<item name="android:background">#fff5f7f9</item>
|
||||
<item name="android:background">@color/background_light</item>
|
||||
<item name="android:focusable">false</item>
|
||||
<item name="android:gravity">center|left</item>
|
||||
<item name="android:paddingLeft">10dip</item>
|
||||
|
@ -298,6 +298,8 @@
|
||||
<string name="reading_list_added">&reading_list_added;</string>
|
||||
<string name="reading_list_failed">&reading_list_failed;</string>
|
||||
<string name="reading_list_duplicate">&reading_list_duplicate;</string>
|
||||
<string name="reading_list_time_minutes">&reading_list_time_minutes;</string>
|
||||
<string name="reading_list_time_over_an_hour">&reading_list_time_over_an_hour;</string>
|
||||
|
||||
<string name="page_action_dropmarker_description">&page_action_dropmarker_description;</string>
|
||||
|
||||
|
@ -537,7 +537,7 @@ var Addons = {
|
||||
|
||||
// Go back if we're in the detail view of the add-on that was uninstalled.
|
||||
let detailItem = document.querySelector("#addons-details > .addon-item");
|
||||
if (detailItem.addon == aAddon) {
|
||||
if (detailItem.addon.id == aAddon.id) {
|
||||
history.back();
|
||||
}
|
||||
},
|
||||
|
@ -465,7 +465,7 @@ var BrowserApp = {
|
||||
if (this._startupStatus)
|
||||
this.onAppUpdated();
|
||||
|
||||
if (!ParentalControls.isAllowed(ParentalControls.INSTALL_EXTENSIONS)) {
|
||||
if (!ParentalControls.isAllowed(ParentalControls.INSTALL_EXTENSION)) {
|
||||
// Disable extension installs
|
||||
Services.prefs.setIntPref("extensions.enabledScopes", 1);
|
||||
Services.prefs.setIntPref("extensions.autoDisableScopes", 1);
|
||||
|
@ -5,7 +5,7 @@
|
||||
MOZ_APP_BASENAME=Fennec
|
||||
MOZ_APP_VENDOR=Mozilla
|
||||
|
||||
MOZ_APP_VERSION=35.0a1
|
||||
MOZ_APP_VERSION=36.0a1
|
||||
MOZ_APP_UA_NAME=Firefox
|
||||
|
||||
MOZ_BRANDING_DIRECTORY=mobile/android/branding/unofficial
|
||||
|
@ -102,8 +102,13 @@ public class SearchWidget extends AppWidgetProvider {
|
||||
|
||||
// Utility to create the view for this widget and attach any event listeners to it
|
||||
private void addView(final AppWidgetManager manager, final Context context, final int id, final Bundle options) {
|
||||
final int category = options.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
|
||||
final boolean isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
|
||||
final boolean isKeyguard;
|
||||
if (options != null) {
|
||||
final int category = options.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
|
||||
isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
|
||||
} else {
|
||||
isKeyguard = false;
|
||||
}
|
||||
|
||||
final RemoteViews views;
|
||||
if (isKeyguard) {
|
||||
|
@ -47,8 +47,6 @@ extern PRLogModuleInfo* gRtspLog;
|
||||
#undef LOG
|
||||
#define LOG(args) PR_LOG(gRtspLog, PR_LOG_DEBUG, args)
|
||||
|
||||
const unsigned long kCommandDelayMs = 200;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
@ -59,10 +57,7 @@ NS_IMPL_ISUPPORTS(RtspController,
|
||||
nsIStreamingProtocolController)
|
||||
|
||||
RtspController::RtspController(nsIChannel *channel)
|
||||
: mState(INIT),
|
||||
mTimerLock("RtspController.mTimerLock"),
|
||||
mPlayTimer(nullptr),
|
||||
mPauseTimer(nullptr)
|
||||
: mState(INIT)
|
||||
{
|
||||
LOG(("RtspController::RtspController()"));
|
||||
}
|
||||
@ -99,26 +94,7 @@ RtspController::Play(void)
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mTimerLock);
|
||||
// Cancel the pause timer if it is active because successive pause-play in a
|
||||
// short duration is unnecessary but could impair playback smoothing.
|
||||
if (mPauseTimer) {
|
||||
mPauseTimer->Cancel();
|
||||
mPauseTimer = nullptr;
|
||||
}
|
||||
|
||||
// Start a timer to delay the play operation for a short duration.
|
||||
if (!mPlayTimer) {
|
||||
mPlayTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (!mPlayTimer) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
mPlayTimer->InitWithFuncCallback(
|
||||
RtspController::PlayTimerCallback,
|
||||
this, kCommandDelayMs,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
mRtspSource->play();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -135,26 +111,7 @@ RtspController::Pause(void)
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mTimerLock);
|
||||
// Cancel the play timer if it is active because successive play-pause in a
|
||||
// short duration is unnecessary but could impair playback smoothing.
|
||||
if (mPlayTimer) {
|
||||
mPlayTimer->Cancel();
|
||||
mPlayTimer = nullptr;
|
||||
}
|
||||
|
||||
// Start a timer to delay the pause operation for a short duration.
|
||||
if (!mPauseTimer) {
|
||||
mPauseTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (!mPauseTimer) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
mPauseTimer->InitWithFuncCallback(
|
||||
RtspController::PauseTimerCallback,
|
||||
this, kCommandDelayMs,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
mRtspSource->pause();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -360,19 +317,6 @@ RtspController::OnDisconnected(uint8_t index,
|
||||
LOG(("RtspController::OnDisconnected() for track %d reason = 0x%x", index, reason));
|
||||
mState = DISCONNECTED;
|
||||
|
||||
// Ensure play and pause timer are stopped.
|
||||
{
|
||||
MutexAutoLock lock(mTimerLock);
|
||||
if (mPlayTimer) {
|
||||
mPlayTimer->Cancel();
|
||||
mPlayTimer = nullptr;
|
||||
}
|
||||
if (mPauseTimer) {
|
||||
mPauseTimer->Cancel();
|
||||
mPauseTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (mListener) {
|
||||
nsRefPtr<SendOnDisconnectedTask> task =
|
||||
new SendOnDisconnectedTask(mListener, index, reason);
|
||||
@ -436,40 +380,5 @@ RtspController::PlaybackEnded()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// RtspController static member methods
|
||||
//-----------------------------------------------------------------------------
|
||||
//static
|
||||
void RtspController::PlayTimerCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
MOZ_ASSERT(aTimer);
|
||||
MOZ_ASSERT(aClosure);
|
||||
|
||||
RtspController *self = static_cast<RtspController*>(aClosure);
|
||||
MOZ_ASSERT(self->mRtspSource.get());
|
||||
|
||||
MutexAutoLock lock(self->mTimerLock);
|
||||
if (self->mPlayTimer) {
|
||||
self->mRtspSource->play();
|
||||
self->mPlayTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void RtspController::PauseTimerCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
MOZ_ASSERT(aTimer);
|
||||
MOZ_ASSERT(aClosure);
|
||||
|
||||
RtspController *self = static_cast<RtspController*>(aClosure);
|
||||
MOZ_ASSERT(self->mRtspSource.get());
|
||||
|
||||
MutexAutoLock lock(self->mTimerLock);
|
||||
if (self->mPauseTimer) {
|
||||
self->mRtspSource->pause();
|
||||
self->mPauseTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::net
|
||||
} // namespace mozilla
|
||||
|
@ -7,12 +7,10 @@
|
||||
#ifndef RtspController_h
|
||||
#define RtspController_h
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsIStreamingProtocolController.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsITimer.h"
|
||||
#include "RTSPSource.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -29,10 +27,6 @@ public:
|
||||
RtspController(nsIChannel *channel);
|
||||
~RtspController();
|
||||
|
||||
// These callbacks will be called when mPlayTimer/mPauseTimer fires.
|
||||
static void PlayTimerCallback(nsITimer *aTimer, void *aClosure);
|
||||
static void PauseTimerCallback(nsITimer *aTimer, void *aClosure);
|
||||
|
||||
private:
|
||||
enum State {
|
||||
INIT,
|
||||
@ -53,13 +47,6 @@ private:
|
||||
State mState;
|
||||
// Rtsp Streaming source.
|
||||
android::sp<android::RTSPSource> mRtspSource;
|
||||
// This lock protects mPlayTimer and mPauseTimer.
|
||||
Mutex mTimerLock;
|
||||
// Timers to delay the play and pause operations.
|
||||
// They are used for optimization and avoid sending unnecessary requests to
|
||||
// the server.
|
||||
nsCOMPtr<nsITimer> mPlayTimer;
|
||||
nsCOMPtr<nsITimer> mPauseTimer;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ PRLogModuleInfo* gRtspChildLog = nullptr;
|
||||
#define LOG(args) PR_LOG(gRtspChildLog, PR_LOG_DEBUG, args)
|
||||
|
||||
const uint32_t kRtspTotalTracks = 2;
|
||||
const unsigned long kRtspCommandDelayMs = 200;
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
namespace mozilla {
|
||||
@ -64,6 +66,9 @@ RtspControllerChild::RtspControllerChild(nsIChannel *channel)
|
||||
, mChannel(channel)
|
||||
, mTotalTracks(0)
|
||||
, mSuspendCount(0)
|
||||
, mTimerLock("RtspControllerChild.mTimerLock")
|
||||
, mPlayTimer(nullptr)
|
||||
, mPauseTimer(nullptr)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
if (!gRtspChildLog)
|
||||
@ -108,6 +113,20 @@ RtspControllerChild::DisallowIPC()
|
||||
mIPCAllowed = false;
|
||||
}
|
||||
|
||||
void
|
||||
RtspControllerChild::StopPlayAndPauseTimer()
|
||||
{
|
||||
MutexAutoLock lock(mTimerLock);
|
||||
if (mPlayTimer) {
|
||||
mPlayTimer->Cancel();
|
||||
mPlayTimer = nullptr;
|
||||
}
|
||||
if (mPauseTimer) {
|
||||
mPauseTimer->Cancel();
|
||||
mPauseTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// RtspControllerChild::PRtspControllerChild
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -174,6 +193,7 @@ RtspControllerChild::RecvOnDisconnected(
|
||||
const uint8_t& index,
|
||||
const nsresult& reason)
|
||||
{
|
||||
StopPlayAndPauseTimer();
|
||||
DisallowIPC();
|
||||
LOG(("RtspControllerChild::RecvOnDisconnected for track %d reason = 0x%x", index, reason));
|
||||
if (mListener) {
|
||||
@ -186,6 +206,7 @@ RtspControllerChild::RecvOnDisconnected(
|
||||
bool
|
||||
RtspControllerChild::RecvAsyncOpenFailed(const nsresult& reason)
|
||||
{
|
||||
StopPlayAndPauseTimer();
|
||||
DisallowIPC();
|
||||
LOG(("RtspControllerChild::RecvAsyncOpenFailed reason = 0x%x", reason));
|
||||
if (mListener) {
|
||||
@ -234,8 +255,6 @@ enum IPCEvent
|
||||
SendPlayEvent,
|
||||
SendPauseEvent,
|
||||
SendSeekEvent,
|
||||
SendResumeEvent,
|
||||
SendSuspendEvent,
|
||||
SendStopEvent,
|
||||
SendPlaybackEndedEvent
|
||||
};
|
||||
@ -275,10 +294,6 @@ public:
|
||||
rv = mController->SendPause();
|
||||
} else if (mEvent == SendSeekEvent) {
|
||||
rv = mController->SendSeek(mSeekTime);
|
||||
} else if (mEvent == SendResumeEvent) {
|
||||
rv = mController->SendResume();
|
||||
} else if (mEvent == SendSuspendEvent) {
|
||||
rv = mController->SendSuspend();
|
||||
} else if (mEvent == SendStopEvent) {
|
||||
rv = mController->SendStop();
|
||||
} else if (mEvent == SendPlaybackEndedEvent) {
|
||||
@ -305,14 +320,30 @@ RtspControllerChild::Play(void)
|
||||
{
|
||||
LOG(("RtspControllerChild::Play()"));
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
if (!OKToSendIPC() || !SendPlay()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
MutexAutoLock lock(mTimerLock);
|
||||
// Cancel the pause timer if it is active because successive pause-play in a
|
||||
// short duration is unncessary but could impair playback smoothing.
|
||||
if (mPauseTimer) {
|
||||
mPauseTimer->Cancel();
|
||||
mPauseTimer = nullptr;
|
||||
}
|
||||
|
||||
// Start a timer to delay the play operation for a short duration.
|
||||
if (!mPlayTimer) {
|
||||
mPlayTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (!mPlayTimer) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
} else {
|
||||
nsresult rv = NS_DispatchToMainThread(
|
||||
new SendIPCEvent(this, SendPlayEvent));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// We have to dispatch the timer callback to the main thread because the
|
||||
// decoder thread is a thread from nsIThreadPool and cannot be the timer
|
||||
// target. Furthermore, IPC send functions should only be called from the
|
||||
// main thread.
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
mPlayTimer->SetTarget(mainThread);
|
||||
mPlayTimer->InitWithFuncCallback(
|
||||
RtspControllerChild::PlayTimerCallback,
|
||||
this, kRtspCommandDelayMs,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -323,14 +354,29 @@ RtspControllerChild::Pause(void)
|
||||
{
|
||||
LOG(("RtspControllerChild::Pause()"));
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
if (!OKToSendIPC() || !SendPause()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
MutexAutoLock lock(mTimerLock);
|
||||
// Cancel the play timer if it is active because successive play-pause in a
|
||||
// shrot duration is unnecessary but could impair playback smoothing.
|
||||
if (mPlayTimer) {
|
||||
mPlayTimer->Cancel();
|
||||
mPlayTimer = nullptr;
|
||||
}
|
||||
|
||||
// Start a timer to delay the pause operation for a short duration.
|
||||
if (!mPauseTimer) {
|
||||
mPauseTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (!mPauseTimer) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
} else {
|
||||
nsresult rv = NS_DispatchToMainThread(
|
||||
new SendIPCEvent(this, SendPauseEvent));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// We have to dispatch the timer callback to the main thread because the
|
||||
// decoder thread is a thread from nsIThreadPool and cannot be the timer
|
||||
// target.
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
mPauseTimer->SetTarget(mainThread);
|
||||
mPauseTimer->InitWithFuncCallback(
|
||||
RtspControllerChild::PauseTimerCallback,
|
||||
this, kRtspCommandDelayMs,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -343,15 +389,7 @@ RtspControllerChild::Resume(void)
|
||||
NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (!--mSuspendCount) {
|
||||
if (NS_IsMainThread()) {
|
||||
if (!OKToSendIPC() || !SendResume()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
nsresult rv = NS_DispatchToMainThread(
|
||||
new SendIPCEvent(this, SendResumeEvent));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return Play();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -363,15 +401,7 @@ RtspControllerChild::Suspend(void)
|
||||
LOG(("RtspControllerChild::Suspend()"));
|
||||
|
||||
if (!mSuspendCount++) {
|
||||
if (NS_IsMainThread()) {
|
||||
if (!OKToSendIPC() || !SendSuspend()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
nsresult rv = NS_DispatchToMainThread(
|
||||
new SendIPCEvent(this, SendSuspendEvent));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return Pause();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -399,6 +429,7 @@ NS_IMETHODIMP
|
||||
RtspControllerChild::Stop()
|
||||
{
|
||||
LOG(("RtspControllerChild::Stop()"));
|
||||
StopPlayAndPauseTimer();
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
if (!OKToSendIPC() || !SendStop()) {
|
||||
@ -542,5 +573,44 @@ RtspControllerChild::AsyncOpen(nsIStreamingProtocolListener *aListener)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// RtspControllerChild static member methods
|
||||
//-----------------------------------------------------------------------------
|
||||
//static
|
||||
void
|
||||
RtspControllerChild::PlayTimerCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
MOZ_ASSERT(aTimer);
|
||||
MOZ_ASSERT(aClosure);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RtspControllerChild *self = static_cast<RtspControllerChild*>(aClosure);
|
||||
|
||||
MutexAutoLock lock(self->mTimerLock);
|
||||
if (!self->mPlayTimer || !self->OKToSendIPC()) {
|
||||
return;
|
||||
}
|
||||
self->SendPlay();
|
||||
self->mPlayTimer = nullptr;
|
||||
}
|
||||
|
||||
//static
|
||||
void
|
||||
RtspControllerChild::PauseTimerCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
MOZ_ASSERT(aTimer);
|
||||
MOZ_ASSERT(aClosure);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RtspControllerChild *self = static_cast<RtspControllerChild*>(aClosure);
|
||||
|
||||
MutexAutoLock lock(self->mTimerLock);
|
||||
if (!self->mPauseTimer || !self->OKToSendIPC()) {
|
||||
return;
|
||||
}
|
||||
self->SendPause();
|
||||
self->mPauseTimer = nullptr;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/net/RtspChannelChild.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
@ -52,6 +54,10 @@ class RtspControllerChild : public nsIStreamingProtocolController
|
||||
void AllowIPC();
|
||||
void DisallowIPC();
|
||||
|
||||
// These callbacks will be called when mPlayTimer/mPauseTimer fires.
|
||||
static void PlayTimerCallback(nsITimer *aTimer, void *aClosure);
|
||||
static void PauseTimerCallback(nsITimer *aTimer, void *aClosure);
|
||||
|
||||
private:
|
||||
bool mIPCOpen;
|
||||
// The intention of this variable is just to avoid any IPC message to be sent
|
||||
@ -73,6 +79,16 @@ class RtspControllerChild : public nsIStreamingProtocolController
|
||||
uint32_t mSuspendCount;
|
||||
// Detach channel-controller relationship.
|
||||
void ReleaseChannel();
|
||||
// This lock protects mPlayTimer and mPauseTimer.
|
||||
Mutex mTimerLock;
|
||||
// Timers to delay the play and pause operations.
|
||||
// They are used for optimization and to avoid sending unnecessary requests to
|
||||
// the server.
|
||||
nsCOMPtr<nsITimer> mPlayTimer;
|
||||
nsCOMPtr<nsITimer> mPauseTimer;
|
||||
// Timers should be stopped if we are going to terminate, such as when
|
||||
// receiving Stop command or OnDisconnected event.
|
||||
void StopPlayAndPauseTimer();
|
||||
};
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -3,7 +3,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Definitions used by constants.js.
|
||||
weave_version := 1.37.0
|
||||
weave_version := 1.38.0
|
||||
weave_id := {340c2bbc-ce74-4362-90b5-7c26312808ef}
|
||||
|
||||
# Preprocess files.
|
||||
|
@ -11,7 +11,7 @@ interface nsIFile;
|
||||
interface nsIInterfaceRequestor;
|
||||
interface nsIArray;
|
||||
|
||||
[scriptable, uuid(4bde6754-406a-45d1-b18e-dc685adc1db4)]
|
||||
[scriptable, uuid(e7bcc22c-e9fc-4e7d-88b9-7482399b322d)]
|
||||
interface nsIParentalControlsService : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -26,6 +26,8 @@ interface nsIParentalControlsService : nsISupports
|
||||
const short ADD_CONTACT = 7; // Add contacts to the system database
|
||||
const short SET_IMAGE = 8; // Setting images as wall paper
|
||||
const short MODIFY_ACCOUNTS = 9; // Modifying system accounts
|
||||
const short REMOTE_DEBUGGING = 10; // Remote debugging
|
||||
const short IMPORT_SETTINGS = 11; // Importing settings from other apps
|
||||
|
||||
/**
|
||||
* @returns true if the current user account has parental controls
|
||||
|
@ -21,7 +21,7 @@ namespace mozilla {
|
||||
*/
|
||||
struct Module
|
||||
{
|
||||
static const unsigned int kVersion = 35;
|
||||
static const unsigned int kVersion = 36;
|
||||
|
||||
struct CIDEntry;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user