Merge m-c to inbound, a=merge CLOSED TREE

This commit is contained in:
Wes Kocher 2015-07-10 16:20:27 -07:00
commit 87ca3721a1
86 changed files with 496 additions and 312 deletions

View File

@ -15,15 +15,15 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ad76c159c641c977d9140c5fedea84aea04e0e60"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e4b63559eba364892867eb381c3002d6518e5d6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="47f48a42502b1c694db2b162011a67a2ff888c5d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -15,15 +15,15 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ad76c159c641c977d9140c5fedea84aea04e0e60"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e4b63559eba364892867eb381c3002d6518e5d6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="47f48a42502b1c694db2b162011a67a2ff888c5d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -19,12 +19,12 @@
<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="ad76c159c641c977d9140c5fedea84aea04e0e60"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e4b63559eba364892867eb381c3002d6518e5d6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>

View File

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ad76c159c641c977d9140c5fedea84aea04e0e60"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e4b63559eba364892867eb381c3002d6518e5d6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="47f48a42502b1c694db2b162011a67a2ff888c5d"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -15,15 +15,15 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ad76c159c641c977d9140c5fedea84aea04e0e60"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e4b63559eba364892867eb381c3002d6518e5d6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="47f48a42502b1c694db2b162011a67a2ff888c5d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>

View File

@ -15,15 +15,15 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ad76c159c641c977d9140c5fedea84aea04e0e60"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e4b63559eba364892867eb381c3002d6518e5d6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="47f48a42502b1c694db2b162011a67a2ff888c5d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
<!-- Stock Android things -->
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>

View File

@ -19,12 +19,12 @@
<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="ad76c159c641c977d9140c5fedea84aea04e0e60"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e4b63559eba364892867eb381c3002d6518e5d6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>

View File

@ -15,15 +15,15 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ad76c159c641c977d9140c5fedea84aea04e0e60"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e4b63559eba364892867eb381c3002d6518e5d6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="47f48a42502b1c694db2b162011a67a2ff888c5d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "ad76c159c641c977d9140c5fedea84aea04e0e60",
"git_revision": "e4b63559eba364892867eb381c3002d6518e5d6a",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "5965f93d5645b666c209e6f3e339426e302d163c",
"revision": "70b3c9f4f6e717231709cfe1df0dc5bb2572c465",
"repo_path": "integration/gaia-central"
}

View File

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ad76c159c641c977d9140c5fedea84aea04e0e60"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e4b63559eba364892867eb381c3002d6518e5d6a"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="47f48a42502b1c694db2b162011a67a2ff888c5d"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -15,15 +15,15 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ad76c159c641c977d9140c5fedea84aea04e0e60"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e4b63559eba364892867eb381c3002d6518e5d6a"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="47f48a42502b1c694db2b162011a67a2ff888c5d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
<!-- Stock Android things -->
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>

View File

@ -165,7 +165,7 @@
if (err == "sslv3Used") {
var learnMoreText = document.getElementById("learn_more_ssl3");
errTitle.setAttribute("sslv3", "true");
document.getElementById("errorTitle").setAttribute("sslv3", "true");
var retryBtn = document.getElementById("errorTryAgain");
retryBtn.textContent = learnMoreText.textContent;

View File

@ -286,6 +286,7 @@ loop.roomViews = (function(mozL10n) {
var DesktopRoomEditContextView = React.createClass({displayName: "DesktopRoomEditContextView",
mixins: [React.addons.LinkedStateMixin],
maxRoomNameLength: 124,
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
@ -510,6 +511,7 @@ loop.roomViews = (function(mozL10n) {
value: location}),
React.createElement("form", {onSubmit: this.handleFormSubmit},
React.createElement("input", {className: "room-context-name",
maxLength: this.maxRoomNameLength,
onKeyDown: this.handleTextareaKeyDown,
placeholder: mozL10n.get("context_edit_name_placeholder"),
type: "text",

View File

@ -286,6 +286,7 @@ loop.roomViews = (function(mozL10n) {
var DesktopRoomEditContextView = React.createClass({
mixins: [React.addons.LinkedStateMixin],
maxRoomNameLength: 124,
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
@ -510,6 +511,7 @@ loop.roomViews = (function(mozL10n) {
value={location} />
<form onSubmit={this.handleFormSubmit}>
<input className="room-context-name"
maxLength={this.maxRoomNameLength}
onKeyDown={this.handleTextareaKeyDown}
placeholder={mozL10n.get("context_edit_name_placeholder")}
type="text"

View File

@ -43,7 +43,6 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
* @param {Object}
*/
function setRootObject(obj) {
console.log("loop.crpyto.mixins: rootObject set to " + obj);
rootObject = obj;
}

View File

@ -283,6 +283,7 @@ loop.shared.views = (function(_, mozL10n) {
propTypes: {
audio: React.PropTypes.object,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
initiate: React.PropTypes.bool,
isDesktop: React.PropTypes.bool,
model: React.PropTypes.object.isRequired,
@ -482,6 +483,7 @@ loop.shared.views = (function(_, mozL10n) {
),
React.createElement(ConversationToolbar, {
audio: this.state.audio,
dispatcher: this.props.dispatcher,
hangup: this.hangup,
publishStream: this.publishStream,
video: this.state.video})
@ -498,7 +500,6 @@ loop.shared.views = (function(_, mozL10n) {
mixins: [Backbone.Events],
propTypes: {
key: React.PropTypes.number.isRequired,
notification: React.PropTypes.object.isRequired
},
@ -506,8 +507,7 @@ loop.shared.views = (function(_, mozL10n) {
var notification = this.props.notification;
return (
React.createElement("div", {className: "notificationContainer"},
React.createElement("div", {className: "alert alert-" + notification.get("level"),
key: this.props.key},
React.createElement("div", {className: "alert alert-" + notification.get("level")},
React.createElement("span", {className: "message"}, notification.get("message"))
),
React.createElement("div", {className: "detailsBar details-" + notification.get("level"),
@ -571,7 +571,6 @@ loop.shared.views = (function(_, mozL10n) {
this.props.notifications.map(function(notification, key) {
return React.createElement(NotificationView, {key: key, notification: notification});
})
)
);
}

View File

@ -283,6 +283,7 @@ loop.shared.views = (function(_, mozL10n) {
propTypes: {
audio: React.PropTypes.object,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
initiate: React.PropTypes.bool,
isDesktop: React.PropTypes.bool,
model: React.PropTypes.object.isRequired,
@ -482,6 +483,7 @@ loop.shared.views = (function(_, mozL10n) {
</div>
<ConversationToolbar
audio={this.state.audio}
dispatcher={this.props.dispatcher}
hangup={this.hangup}
publishStream={this.publishStream}
video={this.state.video} />
@ -498,7 +500,6 @@ loop.shared.views = (function(_, mozL10n) {
mixins: [Backbone.Events],
propTypes: {
key: React.PropTypes.number.isRequired,
notification: React.PropTypes.object.isRequired
},
@ -506,8 +507,7 @@ loop.shared.views = (function(_, mozL10n) {
var notification = this.props.notification;
return (
<div className="notificationContainer">
<div className={"alert alert-" + notification.get("level")}
key={this.props.key}>
<div className={"alert alert-" + notification.get("level")}>
<span className="message">{notification.get("message")}</span>
</div>
<div className={"detailsBar details-" + notification.get("level")}
@ -567,11 +567,10 @@ loop.shared.views = (function(_, mozL10n) {
render: function() {
return (
<div className="messages">{
this.props.notifications.map(function(notification, key) {
<div className="messages">
{this.props.notifications.map(function(notification, key) {
return <NotificationView key={key} notification={notification} />;
})
}
})}
</div>
);
}

View File

@ -580,6 +580,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
propTypes: {
conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel)
.isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
onAfterFeedbackReceived: React.PropTypes.func.isRequired,
sdk: React.PropTypes.object.isRequired
},
@ -594,6 +595,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
onAfterFeedbackReceived: this.props.onAfterFeedbackReceived}),
React.createElement(sharedViews.ConversationView, {
audio: {enabled: false, visible: false},
dispatcher: this.props.dispatcher,
initiate: false,
model: this.props.conversation,
sdk: this.props.sdk,
@ -721,6 +723,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
currentStatus: mozL10n.get("status_in_conversation")});
return (
React.createElement(sharedViews.ConversationView, {
dispatcher: this.props.dispatcher,
initiate: true,
model: this.props.conversation,
sdk: this.props.sdk,
@ -731,6 +734,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
return (
React.createElement(EndedConversationView, {
conversation: this.props.conversation,
dispatcher: this.props.dispatcher,
onAfterFeedbackReceived: this.resetCallStatus(),
sdk: this.props.sdk})
);

View File

@ -580,6 +580,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
propTypes: {
conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel)
.isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
onAfterFeedbackReceived: React.PropTypes.func.isRequired,
sdk: React.PropTypes.object.isRequired
},
@ -594,6 +595,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
onAfterFeedbackReceived={this.props.onAfterFeedbackReceived} />
<sharedViews.ConversationView
audio={{enabled: false, visible: false}}
dispatcher={this.props.dispatcher}
initiate={false}
model={this.props.conversation}
sdk={this.props.sdk}
@ -721,6 +723,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
currentStatus: mozL10n.get("status_in_conversation")});
return (
<sharedViews.ConversationView
dispatcher={this.props.dispatcher}
initiate={true}
model={this.props.conversation}
sdk={this.props.sdk}
@ -731,6 +734,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
return (
<EndedConversationView
conversation={this.props.conversation}
dispatcher={this.props.dispatcher}
onAfterFeedbackReceived={this.resetCallStatus()}
sdk={this.props.sdk} />
);

View File

@ -20,6 +20,7 @@ describe("loop.store.ActiveRoomStore", function () {
dispatcher = new loop.Dispatcher();
sandbox.stub(dispatcher, "dispatch");
sandbox.stub(window, "close");
fakeMozLoop = {
setLoopPref: sinon.stub(),
@ -1252,6 +1253,15 @@ describe("loop.store.ActiveRoomStore", function () {
store.setStoreState({
screenSharingState: SCREEN_SHARE_STATES.ACTIVE
});
// Stub to prevent errors surfacing in the console.
sandbox.stub(window.console, "error");
});
it("should log an error in the console", function() {
listener(new Error("foo"));
sinon.assert.calledOnce(console.error);
});
it("should update the SDK driver when a new window id is received", function() {
@ -1581,6 +1591,24 @@ describe("loop.store.ActiveRoomStore", function () {
}
}));
});
it("should call close window", function() {
var fakeRoomData = {
decryptedContext: {
description: "fakeDescription",
roomName: "fakeName",
urls: {
fake: "url"
}
},
roomOwner: "you",
roomUrl: "original"
};
fakeMozLoop.rooms.on.callArgWith(1, "update", fakeRoomData);
sinon.assert.calledOnce(window.close);
});
});
describe("delete:{roomToken}", function() {

View File

@ -397,6 +397,8 @@ describe("loop.store.ConversationStore", function () {
new sharedActions.ConnectCall({sessionData: fakeSessionData}));
sandbox.stub(dispatcher, "dispatch");
// This is already covered by a test. Stub just prevents console msgs.
sandbox.stub(window.console, "error");
});
it("should dispatch a connection progress action on success", function(done) {
@ -521,6 +523,7 @@ describe("loop.store.ConversationStore", function () {
describe("server response handling", function() {
beforeEach(function() {
sandbox.stub(dispatcher, "dispatch");
sandbox.stub(window.console, "error");
});
it("should dispatch a connect call action on success", function() {
@ -692,6 +695,7 @@ describe("loop.store.ConversationStore", function () {
describe("WebSocket connection result", function() {
beforeEach(function() {
sandbox.stub(window.console, "error");
store.connectCall(
new sharedActions.ConnectCall({sessionData: fakeSessionData}));
@ -715,6 +719,18 @@ describe("loop.store.ConversationStore", function () {
});
});
it("should log an error when connection fails", function(done) {
rejectConnectPromise();
connectPromise.then(function() {
done(new Error("Promise not reject"));
}, function() {
checkFailures(done, function() {
sinon.assert.calledOnce(console.error);
});
});
});
it("should dispatch a connection failure action on failure", function(done) {
rejectConnectPromise();
@ -993,6 +1009,17 @@ describe("loop.store.ConversationStore", function () {
});
describe("#setMute", function() {
beforeEach(function() {
dispatcher.dispatch(
// Setup store to prevent console warnings.
new sharedActions.SetupWindowData({
windowId: "123456",
type: "outgoing",
contact: contact,
callType: sharedUtils.CALL_TYPES.AUDIO_VIDEO
}));
});
it("should save the mute state for the audio stream", function() {
store.setStoreState({"audioMuted": false});

View File

@ -96,7 +96,7 @@
describe("Unexpected Warnings Check", function() {
it("should long only the warnings we expect", function() {
chai.expect(caughtWarnings.length).to.eql(73);
chai.expect(caughtWarnings.length).to.eql(0);
});
});

View File

@ -380,6 +380,10 @@ describe("loop.OTSdkDriver", function () {
});
describe("On connection complete", function() {
beforeEach(function() {
sandbox.stub(window.console, "error");
});
it("should publish the stream if the publisher is ready", function() {
driver._publisherReady = true;
session.connect.callsArg(2);
@ -408,6 +412,21 @@ describe("loop.OTSdkDriver", function () {
}));
});
it("should log an error message and error object", function() {
session.connect.callsArgWith(2, {
title: "Fake",
code: OT.ExceptionCodes.CONNECT_FAILED
});
driver.connectSession(sessionData);
sinon.assert.calledOnce(console.error);
sinon.assert.calledWithExactly(console.error, sinon.match.string, {
title: "Fake",
code: OT.ExceptionCodes.CONNECT_FAILED
});
});
it("should dispatch connectionFailure if connecting failed", function() {
session.connect.callsArgWith(2, new Error("Failure"));

View File

@ -143,7 +143,11 @@ describe("loop.shared.views.TextChatView", function () {
it("should not render a timestamp", function() {
view = mountTestComponent({
showTimestamp: false
showTimestamp: false,
timestamp: "2015-06-23T22:48:39.738Z",
type: CHAT_MESSAGE_TYPES.RECEIVED,
contentType: CHAT_CONTENT_TYPES.TEXT,
message: "foo"
});
var node = view.getDOMNode();
@ -152,7 +156,11 @@ describe("loop.shared.views.TextChatView", function () {
it("should render a timestamp", function() {
view = mountTestComponent({
showTimestamp: true
showTimestamp: true,
timestamp: "2015-06-23T22:48:39.738Z",
type: CHAT_MESSAGE_TYPES.RECEIVED,
contentType: CHAT_CONTENT_TYPES.TEXT,
message: "foo"
});
var node = view.getDOMNode();
@ -248,7 +256,7 @@ describe("loop.shared.views.TextChatView", function () {
type: CHAT_MESSAGE_TYPES.RECEIVED,
contentType: CHAT_CONTENT_TYPES.TEXT,
message: "Is it me you're looking for?",
sentTimestamp: "2015-06-25T17:53:55.357Z"
receivedTimestamp: "2015-06-25T17:53:55.357Z"
}]
});
node = view.getDOMNode();
@ -259,22 +267,29 @@ describe("loop.shared.views.TextChatView", function () {
});
describe("TextChatView", function() {
var view;
var view, fakeServer;
function mountTestComponent(extraProps) {
var props = _.extend({
dispatcher: dispatcher,
showRoomName: false,
useDesktopPaths: false
useDesktopPaths: false,
showAlways: true
}, extraProps);
return TestUtils.renderIntoDocument(
React.createElement(loop.shared.views.chat.TextChatView, props));
}
beforeEach(function() {
// Fake server to catch all XHR requests.
fakeServer = sinon.fakeServer.create();
store.setStoreState({ textChatEnabled: true });
});
afterEach(function() {
fakeServer.restore();
});
it("should show timestamps from msgs sent more than 1 min apart", function() {
view = mountTestComponent();
@ -358,7 +373,7 @@ describe("loop.shared.views.TextChatView", function () {
store.sendTextChatMessage({
contentType: CHAT_CONTENT_TYPES.TEXT,
message: "Foo",
timestamp: 0
sentTimestamp: "2015-06-25T17:53:55.357Z"
});
expect(node.querySelector(".sent")).to.not.eql(null);

View File

@ -313,6 +313,11 @@ describe("loop.shared.utils", function() {
});
describe("#formatURL", function() {
beforeEach(function() {
// Stub to prevent console messages.
sandbox.stub(window.console, "error");
});
it("should decode encoded URIs", function() {
expect(sharedUtils.formatURL("http://invalid.com/?a=Foo%20Bar"))
.eql({
@ -335,6 +340,12 @@ describe("loop.shared.utils", function() {
it("should return null if it the url is not valid", function() {
expect(sharedUtils.formatURL("hinvalid//url")).eql(null);
});
it("should log an error message to the console", function() {
sharedUtils.formatURL("hinvalid//url");
sinon.assert.calledOnce(console.error);
});
});
describe("#composeCallUrlEmail", function() {
@ -365,6 +376,8 @@ describe("loop.shared.utils", function() {
composeEmail: composeEmail,
telemetryAddValue: telemetryAddValue
};
sandbox.stub(window.console, "error");
});
it("should compose a call url email", function() {
@ -388,6 +401,12 @@ describe("loop.shared.utils", function() {
sinon.assert.calledOnce(telemetryAddValue, "LOOP_SHARING_ROOM_URL", 2);
});
it("should log an error for invalid URLs", function() {
sharedUtils.composeCallUrlEmail("http://invalid", "fake@invalid.tld");
sinon.assert.calledOnce(console.error);
});
});
describe("#btoa", function() {

View File

@ -88,7 +88,7 @@
describe("Unexpected Warnings Check", function() {
it("should long only the warnings we expect", function() {
chai.expect(caughtWarnings.length).to.eql(33);
chai.expect(caughtWarnings.length).to.eql(15);
});
});

View File

@ -1068,6 +1068,7 @@ describe("loop.webapp", function() {
React.createElement(
loop.webapp.EndedConversationView, {
conversation: conversation,
dispatcher: dispatcher,
sdk: {},
onAfterFeedbackReceived: function(){}
}));

View File

@ -1315,7 +1315,7 @@
// This simulates the mocha layout for errors which means we can run
// this alongside our other unit tests but use the same harness.
var expectedWarningsCount = 28;
var expectedWarningsCount = 24;
var warningsMismatch = caughtWarnings.length !== expectedWarningsCount;
if (uncaughtError || warningsMismatch) {
$("#results").append("<div class='failures'><em>" +

View File

@ -1315,7 +1315,7 @@
// This simulates the mocha layout for errors which means we can run
// this alongside our other unit tests but use the same harness.
var expectedWarningsCount = 28;
var expectedWarningsCount = 24;
var warningsMismatch = caughtWarnings.length !== expectedWarningsCount;
if (uncaughtError || warningsMismatch) {
$("#results").append("<div class='failures'><em>" +

View File

@ -715,7 +715,11 @@ Rule.prototype = {
previewPropertyValue: function(aProperty, aValue, aPriority) {
let modifications = this.style.startModifyingProperties();
modifications.setProperty(aProperty.name, aValue, aPriority);
modifications.apply();
modifications.apply().then(() => {
// Ensure dispatching a ruleview-changed event
// also for previews
this.elementStyle._changed();
});
},
/**

View File

@ -40,7 +40,7 @@ function* testCancelNew(view) {
let elementRuleEditor = getRuleViewRuleEditor(view, 0);
info("Focusing a new property name in the rule-view");
let editor = yield focusEditableField(elementRuleEditor.closeBrace);
let editor = yield focusEditableField(view, elementRuleEditor.closeBrace);
is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "The new property editor got focused");
info("Bluring the editor input");

View File

@ -33,22 +33,19 @@ add_task(function*() {
let elementRuleEditor = getRuleViewRuleEditor(view, 1);
info("Focusing a new property name in the rule-view");
let editor = yield focusEditableField(elementRuleEditor.closeBrace);
let editor = yield focusEditableField(view, elementRuleEditor.closeBrace);
is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "The new property editor got focused.");
let input = editor.input;
info("Entering a value in the property name editor");
let onModifications = elementRuleEditor.rule._applyingModifications;
input.value = "color";
yield onModifications;
editor.input.value = "color";
info("Pressing return to commit and focus the new value field");
let onValueFocus = once(elementRuleEditor.element, "focus", true);
onModifications = elementRuleEditor.rule._applyingModifications;
let onRuleViewChanged = view.once("ruleview-changed");
EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
yield onValueFocus;
yield onModifications;
yield onRuleViewChanged;
// Getting the new value editor after focus
editor = inplaceEditor(view.doc.activeElement);
@ -62,17 +59,17 @@ add_task(function*() {
editor.input.value = "red";
info("Escaping out of the field");
onModifications = elementRuleEditor.rule._applyingModifications;
onRuleViewChanged = view.once("ruleview-changed");
EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView);
yield onModifications;
yield onRuleViewChanged;
info("Checking that the previous field is focused");
let focusedElement = inplaceEditor(elementRuleEditor.rule.textProps[0].editor.valueSpan).input;
is(focusedElement, focusedElement.ownerDocument.activeElement, "Correct element has focus");
onModifications = elementRuleEditor.rule._applyingModifications;
onRuleViewChanged = view.once("ruleview-changed");
EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView);
yield onModifications;
yield onRuleViewChanged;
is(elementRuleEditor.rule.textProps.length, 1, "Removed the new text property.");
is(elementRuleEditor.propertyList.children.length, 1, "Removed the property editor.");

View File

@ -27,7 +27,7 @@ function* testCancelNew(inspector, ruleView) {
// declaration, but leave it empty.
let elementRuleEditor = getRuleViewRuleEditor(ruleView, 0);
let editor = yield focusEditableField(elementRuleEditor.closeBrace);
let editor = yield focusEditableField(ruleView, elementRuleEditor.closeBrace);
is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
"Property editor is focused");
@ -46,7 +46,7 @@ function* testCancelNewOnEscape(inspector, ruleView) {
// declaration, add some text, then press escape.
let elementRuleEditor = getRuleViewRuleEditor(ruleView, 0);
let editor = yield focusEditableField(elementRuleEditor.closeBrace);
let editor = yield focusEditableField(ruleView, elementRuleEditor.closeBrace);
is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "Next focused editor should be the new property editor.");

View File

@ -27,7 +27,7 @@ function* testCreateNew(ruleView) {
let elementRuleEditor = getRuleViewRuleEditor(ruleView, 0);
info("Focusing a new property name in the rule-view");
let editor = yield focusEditableField(elementRuleEditor.closeBrace);
let editor = yield focusEditableField(ruleView, elementRuleEditor.closeBrace);
is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
"Next focused editor should be the new property editor.");

View File

@ -42,7 +42,7 @@ function* testCreateNew(view) {
let elementRuleEditor = getRuleViewRuleEditor(view, 0);
info("Focusing a new property name in the rule-view");
let editor = yield focusEditableField(elementRuleEditor.closeBrace);
let editor = yield focusEditableField(view, elementRuleEditor.closeBrace);
is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "The new property editor got focused");
let input = editor.input;

View File

@ -29,7 +29,7 @@ add_task(function*() {
function* testCreateNew(inspector, ruleView) {
// Create a new property.
let elementRuleEditor = getRuleViewRuleEditor(ruleView, 0);
let editor = yield focusEditableField(elementRuleEditor.closeBrace);
let editor = yield focusEditableField(ruleView, elementRuleEditor.closeBrace);
is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
"Next focused editor should be the new property editor.");

View File

@ -79,8 +79,7 @@ function* addNewRule(inspector, view, method) {
view.addRuleButton.click();
}
info("Waiting for rule view to change");
let onRuleViewChanged = once(view, "ruleview-changed");
yield onRuleViewChanged;
yield view.once("ruleview-changed");
}
function* testNewRule(view, expected, index) {
@ -96,7 +95,10 @@ function* testNewRule(view, expected, index) {
"Selector text value is as expected: " + expected);
info("Adding new properties to new rule: " + expected)
let onRuleViewChanged = view.once("ruleview-changed");
idRuleEditor.addProperty("font-weight", "bold", "");
yield onRuleViewChanged;
let textProps = idRuleEditor.rule.textProps;
let lastRule = textProps[textProps.length - 1];
is(lastRule.name, "font-weight", "Last rule name is font-weight");

View File

@ -71,7 +71,7 @@ function* testEditSelector(view, name) {
let idRuleEditor = getRuleViewRuleEditor(view, 1);
info("Focusing an existing selector name in the rule-view");
let editor = yield focusEditableField(idRuleEditor.selectorText);
let editor = yield focusEditableField(view, idRuleEditor.selectorText);
is(inplaceEditor(idRuleEditor.selectorText), editor,
"The selector editor got focused");

View File

@ -39,7 +39,7 @@ function* testImageTooltipAfterColorChange(swatch, url, ruleView) {
let onShown = picker.tooltip.once("shown");
swatch.click();
yield onShown;
yield simulateColorPickerChange(picker, [0, 0, 0, 1], {
yield simulateColorPickerChange(ruleView, picker, [0, 0, 0, 1], {
element: content.document.body,
name: "backgroundImage",
value: 'url("chrome://global/skin/icons/warning-64.png"), linear-gradient(rgb(0, 0, 0), rgb(255, 0, 102) 400px)'

View File

@ -36,7 +36,7 @@ function* testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) {
swatch.click();
yield onShown;
yield simulateColorPickerChange(picker, [0, 0, 0, 1], {
yield simulateColorPickerChange(ruleView, picker, [0, 0, 0, 1], {
element: content.document.body,
name: "backgroundColor",
value: "rgb(0, 0, 0)"

View File

@ -32,7 +32,7 @@ function* testPressingEnterCommitsChanges(swatch, ruleView) {
swatch.click();
yield onShown;
yield simulateColorPickerChange(cPicker, [0, 255, 0, .5], {
yield simulateColorPickerChange(ruleView, cPicker, [0, 255, 0, .5], {
element: content.document.body,
name: "borderLeftColor",
value: "rgba(0, 255, 0, 0.5)"

View File

@ -62,13 +62,18 @@ function* testPickingNewColor(view) {
swatchEl.click();
yield onShown;
yield simulateColorPickerChange(cPicker, [1, 1, 1, 1]);
let change = {
element: content.document.body,
name: "backgroundImage",
value: "linear-gradient(to left, rgb(1, 1, 1) 25%, rgb(51, 51, 51) 95%, rgb(0, 0, 0) 100%)"
};
yield simulateColorPickerChange(view, cPicker, [1, 1, 1, 1], change);
is(swatchEl.style.backgroundColor, "rgb(1, 1, 1)",
"The color swatch's background was updated");
is(colorEl.textContent, "#010101", "The color text was updated");
is(content.getComputedStyle(content.document.body).backgroundImage,
"linear-gradient(to left, rgb(255, 0, 102) 25%, rgb(51, 51, 51) 95%, rgb(0, 0, 0) 100%)",
"linear-gradient(to left, rgb(1, 1, 1) 25%, rgb(51, 51, 51) 95%, rgb(0, 0, 0) 100%)",
"The gradient has been updated correctly");
cPicker.hide();

View File

@ -54,7 +54,7 @@ function* testSimpleMultipleColorChanges(inspector, ruleView) {
{rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
];
for (let {rgba, computed} of colors) {
yield simulateColorPickerChange(picker, rgba, {
yield simulateColorPickerChange(ruleView, picker, rgba, {
element: content.document.querySelector("p"),
name: "color",
value: computed
@ -82,7 +82,7 @@ function* testComplexMultipleColorChanges(inspector, ruleView) {
{rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
];
for (let {rgba, computed} of colors) {
yield simulateColorPickerChange(picker, rgba, {
yield simulateColorPickerChange(ruleView, picker, rgba, {
element: content.document.body,
name: "backgroundColor",
value: computed
@ -115,7 +115,7 @@ function* testOverriddenMultipleColorChanges(inspector, ruleView) {
{rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
];
for (let {rgba, computed} of colors) {
yield simulateColorPickerChange(picker, rgba, {
yield simulateColorPickerChange(ruleView, picker, rgba, {
element: content.document.body,
name: "color",
value: computed

View File

@ -22,9 +22,11 @@ add_task(function*() {
let change = spectrum.once("changed");
info("Pressing mouse down over color picker.");
let onRuleViewChanged = view.once("ruleview-changed");
EventUtils.synthesizeMouseAtCenter(spectrum.dragger, {
type: "mousedown",
}, spectrum.dragger.ownerDocument.defaultView);
yield onRuleViewChanged;
let value = yield change;
info(`Color changed to ${value} on mousedown.`);
@ -41,6 +43,7 @@ add_task(function*() {
// i.e. the buttons that were pressed down between events.
info("Moving mouse over color picker without any buttons pressed.");
EventUtils.synthesizeMouse(spectrum.dragger, 10, 10, {
button: -1, // -1 = no buttons are pressed down
type: "mousemove",

View File

@ -32,7 +32,7 @@ function* testPressingEscapeRevertsChanges(swatch, ruleView) {
swatch.click();
yield onShown;
yield simulateColorPickerChange(cPicker, [0, 0, 0, 1], {
yield simulateColorPickerChange(ruleView, cPicker, [0, 0, 0, 1], {
element: content.document.body,
name: "backgroundColor",
value: "rgb(0, 0, 0)"

View File

@ -66,7 +66,7 @@ add_task(function*() {
info("Focusing the css property editable field");
let propertyName = view.doc.querySelectorAll(".ruleview-propertyname")[0];
let editor = yield focusEditableField(propertyName);
let editor = yield focusEditableField(view, propertyName);
info("Starting to test for css property completion");
for (let i = 0; i < testData.length; i ++) {

View File

@ -48,7 +48,7 @@ add_task(function*() {
info("Focusing the css property editable value");
let value = view.doc.querySelectorAll(".ruleview-propertyvalue")[0];
let editor = yield focusEditableField(value);
let editor = yield focusEditableField(view, value);
info("Starting to test for css property completion");
for (let i = 0; i < testData.length; i ++) {

View File

@ -49,7 +49,7 @@ add_task(function*() {
info("Focusing the css property editable field");
let brace = view.doc.querySelector(".ruleview-ruleclose");
let editor = yield focusEditableField(brace);
let editor = yield focusEditableField(view, brace);
info("Starting to test for css property completion");
for (let i = 0; i < testData.length; i ++) {

View File

@ -51,7 +51,7 @@ add_task(function*() {
info("Focusing a new css property editable property");
let brace = view.doc.querySelectorAll(".ruleview-ruleclose")[1];
let editor = yield focusEditableField(brace);
let editor = yield focusEditableField(view, brace);
info("Starting to test for css property completion");
for (let i = 0; i < testData.length; i ++) {

View File

@ -60,10 +60,12 @@ function* runTestData(view, {value, commitKey, modifiers, expected}) {
let propEditor = idRuleEditor.rule.textProps[0].editor;
info("Focusing the inplace editor field");
let editor = yield focusEditableField(propEditor.valueSpan);
let editor = yield focusEditableField(view, propEditor.valueSpan);
is(inplaceEditor(propEditor.valueSpan), editor, "Focused editor should be the value span.");
info("Entering test data " + value);
let onRuleViewChanged = view.once("ruleview-changed");
EventUtils.sendString(value, view.doc.defaultView);
info("Waiting for focus on the field");
@ -72,11 +74,13 @@ function* runTestData(view, {value, commitKey, modifiers, expected}) {
info("Entering the commit key " + commitKey + " " + modifiers);
EventUtils.synthesizeKey(commitKey, modifiers);
yield onBlur;
// No matter if we escape or commit the change, the preview throttle is going
// to update the property value
yield onRuleViewChanged;
if (commitKey === "VK_ESCAPE") {
is(propEditor.valueSpan.textContent, expected, "Value is as expected: " + expected);
} else {
yield once(view, "ruleview-changed");
is(propEditor.valueSpan.textContent, expected, "Value is as expected: " + expected);
}
}

View File

@ -29,7 +29,7 @@ function* editAndCheck(view) {
let newPaddingValue = "20px";
info("Focusing the inplace editor field");
let editor = yield focusEditableField(propEditor.valueSpan);
let editor = yield focusEditableField(view, propEditor.valueSpan);
is(inplaceEditor(propEditor.valueSpan), editor, "Focused editor should be the value span.");
let onPropertyChange = waitForComputedStyleProperty("#testid", null, "padding-top", newPaddingValue);

View File

@ -148,7 +148,7 @@ function* testOddCases(view) {
};
function* runIncrementTest(propertyEditor, view, tests) {
let editor = yield focusEditableField(propertyEditor.valueSpan);
let editor = yield focusEditableField(view, propertyEditor.valueSpan);
for(let test in tests) {
yield testIncrement(editor, tests[test], view, propertyEditor);
@ -167,7 +167,7 @@ function* testIncrement(editor, options, view, {ruleEditor}) {
is(input.value, options.start, "Value initialized at " + options.start);
let onModifications = ruleEditor.rule._applyingModifications;
let onRuleViewChanged = view.once("ruleview-changed");
let onKeyUp = once(input, "keyup");
let key;
key = options.down ? "VK_DOWN" : "VK_UP";
@ -175,7 +175,10 @@ function* testIncrement(editor, options, view, {ruleEditor}) {
EventUtils.synthesizeKey(key, {altKey: options.alt, shiftKey: options.shift},
view.doc.defaultView);
yield onKeyUp;
yield onModifications;
is(editor.input.value, options.end, "Value changed to " + options.end);
// Only expect a change if the value actually changed!
if (options.start !== options.end) {
yield onRuleViewChanged;
}
is(input.value, options.end, "Value changed to " + options.end);
}

View File

@ -52,7 +52,7 @@ function* testEditProperty(ruleEditor, name, value, isValid) {
let propEditor = ruleEditor.rule.textProps[0].editor;
info("Focusing an existing property name in the rule-view");
let editor = yield focusEditableField(propEditor.nameSpan, 32, 1);
let editor = yield focusEditableField(ruleEditor.ruleView, propEditor.nameSpan, 32, 1);
is(inplaceEditor(propEditor.nameSpan), editor, "The property name editor got focused");
let input = editor.input;

View File

@ -34,7 +34,7 @@ function* testEditProperty(inspector, ruleView) {
let idRuleEditor = getRuleViewRuleEditor(ruleView, 1);
let propEditor = idRuleEditor.rule.textProps[0].editor;
let editor = yield focusEditableField(propEditor.nameSpan);
let editor = yield focusEditableField(ruleView, propEditor.nameSpan);
let input = editor.input;
is(inplaceEditor(propEditor.nameSpan), editor, "Next focused editor should be the name editor.");

View File

@ -35,26 +35,25 @@ add_task(function*() {
let doc = ruleEditor.doc;
let propEditor = ruleEditor.rule.textProps[1].editor;
let editor = yield focusEditableField(propEditor.valueSpan);
let editor = yield focusEditableField(view, propEditor.valueSpan);
info("Deleting all the text out of a value field");
yield sendCharsAndWaitForFocus(ruleEditor.element, ["VK_DELETE", "VK_RETURN"]);
yield ruleEditor.rule._applyingModifications;
yield sendCharsAndWaitForFocus(view, ruleEditor.element, ["VK_DELETE", "VK_RETURN"]);
info("Pressing enter a couple times to cycle through editors");
yield sendCharsAndWaitForFocus(ruleEditor.element, ["VK_RETURN"]);
yield sendCharsAndWaitForFocus(ruleEditor.element, ["VK_RETURN"]);
yield ruleEditor.rule._applyingModifications;
yield sendCharsAndWaitForFocus(view, ruleEditor.element, ["VK_RETURN"]);
yield sendCharsAndWaitForFocus(view, ruleEditor.element, ["VK_RETURN"]);
isnot (ruleEditor.rule.textProps[1].editor.nameSpan.style.display, "none", "The name span is visible");
is (ruleEditor.rule.textProps.length, 2, "Correct number of props");
});
function* sendCharsAndWaitForFocus(element, chars) {
function* sendCharsAndWaitForFocus(view, element, chars) {
let onFocus = once(element, "focus", true);
for (let ch of chars) {
let onRuleViewChanged = view.once("ruleview-changed");
EventUtils.sendChar(ch, element.ownerDocument.defaultView);
yield onRuleViewChanged;
}
yield onFocus;
}

View File

@ -77,7 +77,7 @@ function* runTestData(inspector, view, data) {
let idRuleEditor = getRuleViewRuleEditor(view, 1);
info("Focusing an existing selector name in the rule-view");
let editor = yield focusEditableField(idRuleEditor.selectorText);
let editor = yield focusEditableField(view, idRuleEditor.selectorText);
is(inplaceEditor(idRuleEditor.selectorText), editor,
"The selector editor got focused");

View File

@ -35,7 +35,7 @@ function* testEditSelector(view, name) {
let idRuleEditor = getRuleViewRuleEditor(view, 1);
info("Focusing an existing selector name in the rule-view");
let editor = yield focusEditableField(idRuleEditor.selectorText);
let editor = yield focusEditableField(view, idRuleEditor.selectorText);
is(inplaceEditor(idRuleEditor.selectorText), editor,
"The selector editor got focused");

View File

@ -58,7 +58,7 @@ function* testEditSelector(view, name) {
getRuleViewRuleEditor(view, 1, 0);
info("Focusing an existing selector name in the rule-view");
let editor = yield focusEditableField(idRuleEditor.selectorText);
let editor = yield focusEditableField(view, idRuleEditor.selectorText);
is(inplaceEditor(idRuleEditor.selectorText), editor,
"The selector editor got focused");

View File

@ -29,7 +29,7 @@ function* testEditSelector(view, name) {
let ruleEditor = getRuleViewRuleEditor(view, 1);
info("Focusing an existing selector name in the rule-view");
let editor = yield focusEditableField(ruleEditor.selectorText);
let editor = yield focusEditableField(view, ruleEditor.selectorText);
is(inplaceEditor(ruleEditor.selectorText), editor,
"The selector editor got focused");

View File

@ -48,7 +48,7 @@ function* testEditSelector(view, name) {
let ruleEditor = getRuleViewRuleEditor(view, 1);
info("Focusing an existing selector name in the rule-view");
let editor = yield focusEditableField(ruleEditor.selectorText);
let editor = yield focusEditableField(view, ruleEditor.selectorText);
is(inplaceEditor(ruleEditor.selectorText), editor,
"The selector editor got focused");

View File

@ -38,7 +38,7 @@ function* testEditSelector(view, name) {
let ruleEditor = getRuleViewRuleEditor(view, 1);
info("Focusing an existing selector name in the rule-view");
let editor = yield focusEditableField(ruleEditor.selectorText);
let editor = yield focusEditableField(view, ruleEditor.selectorText);
is(inplaceEditor(ruleEditor.selectorText), editor,
"The selector editor got focused");
@ -70,7 +70,7 @@ function* testAddProperty(view) {
let ruleEditor = getRuleViewRuleEditor(view, 1);
info("Focusing a new property name in the rule-view");
let editor = yield focusEditableField(ruleEditor.closeBrace);
let editor = yield focusEditableField(view, ruleEditor.closeBrace);
is(inplaceEditor(ruleEditor.newPropSpan), editor,
"The new property editor got focused");
@ -81,10 +81,10 @@ function* testAddProperty(view) {
info("Pressing return to commit and focus the new value field");
let onValueFocus = once(ruleEditor.element, "focus", true);
let onModifications = ruleEditor.rule._applyingModifications;
let onRuleViewChanged = view.once("ruleview-changed");
EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
yield onValueFocus;
yield onModifications;
yield onRuleViewChanged;
// Getting the new value editor after focus
editor = inplaceEditor(view.doc.activeElement);
@ -98,10 +98,10 @@ function* testAddProperty(view) {
info("Entering a value and bluring the field to expect a rule change");
editor.input.value = "center";
let onBlur = once(editor.input, "blur");
onModifications = ruleEditor.rule._applyingModifications;
onRuleViewChanged = view.once("ruleview-changed");
editor.input.blur();
yield onBlur;
yield onModifications;
yield onRuleViewChanged;
is(textProp.value, "center", "Text prop should have been changed.");
is(textProp.overridden, false, "Property should not be overridden");

View File

@ -72,7 +72,7 @@ add_task(function*() {
ok(dropper, "dropper opened");
yield testSelect(swatch, dropper);
yield testSelect(view, swatch, dropper);
checkTelemetry();
});
@ -92,27 +92,23 @@ function testESC(swatch, dropper) {
return deferred.promise;
}
function testSelect(swatch, dropper) {
let deferred = promise.defer();
function* testSelect(view, swatch, dropper) {
let onDestroyed = dropper.once("destroy");
// the change to the content is done async after rule view change
let onRuleViewChanged = view.once("ruleview-changed");
inspectPage(dropper);
yield onDestroyed;
yield onRuleViewChanged;
dropper.once("destroy", () => {
let color = swatch.style.backgroundColor;
is(color, EXPECTED_COLOR, "swatch changed colors");
// the change to the content is done async after rule view change
executeSoon(() => {
let element = content.document.querySelector("div");
is(content.window.getComputedStyle(element).backgroundColor,
EXPECTED_COLOR,
"div's color set to body color after dropper");
deferred.resolve();
});
});
inspectPage(dropper);
return deferred.promise;
}
function clearTelemetry() {

View File

@ -18,8 +18,12 @@ add_task(function*() {
let filterTooltip = view.tooltips.filterEditor;
let onShow = filterTooltip.tooltip.once("shown");
let onRuleViewChanged = view.once("ruleview-changed");
swatch.click();
yield onShow;
// Clicking on swatch runs a preview of the current value
// and updates the rule-view
yield onRuleViewChanged;
ok(true, "The shown event was emitted after clicking on swatch");
ok(!inplaceEditor(swatch.parentNode),

View File

@ -28,8 +28,12 @@ add_task(function*() {
info("Typing ENTER to focus the next field: property value");
onFocus = once(brace.parentNode, "focus", true);
// The rule view changes twice, once for the first field to loose focus
// and a second time for the second field to gain focus
let onRuleViewChanged = view.once("ruleview-changed").then(() => view.once("ruleview-changed"));
EventUtils.sendKey("return");
yield onFocus;
yield onRuleViewChanged;
ok(true, "The value field was focused");
info("Entering a property value");
@ -38,8 +42,10 @@ add_task(function*() {
info("Typing ENTER again should focus a new property name");
onFocus = once(brace.parentNode, "focus", true);
onRuleViewChanged = view.once("ruleview-changed");
EventUtils.sendKey("return");
yield onFocus;
yield onRuleViewChanged;
ok(true, "The new property name field was focused");
getCurrentInplaceEditor(view).input.blur();
});

View File

@ -43,7 +43,7 @@ function* testLivePreviewData(data, ruleView, selector) {
let propEditor = idRuleEditor.rule.textProps[0].editor;
info("Focusing the property value inplace-editor");
let editor = yield focusEditableField(propEditor.valueSpan);
let editor = yield focusEditableField(ruleView, propEditor.valueSpan);
is(inplaceEditor(propEditor.valueSpan), editor, "The focused editor is the value");
info("Enter a value in the editor")

View File

@ -22,17 +22,35 @@ add_task(function*() {
yield testCreateNewMultiUnfinished(inspector, ruleEditor, view);
});
function waitRuleViewChanged(view, n) {
let deferred = promise.defer();
let count = 0;
let listener = function () {
if (++count == n) {
view.off("ruleview-changed", listener);
deferred.resolve();
}
}
view.on("ruleview-changed", listener);
return deferred.promise;
}
function* testCreateNewMultiUnfinished(inspector, ruleEditor, view) {
let onMutation = inspector.once("markupmutation");
// There is 6 rule-view updates, one for the rule view creation,
// one for each new property and one last for throttle update.
let onRuleViewChanged = waitRuleViewChanged(view, 6);
yield createNewRuleViewProperty(ruleEditor,
"color:blue;background : orange ; text-align:center; border-color: ");
yield onMutation;
yield onRuleViewChanged;
is(ruleEditor.rule.textProps.length, 4, "Should have created new text properties.");
is(ruleEditor.propertyList.children.length, 4, "Should have created property editors.");
EventUtils.sendString("red", view.doc.defaultView);
onRuleViewChanged = view.once("ruleview-changed");
EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
yield onRuleViewChanged;
is(ruleEditor.rule.textProps.length, 4, "Should have the same number of text properties.");
is(ruleEditor.propertyList.children.length, 5, "Should have added the changed value editor.");

View File

@ -43,7 +43,7 @@ function* modifyRuleViewWidth(value, ruleView, inspector) {
let valueSpan = getStyleRule(ruleView).querySelector(".ruleview-propertyvalue");
info("Focusing the property value to set it to edit mode");
let editor = yield focusEditableField(valueSpan.parentNode);
let editor = yield focusEditableField(ruleView, valueSpan.parentNode);
ok(editor.input, "The inplace-editor field is ready");
info("Setting the new value");

View File

@ -53,7 +53,7 @@ function* testManualEdit(inspector, view) {
let {valueSpan} = getRuleViewProperty(view, "div", "color");
let newColor = "#C9184E"
let editor = yield focusEditableField(valueSpan);
let editor = yield focusEditableField(view, valueSpan);
info("Typing new value");
let input = editor.input;
@ -86,7 +86,7 @@ function* testColorPickerEdit(inspector, view) {
let rgbaColor = [83, 183, 89, 1];
let rgbaColorText = "rgba(83, 183, 89, 1)";
yield simulateColorPickerChange(picker, rgbaColor);
yield simulateColorPickerChange(view, picker, rgbaColor);
is(swatch.parentNode.dataset.color, rgbaColorText, "data-color was updated");
view.doc.popupNode = swatch;

View File

@ -101,7 +101,7 @@ function* testTooltipAppearsEvenInEditMode(view) {
function turnToEditMode(ruleView) {
let brace = ruleView.doc.querySelector(".ruleview-ruleclose");
return focusEditableField(brace);
return focusEditableField(ruleView, brace);
}
function* testComputedView(view) {

View File

@ -81,6 +81,8 @@ function* testPickerDimension(ruleView) {
ok(panelRect.height >= h, "The panel is high enough to show the picker");
let onHidden = cPicker.tooltip.once("hidden");
let onRuleViewChanged = ruleView.once("ruleview-changed");
cPicker.hide();
yield onHidden;
yield onRuleViewChanged;
}

View File

@ -413,16 +413,31 @@ function* waitForComputedStyleProperty(selector, pseudo, name, expected) {
* focus
* @return a promise that resolves to the inplace-editor element when ready
*/
let focusEditableField = Task.async(function*(editable, xOffset=1, yOffset=1, options={}) {
let onFocus = once(editable.parentNode, "focus", true);
let focusEditableField = Task.async(function*(ruleView, editable, xOffset=1, yOffset=1, options={}) {
// Focusing the name or value input is going to fire a preview and update the rule view
let expectRuleViewUpdate =
editable.classList.contains("ruleview-propertyname") ||
editable.classList.contains("ruleview-propertyvalue");
let onRuleViewChanged;
if (expectRuleViewUpdate) {
onRuleViewChanged = ruleView.once("ruleview-changed");
}
let onFocus = once(editable.parentNode, "focus", true);
info("Clicking on editable field to turn to edit mode");
EventUtils.synthesizeMouse(editable, xOffset, yOffset, options,
editable.ownerDocument.defaultView);
let event = yield onFocus;
info("Editable field gained focus, returning the input field now");
return inplaceEditor(editable.ownerDocument.activeElement);
let onEdit = inplaceEditor(editable.ownerDocument.activeElement);
if (expectRuleViewUpdate) {
info("Waiting for rule view update");
yield onRuleViewChanged;
}
return onEdit;
});
/**
@ -709,6 +724,7 @@ function getRuleViewSelectorHighlighterIcon(view, selectorText) {
/**
* Simulate a color change in a given color picker tooltip, and optionally wait
* for a given element in the page to have its style changed as a result
* @param {RuleView} ruleView The related rule view instance
* @param {SwatchColorPickerTooltip} colorPicker
* @param {Array} newRgba The new color to be set [r, g, b, a]
* @param {Object} expectedChange Optional object that needs the following props:
@ -718,7 +734,8 @@ function getRuleViewSelectorHighlighterIcon(view, selectorText) {
* - {String} value The expected style value
* The style will be checked like so: getComputedStyle(element)[name] === value
*/
let simulateColorPickerChange = Task.async(function*(colorPicker, newRgba, expectedChange) {
let simulateColorPickerChange = Task.async(function*(ruleView, colorPicker, newRgba, expectedChange) {
let onRuleViewChanged = ruleView.once("ruleview-changed");
info("Getting the spectrum colorpicker object");
let spectrum = yield colorPicker.spectrum;
info("Setting the new color");
@ -726,6 +743,8 @@ let simulateColorPickerChange = Task.async(function*(colorPicker, newRgba, expec
info("Applying the change");
spectrum.updateUI();
spectrum.onChange();
info("Waiting for rule-view to update");
yield onRuleViewChanged;
if (expectedChange) {
info("Waiting for the style to be applied on the page");
@ -781,7 +800,7 @@ function getRuleViewRuleEditor(view, childrenIndex, nodeIndex) {
let focusNewRuleViewProperty = Task.async(function*(ruleEditor) {
info("Clicking on a close ruleEditor brace to start editing a new property");
ruleEditor.closeBrace.scrollIntoView();
let editor = yield focusEditableField(ruleEditor.closeBrace);
let editor = yield focusEditableField(ruleEditor.ruleView, ruleEditor.closeBrace);
is(inplaceEditor(ruleEditor.newPropSpan), editor, "Focused editor is the new property editor.");
is(ruleEditor.rule.textProps.length, 0, "Starting with one new text property.");

View File

@ -246,6 +246,7 @@ blocked::
{
"id": 702,
"pin": 1,
"past_impressions": {"total": 5, "daily": 1},
},
{},
{
@ -264,6 +265,12 @@ none of the following optional values:
- ``id`` - id that was provided as part of the downloaded link object (for all
types of links: directory, suggested, enhanced); not present if the tile was
created from user behavior, e.g., visiting pages
- ``past_impressions`` - number of impressions (new tab "views") a suggested
tile was shown before it was clicked, pinned or blocked. Where the "total"
counter is the overall number of impressions accumulated prior to a click action,
and "daily" counter is the number impressions occurred on same calendar day of
a click. This infomration is submitted once per a suggested tile upon click,
pin or block
- ``pinned`` - 1 if the tile is pinned; not present otherwise
- ``pos`` - integer position if the tile is not in the natural order, e.g., a
pinned tile after an empty slot; not present otherwise

View File

@ -670,6 +670,7 @@ let DirectoryLinksProvider = {
* @return download promise
*/
reportSitesAction: function DirectoryLinksProvider_reportSitesAction(sites, action, triggeringSiteIndex) {
let pastImpressions;
// Check if the suggested tile was shown
if (action == "view") {
sites.slice(0, triggeringSiteIndex + 1).forEach(site => {
@ -687,6 +688,13 @@ let DirectoryLinksProvider = {
// suggested tile has targetedSite, or frecent_sites if it was pinned
let {frecent_sites, targetedSite, url} = sites[triggeringSiteIndex].link;
if (frecent_sites || targetedSite) {
// skip past_impressions for "unpin" to avoid chance of tracking
if (this._frequencyCaps[url] && action != "unpin") {
pastImpressions = {
total: this._frequencyCaps[url].totalViews,
daily: this._frequencyCaps[url].dailyViews
};
}
this._setFrequencyCapClick(url);
}
}
@ -724,6 +732,7 @@ let DirectoryLinksProvider = {
id: id || site.enhancedId,
pin: site.isPinned() ? 1 : undefined,
pos: pos != tilesIndex ? pos : undefined,
past_impressions: pos == triggeringSiteIndex ? pastImpressions : undefined,
score: Math.round(link.frecency / PING_SCORE_DIVISOR) || undefined,
url: site.enhancedId && "",
});
@ -1321,7 +1330,7 @@ let DirectoryLinksProvider = {
capObject.lastShownDate = Date.now();
}
// bump both dialy and total counters
// bump both daily and total counters
capObject.totalViews++;
capObject.dailyViews++;
@ -1336,7 +1345,7 @@ let DirectoryLinksProvider = {
* Sets clicked flag for link url
* @param url String url of the suggested link
*/
_setFrequencyCapClick: function DirectoryLinksProvider_reportFrequencyCapClick(url) {
_setFrequencyCapClick(url) {
let capObject = this._frequencyCaps[url];
// sanity check
if (!capObject) {

View File

@ -1924,3 +1924,109 @@ add_task(function test_inadjecentSites() {
DirectoryLinksProvider._getCurrentTopSiteCount = origCurrentTopSiteCount;
yield promiseCleanDirectoryLinksProvider();
});
add_task(function test_reportPastImpressions() {
let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName;
DirectoryLinksProvider.getFrecentSitesName = () => "";
let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
NewTabUtils.isTopPlacesSite = () => true;
let origCurrentTopSiteCount = DirectoryLinksProvider._getCurrentTopSiteCount;
DirectoryLinksProvider._getCurrentTopSiteCount = () => 8;
let testUrl = "http://frequency.capped/link";
let targets = ["top.site.com"];
let data = {
suggested: [{
type: "affiliate",
frecent_sites: targets,
url: testUrl
}]
};
let dataURI = "data:application/json," + JSON.stringify(data);
yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
// make DirectoryLinksProvider load json
let loadPromise = Promise.defer();
DirectoryLinksProvider.getLinks(_ => {loadPromise.resolve();});
yield loadPromise.promise;
// setup ping handler
let deferred, expectedPath, expectedAction, expectedImpressions;
let done = false;
server.registerPrefixHandler(kPingPath, (aRequest, aResponse) => {
if (done) {
return;
}
do_check_eq(aRequest.path, expectedPath);
let bodyStream = new BinaryInputStream(aRequest.bodyInputStream);
let bodyObject = JSON.parse(NetUtil.readInputStreamToString(bodyStream, bodyStream.available()));
let expectedActionIndex = bodyObject[expectedAction];
if (bodyObject.unpin) {
// unpin should not report past_impressions
do_check_false(bodyObject.tiles[expectedActionIndex].hasOwnProperty("past_impressions"));
}
else if (expectedImpressions) {
do_check_eq(bodyObject.tiles[expectedActionIndex].past_impressions.total, expectedImpressions);
do_check_eq(bodyObject.tiles[expectedActionIndex].past_impressions.daily, expectedImpressions);
}
else {
do_check_eq(expectedPath, "/ping/view");
do_check_false(bodyObject.tiles[expectedActionIndex].hasOwnProperty("past_impressions"));
}
deferred.resolve();
});
// setup ping sender
function sendPingAndTest(path, action, index) {
deferred = Promise.defer();
expectedPath = kPingPath + path;
expectedAction = action;
DirectoryLinksProvider.reportSitesAction(sites, action, index);
return deferred.promise;
}
// Start with a view ping first
let site = {
isPinned: _ => false,
link: {
directoryId: 1,
frecency: 30000,
frecent_sites: targets,
targetedSite: targets[0],
url: testUrl
}
};
let sites = [,
{
isPinned: _ => false,
link: {type: "history", url: "https://foo.com"}
},
site
];
yield sendPingAndTest("view", "view", 2);
yield sendPingAndTest("view", "view", 2);
yield sendPingAndTest("view", "view", 2);
expectedImpressions = DirectoryLinksProvider._frequencyCaps[testUrl].totalViews;
do_check_eq(expectedImpressions, 3);
// now report pin, unpin, block and click
sites.isPinned = _ => true;
yield sendPingAndTest("click", "pin", 2);
sites.isPinned = _ => false;
yield sendPingAndTest("click", "unpin", 2);
sites.isPinned = _ => false;
yield sendPingAndTest("click", "click", 2);
sites.isPinned = _ => false;
yield sendPingAndTest("click", "block", 2);
// Cleanup.
done = true;
DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName;
NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
DirectoryLinksProvider._getCurrentTopSiteCount = origCurrentTopSiteCount;
});

View File

@ -49,7 +49,7 @@ ul {
background-position: right 0;
}
#errorTitleText[sslv3=true] {
#errorTitle[sslv3=true] {
background-image: url("aboutNetError_alert.svg");
}

View File

@ -518,6 +518,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
#PanelUI-fxa-status {
display: flex;
flex: 1 1 0%;
width: 1px;
}
#PanelUI-footer-inner,

View File

@ -231,6 +231,10 @@ description > html|a {
box-shadow: 0px 0px 0px 1px #0095DD;
}
#fxaProfileImage:active {
box-shadow: 0px 0px 0px 1px #ff9500;
}
#noFxaAccount {
/* Overriding the margins from the base preferences.css theme file.
These overrides can be simplified by fixing bug 1027174 */

View File

@ -1,84 +0,0 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
/* 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/. */
package org.mozilla.gecko;
import java.util.Timer;
import java.util.TimerTask;
import org.mozilla.gecko.util.GamepadUtils;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;
public class ScrollAnimator implements View.OnGenericMotionListener {
private Timer mScrollTimer;
private int mX;
private int mY;
// Assuming 60fps, this will make the view scroll once per frame
static final long MS_PER_FRAME = 1000 / 60;
// Maximum number of pixels that can be scrolled per frame
static final float MAX_SCROLL = 0.075f * GeckoAppShell.getDpi();
private class ScrollRunnable extends TimerTask {
private final View mView;
public ScrollRunnable(View view) {
mView = view;
}
@Override
public final void run() {
mView.scrollBy(mX, mY);
}
}
@Override
public boolean onGenericMotion(View view, MotionEvent event) {
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
// Cancel the animation if the joystick is in a neutral position
if (GamepadUtils.isValueInDeadZone(event, MotionEvent.AXIS_X) &&
GamepadUtils.isValueInDeadZone(event, MotionEvent.AXIS_Y)) {
if (mScrollTimer != null) {
mScrollTimer.cancel();
mScrollTimer = null;
}
return true;
}
// Scroll with a velocity relative to the screen DPI
mX = (int) (event.getAxisValue(MotionEvent.AXIS_X) * MAX_SCROLL);
mY = (int) (event.getAxisValue(MotionEvent.AXIS_Y) * MAX_SCROLL);
// Start the timer; the view will continue to scroll as long as
// the joystick is not in the deadzone.
if (mScrollTimer == null) {
mScrollTimer = new Timer();
ScrollRunnable task = new ScrollRunnable(view);
mScrollTimer.scheduleAtFixedRate(task, 0, MS_PER_FRAME);
}
return true;
}
}
return false;
}
/**
* Cancels the running scroll animation if it is in progress.
*/
public void cancel() {
if (mScrollTimer != null) {
mScrollTimer.cancel();
mScrollTimer = null;
}
}
}

View File

@ -431,7 +431,6 @@ gbjar.sources += [
'RemoteTabsExpandableListAdapter.java',
'Restarter.java',
'RestrictedProfiles.java',
'ScrollAnimator.java',
'ServiceNotificationClient.java',
'SessionParser.java',
'SharedPreferencesHelper.java',

View File

@ -286,15 +286,6 @@ DataReportingService.prototype = Object.freeze({
getClientID: function() {
return ClientID.getClientID();
},
/**
* Reset the stable client id.
*
* @return Promise<string> The new client ID.
*/
resetClientID: Task.async(function* () {
return ClientID.resetClientID();
}),
});
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataReportingService]);

View File

@ -245,21 +245,6 @@ HealthReporterState.prototype = Object.freeze({
return this.removeRemoteIDs(ids);
},
/**
* Reset the client ID to something else.
* Returns a promise that is resolved when completed.
*/
resetClientID: Task.async(function* () {
let drs = Cc["@mozilla.org/datareporting/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject;
yield drs.resetClientID();
this._s.clientID = yield drs.getClientID();
this._log.info("Reset client id to " + this._s.clientID + ".");
yield this.save();
}),
_migratePrefs: function () {
let prefs = this._reporter._prefs;
@ -1533,13 +1518,6 @@ this.HealthReporter.prototype = Object.freeze({
} catch (ex) {
this._log.error("Error processing request to delete data: " +
CommonUtils.exceptionStr(error));
} finally {
// If we don't have any remote documents left, nuke the ID.
// This is done for privacy reasons. Why preserve the ID if we
// don't need to?
if (!this.haveRemoteData()) {
yield this._state.resetClientID();
}
}
}.bind(this));
},

View File

@ -758,9 +758,9 @@ add_task(function test_request_remote_data_deletion() {
do_check_false(reporter.haveRemoteData());
do_check_false(server.hasDocument(reporter.serverNamespace, id));
// Client ID should be updated.
// Client ID should stay the same.
do_check_neq(reporter._state.clientID, null);
do_check_neq(reporter._state.clientID, clientID);
do_check_eq(reporter._state.clientID, clientID);
do_check_eq(reporter._state.clientIDVersion, 1);
// And it should be persisted to disk.

View File

@ -284,9 +284,11 @@ function createScreenshotData(document, args) {
height -= scrollbarHeight.value;
const canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
const ratio = window.devicePixelRatio;
canvas.width = width * ratio;
canvas.height = height * ratio;
ctx.scale(ratio, ratio);
ctx.drawWindow(window, left, top, width, height, "#fff");
const data = canvas.toDataURL("image/png", "");

View File

@ -35,14 +35,6 @@ this.ClientID = Object.freeze({
return ClientIDImpl.getClientID();
},
/**
* Generates a new client ID.
* @return {Promise<string>} A promise resolved with the new client id.
*/
resetClientID: function() {
return ClientIDImpl.resetClientID();
},
/**
* Only used for testing. Invalidates the client ID so that it gets read
* again from file.
@ -138,22 +130,6 @@ let ClientIDImpl = {
return Promise.resolve(this._clientID);
},
/**
* Reset the stable client id.
*
* @return {Promise<string>} The new client ID.
*/
resetClientID: Task.async(function* () {
yield this._loadClientIdTask;
yield this._saveClientIdTask;
this._clientID = CommonUtils.generateUUID();
this._saveClientIdTask = this._saveClientID();
yield this._saveClientIdTask;
return this._clientID;
}),
/*
* Resets the provider. This is for testing only.
*/

View File

@ -148,6 +148,9 @@ for var in ('APP_VERSION', 'APP_ID'):
if CONFIG['MOZILLA_OFFICIAL']:
DEFINES['MOZILLA_OFFICIAL'] = True
if CONFIG['MOZ_BUILD_APP'] == 'browser':
DEFINES['MOZ_BUILD_APP_IS_BROWSER'] = True
LOCAL_INCLUDES += [
'../profile',
'/config',

View File

@ -620,7 +620,8 @@ nsXREDirProvider::LoadExtensionBundleDirectories()
if (!mozilla::Preferences::GetBool("extensions.defaultProviders.enabled", true))
return;
if (mProfileDir && !gSafeMode) {
if (mProfileDir) {
if (!gSafeMode) {
nsCOMPtr<nsIFile> extensionsINI;
mProfileDir->Clone(getter_AddRefs(extensionsINI));
if (!extensionsINI)
@ -643,6 +644,17 @@ nsXREDirProvider::LoadExtensionBundleDirectories()
NS_EXTENSION_LOCATION);
LoadExtensionDirectories(parser, "ThemeDirs", mThemeDirectories,
NS_SKIN_LOCATION);
#ifdef MOZ_BUILD_APP_IS_BROWSER
} else {
// In safe mode, still load the default theme directory:
nsCOMPtr<nsIFile> themeManifest;
mXULAppDir->Clone(getter_AddRefs(themeManifest));
themeManifest->AppendNative(NS_LITERAL_CSTRING("extensions"));
themeManifest->AppendNative(NS_LITERAL_CSTRING("{972ce4c6-7e08-4474-a285-3208198ce6fd}"));
themeManifest->AppendNative(NS_LITERAL_CSTRING("chrome.manifest"));
XRE_AddManifestLocation(NS_SKIN_LOCATION, themeManifest);
#endif
}
}
}