Merge m-c to inbound

This commit is contained in:
Wes Kocher 2014-07-07 16:34:44 -07:00
commit fa8c67f1bb
77 changed files with 815 additions and 313 deletions

View File

@ -26,7 +26,7 @@ function hookScreen(window) {
let nodePrincipal = window.document.nodePrincipal;
let origin = nodePrincipal.origin;
if (nodePrincipal.appStatus == nodePrincipal.APP_STATUS_NOT_INSTALLED) {
Cu.reportError('deny mozLockOrientation:' + origin + 'is not installed');
// Only inject screen mock for apps
return;
}

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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="bf9aaf39dd5a6491925a022db167c460f8207d34"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>

View File

@ -17,9 +17,9 @@
</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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
@ -131,6 +131,6 @@
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="efd87a5797ca40fa2df256630c07e0dfb2f762dc"/>
<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="832f4acaf481a19031e479a40b03d9ce5370ddee"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d0aa65b140a45016975ed0ecf35f280dd336e1d3"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="dd72bacb432efc5135a1f747d00aab91f898bddb"/>
<project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
</manifest>

View File

@ -15,11 +15,11 @@
<project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>

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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="bf9aaf39dd5a6491925a022db167c460f8207d34"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>

View File

@ -17,9 +17,9 @@
</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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
@ -143,7 +143,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="bbf7212289fc8311e43f9d11e10788e310d36a08"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d0aa65b140a45016975ed0ecf35f280dd336e1d3"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="dd72bacb432efc5135a1f747d00aab91f898bddb"/>
<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"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "278dd1b102a39cf2c48f11fe3038eaf8f0779d7d",
"revision": "02f96bd32a7d77bc1684f3ca745f0e810871159b",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,11 +17,11 @@
<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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>

View File

@ -15,11 +15,11 @@
<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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>

View File

@ -17,9 +17,9 @@
</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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
@ -127,7 +127,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="d0aa65b140a45016975ed0ecf35f280dd336e1d3"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="dd72bacb432efc5135a1f747d00aab91f898bddb"/>
<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"/>

View File

@ -17,11 +17,11 @@
<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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->

View File

@ -1290,6 +1290,7 @@ pref("devtools.debugger.ignore-caught-exceptions", true);
pref("devtools.debugger.source-maps-enabled", true);
pref("devtools.debugger.pretty-print-enabled", true);
pref("devtools.debugger.auto-pretty-print", false);
pref("devtools.debugger.auto-black-box", true);
pref("devtools.debugger.tracer", false);
// The default Debugger UI settings

View File

@ -123,8 +123,15 @@ PlacesViewBase.prototype = {
get selectedNode() {
if (this._contextMenuShown) {
let popup = document.popupNode;
return popup._placesNode || popup.parentNode._placesNode || null;
let anchor = this._contextMenuShown.triggerNode;
if (!anchor)
return null;
if (anchor._placesNode)
return this._rootElt == anchor ? null : anchor._placesNode;
anchor = anchor.parentNode;
return this._rootElt == anchor ? null : (anchor._placesNode || null);
}
return null;
},
@ -190,13 +197,13 @@ PlacesViewBase.prototype = {
},
buildContextMenu: function PVB_buildContextMenu(aPopup) {
this._contextMenuShown = true;
this._contextMenuShown = aPopup;
window.updateCommands("places");
return this.controller.buildContextMenu(aPopup);
},
destroyContextMenu: function PVB_destroyContextMenu(aPopup) {
this._contextMenuShown = false;
this._contextMenuShown = null;
},
_cleanPopup: function PVB_cleanPopup(aPopup, aDelay) {

View File

@ -366,20 +366,6 @@ PlacesController.prototype = {
return ip != null && (isPaste || ip.isTag != true);
},
/**
* Determines whether or not the root node for the view is selected
*/
rootNodeIsSelected: function PC_rootNodeIsSelected() {
var nodes = this._view.selectedNodes;
var root = this._view.result.root;
for (var i = 0; i < nodes.length; ++i) {
if (nodes[i] == root)
return true;
}
return false;
},
/**
* Looks at the data on the clipboard to see if it is paste-able.
* Paste-able data is:
@ -433,7 +419,7 @@ PlacesController.prototype = {
* Gathers information about the selected nodes according to the following
* rules:
* "link" node is a URI
* "bookmark" node is a bookamrk
* "bookmark" node is a bookmark
* "livemarkChild" node is a child of a livemark
* "tagChild" node is a child of a tag
* "folder" node is a folder
@ -447,15 +433,10 @@ PlacesController.prototype = {
* node are set on its corresponding object as properties.
* Notes:
* 1) This can be slow, so don't call it anywhere performance critical!
* 2) A single-object array corresponding the root node is returned if
* there's no selection.
*/
_buildSelectionMetadata: function PC__buildSelectionMetadata() {
var metadata = [];
var root = this._view.result.root;
var nodes = this._view.selectedNodes;
if (nodes.length == 0)
nodes.push(root); // See the second note above
for (var i = 0; i < nodes.length; i++) {
var nodeData = {};
@ -536,10 +517,23 @@ PlacesController.prototype = {
*/
_shouldShowMenuItem: function PC__shouldShowMenuItem(aMenuItem, aMetaData) {
var selectiontype = aMenuItem.getAttribute("selectiontype");
if (selectiontype == "multiple" && aMetaData.length == 1)
if (!selectiontype) {
selectiontype = "single|multiple";
}
var selectionTypes = selectiontype.split("|");
if (selectionTypes.indexOf("any") != -1) {
return true;
}
var count = aMetaData.length;
if (count > 1 && selectionTypes.indexOf("multiple") == -1)
return false;
if (selectiontype == "single" && aMetaData.length != 1)
if (count == 1 && selectionTypes.indexOf("single") == -1)
return false;
// NB: if there is no selection, we show the item if and only if
// the selectiontype includes 'none' - the metadata list will be
// empty so none of the other criteria will apply anyway.
if (count == 0)
return selectionTypes.indexOf("none") != -1;
var forceHideAttr = aMenuItem.getAttribute("forcehideselection");
if (forceHideAttr) {
@ -586,9 +580,11 @@ PlacesController.prototype = {
* 1) The "selectiontype" attribute may be set on a menu-item to "single"
* if the menu-item should be visible only if there is a single node
* selected, or to "multiple" if the menu-item should be visible only if
* multiple nodes are selected. If the attribute is not set or if it is
* set to an invalid value, the menu-item may be visible for both types of
* selection.
* multiple nodes are selected, or to "none" if the menuitems should be
* visible for if there are no selected nodes, or to a |-separated
* combination of these.
* If the attribute is not set or set to an invalid value, the menu-item
* may be visible irrespective of the selection.
* 2) The "selection" attribute may be set on a menu-item to the various
* meta-data rules for which it may be visible. The rules should be
* separated with the | character.
@ -619,18 +615,19 @@ PlacesController.prototype = {
var separator = null;
var visibleItemsBeforeSep = false;
var anyVisible = false;
var usableItemCount = 0;
for (var i = 0; i < aPopup.childNodes.length; ++i) {
var item = aPopup.childNodes[i];
if (item.localName != "menuseparator") {
// We allow pasting into tag containers, so special case that.
var hideIfNoIP = item.getAttribute("hideifnoinsertionpoint") == "true" &&
noIp && !(ip && ip.isTag && item.id == "placesContext_paste");
item.hidden = hideIfNoIP || !this._shouldShowMenuItem(item, metadata);
var shouldHideItem = hideIfNoIP || !this._shouldShowMenuItem(item, metadata);
item.hidden = item.disabled = shouldHideItem;
if (!item.hidden) {
visibleItemsBeforeSep = true;
anyVisible = true;
usableItemCount++;
// Show the separator above the menu-item if any
if (separator) {
@ -654,21 +651,21 @@ PlacesController.prototype = {
}
// Set Open Folder/Links In Tabs items enabled state if they're visible
if (anyVisible) {
if (usableItemCount > 0) {
var openContainerInTabsItem = document.getElementById("placesContext_openContainer:tabs");
if (!openContainerInTabsItem.hidden && this._view.selectedNode &&
PlacesUtils.nodeIsContainer(this._view.selectedNode)) {
openContainerInTabsItem.disabled =
!PlacesUtils.hasChildURIs(this._view.selectedNode);
}
else {
// see selectiontype rule in the overlay
var openLinksInTabsItem = document.getElementById("placesContext_openLinks:tabs");
openLinksInTabsItem.disabled = openLinksInTabsItem.hidden;
if (!openContainerInTabsItem.hidden) {
var containerToUse = this._view.selectedNode || this._view.result.root;
if (PlacesUtils.nodeIsContainer(containerToUse)) {
if (!PlacesUtils.hasChildURIs(containerToUse, true)) {
openContainerInTabsItem.disabled = true;
// Ensure that we don't display the menu if nothing is enabled:
usableItemCount--;
}
}
}
}
return anyVisible;
return usableItemCount > 0;
},
/**
@ -734,10 +731,15 @@ PlacesController.prototype = {
*/
openSelectionInTabs: function PC_openLinksInTabs(aEvent) {
var node = this._view.selectedNode;
var nodes = this._view.selectedNodes;
// In the case of no selection, open the root node:
if (!node && !nodes.length) {
node = this._view.result.root;
}
if (node && PlacesUtils.nodeIsContainer(node))
PlacesUIUtils.openContainerNodeInTabs(this._view.selectedNode, aEvent, this._view);
PlacesUIUtils.openContainerNodeInTabs(node, aEvent, this._view);
else
PlacesUIUtils.openURINodesInTabs(this._view.selectedNodes, aEvent, this._view);
PlacesUIUtils.openURINodesInTabs(nodes, aEvent, this._view);
},
/**

View File

@ -113,7 +113,7 @@
onclick="checkForMiddleClick(this, event);"
label="&cmd.open_all_in_tabs.label;"
accesskey="&cmd.open_all_in_tabs.accesskey;"
selectiontype="single"
selectiontype="single|none"
selection="folder|host|query"/>
<menuitem id="placesContext_openLinks:tabs"
oncommand="var view = PlacesUIUtils.getViewForNode(document.popupNode);
@ -134,20 +134,20 @@
command="placesCmd_new:bookmark"
label="&cmd.new_bookmark.label;"
accesskey="&cmd.new_bookmark.accesskey;"
selection="any"
selectiontype="any"
hideifnoinsertionpoint="true"/>
<menuitem id="placesContext_new:folder"
command="placesCmd_new:folder"
label="&cmd.new_folder.label;"
accesskey="&cmd.context_new_folder.accesskey;"
selection="any"
selectiontype="any"
hideifnoinsertionpoint="true"/>
<menuitem id="placesContext_new:separator"
command="placesCmd_new:separator"
label="&cmd.new_separator.label;"
accesskey="&cmd.new_separator.accesskey;"
closemenu="single"
selection="any"
selectiontype="any"
hideifnoinsertionpoint="true"/>
<menuseparator id="placesContext_newSeparator"/>
<menuitem id="placesContext_createBookmark"
@ -167,14 +167,13 @@
command="placesCmd_copy"
label="&copyCmd.label;"
closemenu="single"
accesskey="&copyCmd.accesskey;"
selection="any"/>
accesskey="&copyCmd.accesskey;"/>
<menuitem id="placesContext_paste"
command="placesCmd_paste"
label="&pasteCmd.label;"
closemenu="single"
accesskey="&pasteCmd.accesskey;"
selection="any"
selectiontype="any"
hideifnoinsertionpoint="true"/>
<menuseparator id="placesContext_editSeparator"/>
<menuitem id="placesContext_delete"

View File

@ -43,7 +43,7 @@ var SidebarUtils = {
var openInTabs = isContainer &&
(aEvent.button == 1 ||
(aEvent.button == 0 && modifKey)) &&
PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(row.value));
PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(row.value), true);
if (aEvent.button == 0 && isContainer && !openInTabs) {
tbo.view.toggleOpenState(row.value);

View File

@ -293,7 +293,8 @@ let DebuggerController = {
_startDebuggingTab: function() {
let deferred = promise.defer();
let threadOptions = {
useSourceMaps: Prefs.sourceMapsEnabled
useSourceMaps: Prefs.sourceMapsEnabled,
autoBlackBox: Prefs.autoBlackBox
};
this._target.activeTab.attachThread(threadOptions, (aResponse, aThreadClient) => {
@ -345,7 +346,8 @@ let DebuggerController = {
_startChromeDebugging: function(aChromeDebugger) {
let deferred = promise.defer();
let threadOptions = {
useSourceMaps: Prefs.sourceMapsEnabled
useSourceMaps: Prefs.sourceMapsEnabled,
autoBlackBox: Prefs.autoBlackBox
};
this.client.attachThread(aChromeDebugger, (aResponse, aThreadClient) => {
@ -397,8 +399,11 @@ let DebuggerController = {
* Detach and reattach to the thread actor with useSourceMaps true, blow
* away old sources and get them again.
*/
reconfigureThread: function(aUseSourceMaps) {
this.activeThread.reconfigure({ useSourceMaps: aUseSourceMaps }, aResponse => {
reconfigureThread: function({ useSourceMaps, autoBlackBox }) {
this.activeThread.reconfigure({
useSourceMaps: useSourceMaps,
autoBlackBox: autoBlackBox
}, aResponse => {
if (aResponse.error) {
let msg = "Couldn't reconfigure thread: " + aResponse.message;
Cu.reportError(msg);
@ -2241,7 +2246,8 @@ let Prefs = new ViewHelpers.Prefs("devtools", {
prettyPrintEnabled: ["Bool", "debugger.pretty-print-enabled"],
autoPrettyPrint: ["Bool", "debugger.auto-pretty-print"],
tracerEnabled: ["Bool", "debugger.tracer"],
editorTabSize: ["Int", "editor.tabsize"]
editorTabSize: ["Int", "editor.tabsize"],
autoBlackBox: ["Bool", "debugger.auto-black-box"]
});
/**

View File

@ -197,6 +197,7 @@ function OptionsView() {
this._toggleShowVariablesOnlyEnum = this._toggleShowVariablesOnlyEnum.bind(this);
this._toggleShowVariablesFilterBox = this._toggleShowVariablesFilterBox.bind(this);
this._toggleShowOriginalSource = this._toggleShowOriginalSource.bind(this);
this._toggleAutoBlackBox = this._toggleAutoBlackBox.bind(this);
}
OptionsView.prototype = {
@ -214,6 +215,7 @@ OptionsView.prototype = {
this._showVariablesOnlyEnumItem = document.getElementById("show-vars-only-enum");
this._showVariablesFilterBoxItem = document.getElementById("show-vars-filter-box");
this._showOriginalSourceItem = document.getElementById("show-original-source");
this._autoBlackBoxItem = document.getElementById("auto-black-box");
this._autoPrettyPrint.setAttribute("checked", Prefs.autoPrettyPrint);
this._pauseOnExceptionsItem.setAttribute("checked", Prefs.pauseOnExceptions);
@ -222,8 +224,10 @@ OptionsView.prototype = {
this._showVariablesOnlyEnumItem.setAttribute("checked", Prefs.variablesOnlyEnumVisible);
this._showVariablesFilterBoxItem.setAttribute("checked", Prefs.variablesSearchboxVisible);
this._showOriginalSourceItem.setAttribute("checked", Prefs.sourceMapsEnabled);
this._autoBlackBoxItem.setAttribute("checked", Prefs.autoBlackBox);
},
/**
* Destruction function, called when the debugger is closed.
*/
@ -322,7 +326,30 @@ OptionsView.prototype = {
window.once(EVENTS.OPTIONS_POPUP_HIDDEN, () => {
// The popup panel needs more time to hide after triggering onpopuphidden.
window.setTimeout(() => {
DebuggerController.reconfigureThread(pref);
DebuggerController.reconfigureThread({
useSourceMaps: pref,
autoBlackBox: Prefs.autoBlackBox
});
}, POPUP_HIDDEN_DELAY);
});
},
/**
* Listener handling the 'automatically black box minified sources' menuitem
* command.
*/
_toggleAutoBlackBox: function() {
let pref = Prefs.autoBlackBox =
this._autoBlackBoxItem.getAttribute("checked") == "true";
// Don't block the UI while reconfiguring the server.
window.once(EVENTS.OPTIONS_POPUP_HIDDEN, () => {
// The popup panel needs more time to hide after triggering onpopuphidden.
window.setTimeout(() => {
DebuggerController.reconfigureThread({
useSourceMaps: Prefs.sourceMapsEnabled,
autoBlackBox: pref
});
}, POPUP_HIDDEN_DELAY);
});
},
@ -332,7 +359,8 @@ OptionsView.prototype = {
_showPanesOnStartupItem: null,
_showVariablesOnlyEnumItem: null,
_showVariablesFilterBoxItem: null,
_showOriginalSourceItem: null
_showOriginalSourceItem: null,
_autoBlackBoxItem: null
};
/**

View File

@ -88,6 +88,8 @@
oncommand="DebuggerView.Options._toggleShowVariablesFilterBox()"/>
<command id="toggleShowOriginalSource"
oncommand="DebuggerView.Options._toggleShowOriginalSource()"/>
<command id="toggleAutoBlackBox"
oncommand="DebuggerView.Options._toggleAutoBlackBox()"/>
<command id="toggleTracing"
oncommand="DebuggerView.Tracer._onToggleTracing()"/>
<command id="startTracing"
@ -209,6 +211,11 @@
label="&debuggerUI.showOriginalSource;"
accesskey="&debuggerUI.showOriginalSource.accesskey;"
command="toggleShowOriginalSource"/>
<menuitem id="auto-black-box"
type="checkbox"
label="&debuggerUI.autoBlackBox;"
accesskey="&debuggerUI.autoBlackBox.accesskey;"
command="toggleAutoBlackBox"/>
</menupopup>
</popupset>

View File

@ -22,7 +22,7 @@ support-files =
code_math.js
code_math.map
code_math.min.js
code_math_bogus_map.min.js
code_math_bogus_map.js
code_script-switching-01.js
code_script-switching-02.js
code_test-editor-mode

View File

@ -6,7 +6,7 @@
*/
const TAB_URL = EXAMPLE_URL + "doc_minified_bogus_map.html";
const JS_URL = EXAMPLE_URL + "code_math_bogus_map.min.js";
const JS_URL = EXAMPLE_URL + "code_math_bogus_map.js";
// This test causes an error to be logged in the console, which appears in TBPL
// logs, so we are disabling that here.
@ -46,7 +46,7 @@ function test() {
}
function checkInitialSource() {
isnot(gSources.selectedValue.indexOf(".min.js"), -1,
isnot(gSources.selectedValue.indexOf("code_math_bogus_map.js"), -1,
"The debugger should show the minified js file.");
}

View File

@ -9,6 +9,6 @@
</head>
<body>
<script src="code_math_bogus_map.min.js"></script>
<script src="code_math_bogus_map.js"></script>
</body>
</html>

View File

@ -32,8 +32,8 @@ const GRAPH_REGION_LINE_COLOR = "rgba(237,38,85,0.8)";
const GRAPH_STRIPE_PATTERN_WIDTH = 16; // px
const GRAPH_STRIPE_PATTERN_HEIGHT = 16; // px
const GRAPH_STRIPE_PATTERN_LINE_WIDTH = 4; // px
const GRAPH_STRIPE_PATTERN_LINE_SPACING = 8; // px
const GRAPH_STRIPE_PATTERN_LINE_WIDTH = 2; // px
const GRAPH_STRIPE_PATTERN_LINE_SPACING = 4; // px
// Line graph constants.
@ -41,7 +41,7 @@ const LINE_GRAPH_DAMPEN_VALUES = 0.85;
const LINE_GRAPH_MIN_SQUARED_DISTANCE_BETWEEN_POINTS = 400; // 20 px
const LINE_GRAPH_TOOLTIP_SAFE_BOUNDS = 10; // px
const LINE_GRAPH_STROKE_WIDTH = 2; // px
const LINE_GRAPH_STROKE_WIDTH = 1; // px
const LINE_GRAPH_STROKE_COLOR = "rgba(255,255,255,0.9)";
const LINE_GRAPH_HELPER_LINES_DASH = [5]; // px
const LINE_GRAPH_HELPER_LINES_WIDTH = 1; // px
@ -62,7 +62,7 @@ const LINE_GRAPH_REGION_STRIPES_COLOR = "rgba(237,38,85,0.2)";
const BAR_GRAPH_DAMPEN_VALUES = 0.75;
const BAR_GRAPH_BARS_MARGIN_TOP = 1; // px
const BAR_GRAPH_BARS_MARGIN_END = 2; // px
const BAR_GRAPH_BARS_MARGIN_END = 1; // px
const BAR_GRAPH_MIN_BARS_WIDTH = 5; // px
const BAR_GRAPH_MIN_BLOCKS_HEIGHT = 1; // px
@ -1111,7 +1111,7 @@ LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
gradient.addColorStop(1, LINE_GRAPH_BACKGROUND_GRADIENT_END);
ctx.fillStyle = gradient;
ctx.strokeStyle = LINE_GRAPH_STROKE_COLOR;
ctx.lineWidth = LINE_GRAPH_STROKE_WIDTH;
ctx.lineWidth = LINE_GRAPH_STROKE_WIDTH * this._pixelRatio;
ctx.beginPath();
let prevX = 0;
@ -1379,6 +1379,8 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
// information about the data source, and how a "bar" contains "blocks".
let prevHeight = [];
let scaledMarginEnd = BAR_GRAPH_BARS_MARGIN_END * this._pixelRatio;
let unscaledMarginTop = BAR_GRAPH_BARS_MARGIN_TOP;
for (let type = 0; type < totalTypes; type++) {
ctx.fillStyle = this.format[type].color || "#000";
@ -1410,13 +1412,13 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
ctx.lineTo(blockLeft, bottom);
if (prevHeight[tick] === undefined) {
prevHeight[tick] = averageHeight + BAR_GRAPH_BARS_MARGIN_TOP;
prevHeight[tick] = averageHeight + unscaledMarginTop;
} else {
prevHeight[tick] += averageHeight + BAR_GRAPH_BARS_MARGIN_TOP;
prevHeight[tick] += averageHeight + unscaledMarginTop;
}
}
prevLeft += blockWidth + BAR_GRAPH_BARS_MARGIN_END;
prevLeft += blockWidth + scaledMarginEnd;
skippedHeight = 0;
skippedCount = 0;
}
@ -1451,6 +1453,7 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
let prevLeft = 0;
let skippedCount = 0;
let skippedHeight = 0;
let scaledMarginEnd = BAR_GRAPH_BARS_MARGIN_END * this._pixelRatio;
for (let { delta, values } of data) {
let barLeft = (delta - dataOffsetX) * dataScaleX;
@ -1466,7 +1469,7 @@ BarGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
let averageHeight = (barHeight + skippedHeight) / (skippedCount + 1);
maxHeight = Math.max(averageHeight, maxHeight);
prevLeft += barWidth;
prevLeft += barWidth + scaledMarginEnd;
skippedHeight = 0;
skippedCount = 0;
}
@ -1558,12 +1561,16 @@ AbstractCanvasGraph.getStripePattern = function(data) {
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, width, height);
let pixelRatio = ownerDocument.defaultView.devicePixelRatio;
let scaledLineWidth = GRAPH_STRIPE_PATTERN_LINE_WIDTH * pixelRatio;
let scaledLineSpacing = GRAPH_STRIPE_PATTERN_LINE_SPACING * pixelRatio;
ctx.strokeStyle = stripesColor;
ctx.lineWidth = GRAPH_STRIPE_PATTERN_LINE_WIDTH;
ctx.lineWidth = scaledLineWidth;
ctx.lineCap = "square";
ctx.beginPath();
for (let i = -height; i <= height; i += GRAPH_STRIPE_PATTERN_LINE_SPACING) {
for (let i = -height; i <= height; i += scaledLineSpacing) {
ctx.moveTo(width, i);
ctx.lineTo(0, i + height);
}

View File

@ -137,7 +137,6 @@ support-files =
[browser_console_navigation_marker.js]
[browser_console_nsiconsolemessage.js]
[browser_console_optimized_out_vars.js]
skip-if = true # Intermittent failures - bug 1016310
[browser_console_private_browsing.js]
[browser_console_variables_view.js]
[browser_console_variables_view_dom_nodes.js]

View File

@ -95,6 +95,12 @@
<!ENTITY debuggerUI.showOriginalSource "Show Original Sources">
<!ENTITY debuggerUI.showOriginalSource.accesskey "O">
<!-- LOCALIZATION NOTE (debuggerUI.autoBlackBox): This is the label for
- the checkbox that toggles whether sources that we suspect are minified are
- automatically black boxed or not. -->
<!ENTITY debuggerUI.autoBlackBox "Automatically Black Box Minified Sources">
<!ENTITY debuggerUI.autoBlackBox.accesskey "B">
<!-- LOCALIZATION NOTE (debuggerUI.searchPanelOperators): This is the text that
- appears in the filter panel popup as a header for the operators part. -->
<!ENTITY debuggerUI.searchPanelOperators "Operators:">

View File

@ -66,15 +66,22 @@ nsresult MediaOmxReader::Init(MediaDecoderReader* aCloneDonor)
return NS_OK;
}
void MediaOmxReader::Shutdown()
void MediaOmxReader::ReleaseDecoder()
{
ReleaseMediaResources();
if (mOmxDecoder.get()) {
mOmxDecoder->ReleaseDecoder();
}
mOmxDecoder.clear();
}
void MediaOmxReader::Shutdown()
{
ReleaseMediaResources();
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &MediaOmxReader::ReleaseDecoder);
NS_DispatchToMainThread(event);
}
bool MediaOmxReader::IsWaitingMediaResources()
{
if (!mOmxDecoder.get()) {

View File

@ -104,6 +104,8 @@ public:
// ANDROID_VERSION < 19
void CheckAudioOffload();
#endif
void ReleaseDecoder();
};
} // namespace mozilla

View File

@ -248,6 +248,20 @@ CameraControlImpl::OnPreviewStateChange(CameraControlListener::PreviewState aNew
}
}
void
CameraControlImpl::OnRateLimitPreview(bool aLimit)
{
// This function runs on neither the Main Thread nor the Camera Thread.
RwLockAutoEnterRead lock(mListenerLock);
DOM_CAMERA_LOGI("OnRateLimitPreview: %d\n", aLimit);
for (uint32_t i = 0; i < mListeners.Length(); ++i) {
CameraControlListener* l = mListeners[i];
l->OnRateLimitPreview(aLimit);
}
}
bool
CameraControlImpl::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight)
{

View File

@ -67,6 +67,7 @@ protected:
void OnFacesDetected(const nsTArray<Face>& aFaces);
void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType);
void OnRateLimitPreview(bool aLimit);
bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight);
void OnRecorderStateChange(CameraControlListener::RecorderState aState,
int32_t aStatus = -1, int32_t aTrackNumber = -1);

View File

@ -64,6 +64,7 @@ public:
virtual void OnRecorderStateChange(RecorderState aState, int32_t aStatus, int32_t aTrackNum) { }
virtual void OnShutter() { }
virtual void OnRateLimitPreview(bool aLimit) { }
virtual bool OnNewPreviewFrame(layers::Image* aFrame, uint32_t aWidth, uint32_t aHeight)
{
return false;

View File

@ -4,6 +4,15 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CameraPreviewMediaStream.h"
#include "CameraCommon.h"
/**
* Maximum number of outstanding invalidates before we start to drop frames;
* if we hit this threshold, it is an indicator that the main thread is
* either very busy or the device is busy elsewhere (e.g. encoding or
* persisting video data).
*/
#define MAX_INVALIDATE_PENDING 4
using namespace mozilla::layers;
using namespace mozilla::dom;
@ -13,7 +22,9 @@ namespace mozilla {
CameraPreviewMediaStream::CameraPreviewMediaStream(DOMMediaStream* aWrapper)
: MediaStream(aWrapper)
, mMutex("mozilla::camera::CameraPreviewMediaStream")
, mFrameCallback(nullptr)
, mInvalidatePending(0)
, mDiscardedFrames(0)
, mRateLimit(false)
{
SetGraphImpl(MediaStreamGraph::GetInstance());
mIsConsumed = false;
@ -103,22 +114,53 @@ CameraPreviewMediaStream::Destroy()
}
void
CameraPreviewMediaStream::SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage)
CameraPreviewMediaStream::Invalidate()
{
MutexAutoLock lock(mMutex);
TimeStamp now = TimeStamp::Now();
for (uint32_t i = 0; i < mVideoOutputs.Length(); ++i) {
--mInvalidatePending;
for (nsTArray<nsRefPtr<VideoFrameContainer> >::size_type i = 0; i < mVideoOutputs.Length(); ++i) {
VideoFrameContainer* output = mVideoOutputs[i];
output->SetCurrentFrame(aIntrinsicSize, aImage, now);
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(output, &VideoFrameContainer::Invalidate);
NS_DispatchToMainThread(event);
output->Invalidate();
}
}
void
CameraPreviewMediaStream::RateLimit(bool aLimit)
{
mRateLimit = aLimit;
}
void
CameraPreviewMediaStream::SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage)
{
{
MutexAutoLock lock(mMutex);
if (mInvalidatePending > 0) {
if (mRateLimit || mInvalidatePending > MAX_INVALIDATE_PENDING) {
++mDiscardedFrames;
DOM_CAMERA_LOGW("Discard preview frame %d, %d invalidation(s) pending",
mDiscardedFrames, mInvalidatePending);
return;
}
DOM_CAMERA_LOGI("Update preview frame, %d invalidation(s) pending",
mInvalidatePending);
}
mDiscardedFrames = 0;
TimeStamp now = TimeStamp::Now();
for (nsTArray<nsRefPtr<VideoFrameContainer> >::size_type i = 0; i < mVideoOutputs.Length(); ++i) {
VideoFrameContainer* output = mVideoOutputs[i];
output->SetCurrentFrame(aIntrinsicSize, aImage, now);
}
++mInvalidatePending;
}
if (mFrameCallback) {
mFrameCallback->OnNewFrame(aIntrinsicSize, aImage);
}
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &CameraPreviewMediaStream::Invalidate);
NS_DispatchToMainThread(event);
}
void
@ -126,7 +168,7 @@ CameraPreviewMediaStream::ClearCurrentFrame()
{
MutexAutoLock lock(mMutex);
for (uint32_t i = 0; i < mVideoOutputs.Length(); ++i) {
for (nsTArray<nsRefPtr<VideoFrameContainer> >::size_type i = 0; i < mVideoOutputs.Length(); ++i) {
VideoFrameContainer* output = mVideoOutputs[i];
output->ClearCurrentFrame();
nsCOMPtr<nsIRunnable> event =

View File

@ -11,13 +11,8 @@
namespace mozilla {
class CameraPreviewFrameCallback {
public:
virtual void OnNewFrame(const gfxIntSize& aIntrinsicSize, layers::Image* aImage) = 0;
};
/**
* This is a stream for camere preview.
* This is a stream for camera preview.
*
* XXX It is a temporary fix of SourceMediaStream.
* A camera preview requests no delay and no buffering stream.
@ -40,20 +35,21 @@ public:
virtual void RemoveListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
virtual void Destroy();
void Invalidate();
// Call these on any thread.
void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage);
void ClearCurrentFrame();
void SetFrameCallback(CameraPreviewFrameCallback* aCallback) {
mFrameCallback = aCallback;
}
void RateLimit(bool aLimit);
protected:
// mMutex protects all the class' fields.
// This class is not registered to MediaStreamGraph.
// It needs to protect all the fields.
Mutex mMutex;
CameraPreviewFrameCallback* mFrameCallback;
int32_t mInvalidatePending;
uint32_t mDiscardedFrames;
bool mRateLimit;
};
}

View File

@ -214,7 +214,7 @@ protected:
DOMCameraControlListener* mListener;
// our viewfinder stream
CameraPreviewMediaStream* mInput;
nsRefPtr<CameraPreviewMediaStream> mInput;
// set once when this object is created
nsCOMPtr<nsPIDOMWindow> mWindow;

View File

@ -287,6 +287,12 @@ DOMCameraControlListener::OnShutter()
NS_DispatchToMainThread(new Callback(mDOMCameraControl));
}
void
DOMCameraControlListener::OnRateLimitPreview(bool aLimit)
{
mStream->RateLimit(aLimit);
}
bool
DOMCameraControlListener::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight)
{

View File

@ -28,6 +28,7 @@ public:
virtual void OnRecorderStateChange(RecorderState aState, int32_t aStatus, int32_t aTrackNum) MOZ_OVERRIDE;
virtual void OnConfigurationChange(const CameraListenerConfiguration& aConfiguration) MOZ_OVERRIDE;
virtual void OnShutter() MOZ_OVERRIDE;
virtual void OnRateLimitPreview(bool aLimit) MOZ_OVERRIDE;
virtual bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) MOZ_OVERRIDE;
virtual void OnUserError(UserContext aContext, nsresult aError) MOZ_OVERRIDE;

View File

@ -1682,6 +1682,12 @@ nsGonkCameraControl::GetRecorderProfileManagerImpl()
return profileMgr.forget();
}
void
nsGonkCameraControl::OnRateLimitPreview(bool aLimit)
{
CameraControlImpl::OnRateLimitPreview(aLimit);
}
void
nsGonkCameraControl::OnNewPreviewFrame(layers::TextureClient* aBuffer)
{
@ -1744,6 +1750,12 @@ OnFacesDetected(nsGonkCameraControl* gc, camera_frame_metadata_t* aMetaData)
gc->OnFacesDetected(aMetaData);
}
void
OnRateLimitPreview(nsGonkCameraControl* gc, bool aLimit)
{
gc->OnRateLimitPreview(aLimit);
}
void
OnNewPreviewFrame(nsGonkCameraControl* gc, layers::TextureClient* aBuffer)
{

View File

@ -52,10 +52,11 @@ public:
void OnFacesDetected(camera_frame_metadata_t* aMetaData);
void OnTakePictureComplete(uint8_t* aData, uint32_t aLength);
void OnTakePictureError();
void OnRateLimitPreview(bool aLimit);
void OnNewPreviewFrame(layers::TextureClient* aBuffer);
void OnRecorderEvent(int msg, int ext1, int ext2);
void OnSystemError(CameraControlListener::SystemContext aWhere, nsresult aError);
// See ICameraControl.h for getter/setter return values.
virtual nsresult Set(uint32_t aKey, const nsAString& aValue) MOZ_OVERRIDE;
virtual nsresult Get(uint32_t aKey, nsAString& aValue) MOZ_OVERRIDE;
@ -84,6 +85,7 @@ public:
protected:
~nsGonkCameraControl();
using CameraControlImpl::OnRateLimitPreview;
using CameraControlImpl::OnNewPreviewFrame;
using CameraControlImpl::OnAutoFocusComplete;
using CameraControlImpl::OnFacesDetected;
@ -178,6 +180,7 @@ private:
};
// camera driver callbacks
void OnRateLimitPreview(nsGonkCameraControl* gc, bool aLimit);
void OnTakePictureComplete(nsGonkCameraControl* gc, uint8_t* aData, uint32_t aLength);
void OnTakePictureError(nsGonkCameraControl* gc);
void OnAutoFocusComplete(nsGonkCameraControl* gc, bool aSuccess);

View File

@ -44,6 +44,12 @@ GonkCameraHardware::GonkCameraHardware(mozilla::nsGonkCameraControl* aTarget, ui
DOM_CAMERA_LOGT("%s:%d : this=%p (aTarget=%p)\n", __func__, __LINE__, (void*)this, (void*)aTarget);
}
void
GonkCameraHardware::OnRateLimitPreview(bool aLimit)
{
::OnRateLimitPreview(mTarget, aLimit);
}
void
GonkCameraHardware::OnNewFrame()
{

View File

@ -55,6 +55,8 @@ public:
static sp<GonkCameraHardware> Connect(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId);
virtual void Close();
virtual void OnRateLimitPreview(bool aLimit);
// derived from GonkNativeWindowNewFrameCallback
virtual void OnNewFrame() MOZ_OVERRIDE;

View File

@ -170,6 +170,7 @@ GonkCameraSource::GonkCameraSource(
mStarted(false),
mNumFramesEncoded(0),
mTimeBetweenFrameCaptureUs(0),
mRateLimit(false),
mFirstFrameTimeUs(0),
mNumFramesDropped(0),
mNumGlitches(0),
@ -589,6 +590,10 @@ status_t GonkCameraSource::reset() {
}
}
stopCameraRecording();
if (mRateLimit) {
mRateLimit = false;
mCameraHw->OnRateLimitPreview(false);
}
releaseCamera();
if (mCollectStats) {
@ -692,51 +697,65 @@ status_t GonkCameraSource::read(
void GonkCameraSource::dataCallbackTimestamp(int64_t timestampUs,
int32_t msgType, const sp<IMemory> &data) {
bool rateLimit;
bool prevRateLimit;
CS_LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
Mutex::Autolock autoLock(mLock);
if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
CS_LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
releaseOneRecordingFrame(data);
return;
}
if (mNumFramesReceived > 0) {
CHECK(timestampUs > mLastFrameTimestampUs);
if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
++mNumGlitches;
{
Mutex::Autolock autoLock(mLock);
if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
CS_LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
releaseOneRecordingFrame(data);
return;
}
}
// May need to skip frame or modify timestamp. Currently implemented
// by the subclass CameraSourceTimeLapse.
if (skipCurrentFrame(timestampUs)) {
releaseOneRecordingFrame(data);
return;
}
mLastFrameTimestampUs = timestampUs;
if (mNumFramesReceived == 0) {
mFirstFrameTimeUs = timestampUs;
// Initial delay
if (mStartTimeUs > 0) {
if (timestampUs < mStartTimeUs) {
// Frame was captured before recording was started
// Drop it without updating the statistical data.
releaseOneRecordingFrame(data);
return;
if (mNumFramesReceived > 0) {
CHECK(timestampUs > mLastFrameTimestampUs);
if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
++mNumGlitches;
}
mStartTimeUs = timestampUs - mStartTimeUs;
}
}
++mNumFramesReceived;
CHECK(data != NULL && data->size() > 0);
mFramesReceived.push_back(data);
int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
mFrameTimes.push_back(timeUs);
CS_LOGV("initial delay: %lld, current time stamp: %lld",
mStartTimeUs, timeUs);
mFrameAvailableCondition.signal();
// May need to skip frame or modify timestamp. Currently implemented
// by the subclass CameraSourceTimeLapse.
if (skipCurrentFrame(timestampUs)) {
releaseOneRecordingFrame(data);
return;
}
mLastFrameTimestampUs = timestampUs;
if (mNumFramesReceived == 0) {
mFirstFrameTimeUs = timestampUs;
// Initial delay
if (mStartTimeUs > 0) {
if (timestampUs < mStartTimeUs) {
// Frame was captured before recording was started
// Drop it without updating the statistical data.
releaseOneRecordingFrame(data);
return;
}
mStartTimeUs = timestampUs - mStartTimeUs;
}
}
++mNumFramesReceived;
// If a backlog is building up in the receive queue, we are likely
// resource constrained and we need to throttle
prevRateLimit = mRateLimit;
rateLimit = mFramesReceived.empty();
mRateLimit = rateLimit;
CHECK(data != NULL && data->size() > 0);
mFramesReceived.push_back(data);
int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
mFrameTimes.push_back(timeUs);
CS_LOGV("initial delay: %lld, current time stamp: %lld",
mStartTimeUs, timeUs);
mFrameAvailableCondition.signal();
}
if(prevRateLimit != rateLimit) {
mCameraHw->OnRateLimitPreview(rateLimit);
}
}
bool GonkCameraSource::isMetaDataStoredInVideoBuffers() const {

View File

@ -127,6 +127,7 @@ private:
List<sp<IMemory> > mFramesReceived;
List<sp<IMemory> > mFramesBeingEncoded;
List<int64_t> mFrameTimes;
bool mRateLimit;
int64_t mFirstFrameTimeUs;
int32_t mNumFramesDropped;

View File

@ -349,7 +349,8 @@ private:
#ifdef MOZ_WIDGET_GONK
nsString mLastStatus;
void DispatchMountChangeEvent(nsAString& aVolumeStatus);
void DispatchStatusChangeEvent(nsAString& aStatus);
void DispatchStorageStatusChangeEvent(nsAString& aVolumeStatus);
#endif
// nsIDOMDeviceStorage.type

View File

@ -4194,14 +4194,32 @@ nsDOMDeviceStorage::EnumerateInternal(const nsAString& aPath,
#ifdef MOZ_WIDGET_GONK
void
nsDOMDeviceStorage::DispatchMountChangeEvent(nsAString& aVolumeStatus)
nsDOMDeviceStorage::DispatchStatusChangeEvent(nsAString& aStatus)
{
if (aVolumeStatus == mLastStatus) {
if (aStatus == mLastStatus) {
// We've already sent this status, don't bother sending it again.
return;
}
mLastStatus = aVolumeStatus;
mLastStatus = aStatus;
DeviceStorageChangeEventInit init;
init.mBubbles = true;
init.mCancelable = false;
init.mPath = mStorageName;
init.mReason = aStatus;
nsRefPtr<DeviceStorageChangeEvent> event =
DeviceStorageChangeEvent::Constructor(this, NS_LITERAL_STRING("change"),
init);
event->SetTrusted(true);
bool ignore;
DispatchEvent(event, &ignore);
}
void
nsDOMDeviceStorage::DispatchStorageStatusChangeEvent(nsAString& aVolumeStatus)
{
DeviceStorageChangeEventInit init;
init.mBubbles = true;
init.mCancelable = false;
@ -4209,7 +4227,7 @@ nsDOMDeviceStorage::DispatchMountChangeEvent(nsAString& aVolumeStatus)
init.mReason = aVolumeStatus;
nsRefPtr<DeviceStorageChangeEvent> event =
DeviceStorageChangeEvent::Constructor(this, NS_LITERAL_STRING("change"),
DeviceStorageChangeEvent::Constructor(this, NS_LITERAL_STRING("storage-state-change"),
init);
event->SetTrusted(true);
@ -4268,9 +4286,15 @@ nsDOMDeviceStorage::Observe(nsISupports *aSubject,
}
DeviceStorageFile dsf(mStorageType, mStorageName);
nsString status;
nsString status, storageStatus;
// Get Status (one of "available, unavailable, shared")
dsf.GetStatus(status);
DispatchMountChangeEvent(status);
DispatchStatusChangeEvent(status);
// Get real volume status (defined in dom/system/gonk/nsIVolume.idl)
dsf.GetStorageStatus(storageStatus);
DispatchStorageStatusChangeEvent(storageStatus);
return NS_OK;
}
#endif

View File

@ -104,6 +104,7 @@ function MozInputMethod() { }
MozInputMethod.prototype = {
_inputcontext: null,
_wrappedInputContext: null,
_layouts: {},
_window: null,
_isSystem: false,
@ -211,7 +212,7 @@ MozInputMethod.prototype = {
if (!WindowMap.isActive(this._window)) {
return null;
}
return this._inputcontext;
return this._wrappedInputContext;
},
set oninputcontextchange(handler) {
@ -226,6 +227,7 @@ MozInputMethod.prototype = {
if (this._inputcontext) {
this._inputcontext.destroy();
this._inputcontext = null;
this._wrappedInputContext = null;
this._mgmt._supportsSwitching = false;
}
@ -236,6 +238,10 @@ MozInputMethod.prototype = {
this._inputcontext = new MozInputContext(data);
this._inputcontext.init(this._window);
// inputcontext will be exposed as a WebIDL object. Create its
// content-side object explicitly to avoid Bug 1001325.
this._wrappedInputContext =
this._window.MozInputContext._create(this._window, this._inputcontext);
}
let event = new this._window.Event("inputcontextchange",

View File

@ -12,8 +12,15 @@ function peerReadyCb(evt) {
let peer = nfc.getNFCPeer(evt.detail);
ok(peer instanceof MozNFCPeer, "Should get a NFCPeer object.");
// reset callback and NFC Hardware.
// reset callback.
nfc.onpeerready = null;
emulator.deactivate();
}
function peerLostCb() {
log("peerLostCb called");
ok(true);
nfc.onpeerlost = null;
toggleNFC(false).then(runNextTest);
}
@ -23,6 +30,7 @@ function handleTechnologyDiscoveredRE0(msg) {
is(msg.techList[0], "P2P", "check for correct tech type");
nfc.onpeerready = peerReadyCb;
nfc.onpeerlost = peerLostCb;
let request = nfc.checkP2PRegistration(MANIFEST_URL);
request.onsuccess = function (evt) {

View File

@ -286,7 +286,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
isRegisteredP2PTarget: function isRegisteredP2PTarget(appId, event) {
let targetInfo = this.peerTargetsMap[appId];
// Check if it is a registered target for the 'event'
return ((targetInfo != null) && (targetInfo.event & event !== 0));
return ((targetInfo != null) && ((targetInfo.event & event) !== 0));
},
notifyPeerEvent: function notifyPeerEvent(appId, event) {
@ -527,7 +527,7 @@ Nfc.prototype = {
gSystemMessenger.broadcastMessage("nfc-manager-tech-lost", message);
// Notify 'PeerLost' to appropriate registered target, if any
gMessageManager.notifyPeerEvent(this.currentPeerAppId, NFC.NFC_PEER_EVENT_LOST);
gMessageManager.notifyPeerEvent(gMessageManager.currentPeerAppId, NFC.NFC_PEER_EVENT_LOST);
delete this.sessionTokenMap[this._currentSessionId];
this._currentSessionId = null;
this.currentPeerAppId = null;

View File

@ -315,7 +315,7 @@ interface MozWifiManager : EventTarget {
* An event listener that is called with information about the signal
* strength and link speed every 5 seconds.
*/
attribute EventHandler onconnectionInfoUpdate;
attribute EventHandler onconnectioninfoupdate;
/**
* These two events fire when the wifi system is brought online or taken
@ -328,5 +328,5 @@ interface MozWifiManager : EventTarget {
* An event listener that is called with information about the number
* of wifi stations connected to wifi hotspot every 5 seconds.
*/
attribute EventHandler onstationInfoUpdate;
attribute EventHandler onstationinfoupdate;
};

View File

@ -77,10 +77,10 @@ MozWifiCapabilities.prototype = {
function DOMWifiManager() {
this.defineEventHandlerGetterSetter("onstatuschange");
this.defineEventHandlerGetterSetter("onconnectionInfoUpdate");
this.defineEventHandlerGetterSetter("onconnectioninfoupdate");
this.defineEventHandlerGetterSetter("onenabled");
this.defineEventHandlerGetterSetter("ondisabled");
this.defineEventHandlerGetterSetter("onstationInfoUpdate");
this.defineEventHandlerGetterSetter("onstationinfoupdate");
}
DOMWifiManager.prototype = {
@ -117,9 +117,9 @@ DOMWifiManager.prototype = {
"WifiManager:onconnecting", "WifiManager:onassociate",
"WifiManager:onconnect", "WifiManager:ondisconnect",
"WifiManager:onwpstimeout", "WifiManager:onwpsfail",
"WifiManager:onwpsoverlap", "WifiManager:connectionInfoUpdate",
"WifiManager:onwpsoverlap", "WifiManager:connectioninfoupdate",
"WifiManager:onauthenticating", "WifiManager:onconnectingfailed",
"WifiManager:stationInfoUpdate"];
"WifiManager:stationinfoupdate"];
this.initDOMRequestHelper(aWindow, messages);
this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
@ -379,7 +379,7 @@ DOMWifiManager.prototype = {
this._fireStatusChangeEvent();
break;
case "WifiManager:connectionInfoUpdate":
case "WifiManager:connectioninfoupdate":
this._lastConnectionInfo = this._convertConnectionInfo(msg);
this._fireConnectionInfoUpdate(msg);
break;
@ -394,7 +394,7 @@ DOMWifiManager.prototype = {
this._connectionStatus = "authenticating";
this._fireStatusChangeEvent();
break;
case "WifiManager:stationInfoUpdate":
case "WifiManager:stationinfoupdate":
this._stationNumber = msg.station;
this._fireStationInfoUpdate(msg);
break;
@ -426,7 +426,7 @@ DOMWifiManager.prototype = {
},
_fireStationInfoUpdate: function onStationInfoUpdate(info) {
var evt = new this._window.MozWifiStationInfoEvent("stationInfoUpdate",
var evt = new this._window.MozWifiStationInfoEvent("stationinfoupdate",
{ station: this._stationNumber}
);
this.__DOM_IMPL__.dispatchEvent(evt);

View File

@ -1112,7 +1112,7 @@ var WifiManager = (function() {
function getWifiHotspotStatus() {
wifiCommand.hostapdGetStations(function(result) {
notify("stationInfoUpdate", {station: result});
notify("stationinfoupdate", {station: result});
});
}
@ -2324,8 +2324,8 @@ function WifiWorker() {
});
};
WifiManager.onstationInfoUpdate = function() {
self._fireEvent("stationInfoUpdate", { station: this.station });
WifiManager.onstationinfoupdate = function() {
self._fireEvent("stationinfoupdate", { station: this.station });
};
// Read the 'wifi.enabled' setting in order to start with a known
@ -2511,8 +2511,8 @@ WifiWorker.prototype = {
}
self._lastConnectionInfo = info;
debug("Firing connectionInfoUpdate: " + uneval(info));
self._fireEvent("connectionInfoUpdate", info);
debug("Firing connectioninfoupdate: " + uneval(info));
self._fireEvent("connectioninfoupdate", info);
});
}

View File

@ -6,6 +6,7 @@
package org.mozilla.gecko.db;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import org.mozilla.gecko.db.BrowserContract.ExpirePriority;
@ -13,6 +14,7 @@ import org.mozilla.gecko.db.SuggestedSites;
import org.mozilla.gecko.distribution.Distribution;
import org.mozilla.gecko.favicons.decoders.LoadFaviconResult;
import org.mozilla.gecko.mozglue.RobocopTarget;
import org.mozilla.gecko.util.StringUtils;
import android.content.ContentResolver;
import android.content.ContentValues;
@ -35,6 +37,10 @@ public class BrowserDB {
public static String KEYWORD = "keyword";
}
public static enum FilterFlags {
EXCLUDE_PINNED_SITES
}
private static BrowserDBIface sDb = null;
private static SuggestedSites sSuggestedSites;
@ -42,7 +48,8 @@ public class BrowserDB {
public void invalidateCachedState();
@RobocopTarget
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit);
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit,
EnumSet<FilterFlags> flags);
// This should only return frecent sites. BrowserDB.getTopSites will do the
// work to combine that list with the pinned sites list.
@ -176,13 +183,27 @@ public class BrowserDB {
@RobocopTarget
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
return sDb.filter(cr, constraint, limit);
return filter(cr, constraint, limit, EnumSet.noneOf(FilterFlags.class));
}
@RobocopTarget
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit,
EnumSet<FilterFlags> flags) {
return sDb.filter(cr, constraint, limit, flags);
}
private static void appendUrlsFromCursor(List<String> urls, Cursor c) {
c.moveToPosition(-1);
while (c.moveToNext()) {
urls.add(c.getString(c.getColumnIndex(URLColumns.URL)));
String url = c.getString(c.getColumnIndex(URLColumns.URL));
// Do a simpler check before decoding to avoid parsing
// all URLs unnecessarily.
if (StringUtils.isUserEnteredUrl(url)) {
url = StringUtils.decodeUserEnteredUrl(url);
}
urls.add(url);
};
}

View File

@ -11,6 +11,7 @@ import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
@ -32,6 +33,7 @@ import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
import org.mozilla.gecko.db.BrowserContract.SyncColumns;
import org.mozilla.gecko.db.BrowserContract.Thumbnails;
import org.mozilla.gecko.db.BrowserContract.URLColumns;
import org.mozilla.gecko.db.BrowserDB.FilterFlags;
import org.mozilla.gecko.distribution.Distribution;
import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
import org.mozilla.gecko.favicons.decoders.LoadFaviconResult;
@ -507,7 +509,19 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
}
@Override
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit,
EnumSet<FilterFlags> flags) {
String selection = "";
String[] selectionArgs = null;
if (flags.contains(FilterFlags.EXCLUDE_PINNED_SITES)) {
selection = Combined.URL + " NOT IN (SELECT " +
Bookmarks.URL + " FROM bookmarks WHERE " +
DBUtils.qualifyColumn("bookmarks", Bookmarks.PARENT) + " = ? AND " +
DBUtils.qualifyColumn("bookmarks", Bookmarks.IS_DELETED) + " == 0)";
selectionArgs = new String[] { String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID) };
}
return filterAllSites(cr,
new String[] { Combined._ID,
Combined.URL,
@ -517,7 +531,8 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
Combined.HISTORY_ID },
constraint,
limit,
null);
null,
selection, selectionArgs);
}
@Override

View File

@ -196,7 +196,7 @@ abstract class HomeFragment extends Fragment {
// Some pinned site items have "user-entered" urls. URLs entered in the PinSiteDialog are wrapped in
// a special URI until we can get a valid URL. If the url is a user-entered url, decode the URL before loading it.
final Tab newTab = Tabs.getInstance().loadUrl(decodeUserEnteredUrl(url), flags);
final Tab newTab = Tabs.getInstance().loadUrl(StringUtils.decodeUserEnteredUrl(url), flags);
final int newTabId = newTab.getId(); // We don't want to hold a reference to the Tab.
final String message = isPrivate ?
@ -275,22 +275,6 @@ abstract class HomeFragment extends Fragment {
return mCanLoadHint;
}
/**
* Given a url with a user-entered scheme, extract the
* scheme-specific component. For e.g, given "user-entered://www.google.com",
* this method returns "//www.google.com". If the passed url
* does not have a user-entered scheme, the same url will be returned.
*
* @param url to be decoded
* @return url component entered by user
*/
public static String decodeUserEnteredUrl(String url) {
Uri uri = Uri.parse(url);
if ("user-entered".equals(uri.getScheme())) {
return uri.getSchemeSpecificPart();
}
return url;
}
protected abstract void load();

View File

@ -5,8 +5,12 @@
package org.mozilla.gecko.home;
import java.util.EnumSet;
import org.mozilla.gecko.R;
import org.mozilla.gecko.db.BrowserDB.FilterFlags;
import org.mozilla.gecko.db.BrowserDB.URLColumns;
import org.mozilla.gecko.util.StringUtils;
import android.content.Context;
import android.database.Cursor;
@ -111,7 +115,7 @@ class PinSiteDialog extends DialogFragment {
// a special URI until we can get a valid URL for this bookmark.
final String text = mSearch.getText().toString().trim();
if (!TextUtils.isEmpty(text)) {
final String url = TopSitesPanel.encodeUserEnteredUrl(text);
final String url = StringUtils.encodeUserEnteredUrl(text);
mOnSiteSelectedListener.onSiteSelected(url, text);
dismiss();
}
@ -191,7 +195,9 @@ class PinSiteDialog extends DialogFragment {
private void filter(String searchTerm) {
// Restart loaders with the new search term
SearchLoader.restart(getLoaderManager(), LOADER_ID_SEARCH, mLoaderCallbacks, searchTerm);
SearchLoader.restart(getLoaderManager(), LOADER_ID_SEARCH,
mLoaderCallbacks, searchTerm,
EnumSet.of(FilterFlags.EXCLUDE_PINNED_SITES));
}
public void setOnSiteSelectedListener(OnSiteSelectedListener listener) {

View File

@ -5,8 +5,11 @@
package org.mozilla.gecko.home;
import java.util.EnumSet;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.db.BrowserDB.FilterFlags;
import android.content.Context;
import android.database.Cursor;
@ -24,35 +27,52 @@ class SearchLoader {
public static final String LOGTAG = "GeckoSearchLoader";
private static final String KEY_SEARCH_TERM = "search_term";
private static final String KEY_FILTER_FLAGS = "flags";
private SearchLoader() {
}
@SuppressWarnings("unchecked")
public static Loader<Cursor> createInstance(Context context, Bundle args) {
if (args != null) {
final String searchTerm = args.getString(KEY_SEARCH_TERM);
return new SearchCursorLoader(context, searchTerm);
final EnumSet<FilterFlags> flags =
(EnumSet<FilterFlags>) args.getSerializable(KEY_FILTER_FLAGS);
return new SearchCursorLoader(context, searchTerm, flags);
} else {
return new SearchCursorLoader(context, "");
return new SearchCursorLoader(context, "", EnumSet.noneOf(FilterFlags.class));
}
}
private static Bundle createArgs(String searchTerm) {
private static Bundle createArgs(String searchTerm, EnumSet<FilterFlags> flags) {
Bundle args = new Bundle();
args.putString(SearchLoader.KEY_SEARCH_TERM, searchTerm);
args.putSerializable(SearchLoader.KEY_FILTER_FLAGS, flags);
return args;
}
public static void init(LoaderManager manager, int loaderId,
LoaderCallbacks<Cursor> callbacks, String searchTerm) {
final Bundle args = createArgs(searchTerm);
LoaderCallbacks<Cursor> callbacks, String searchTerm) {
init(manager, loaderId, callbacks, searchTerm, EnumSet.noneOf(FilterFlags.class));
}
public static void init(LoaderManager manager, int loaderId,
LoaderCallbacks<Cursor> callbacks, String searchTerm,
EnumSet<FilterFlags> flags) {
final Bundle args = createArgs(searchTerm, flags);
manager.initLoader(loaderId, args, callbacks);
}
public static void restart(LoaderManager manager, int loaderId,
LoaderCallbacks<Cursor> callbacks, String searchTerm) {
final Bundle args = createArgs(searchTerm);
restart(manager, loaderId, callbacks, searchTerm, EnumSet.noneOf(FilterFlags.class));
}
public static void restart(LoaderManager manager, int loaderId,
LoaderCallbacks<Cursor> callbacks, String searchTerm,
EnumSet<FilterFlags> flags) {
final Bundle args = createArgs(searchTerm, flags);
manager.restartLoader(loaderId, args, callbacks);
}
@ -65,15 +85,19 @@ class SearchLoader {
// The target search term associated with the loader
private final String mSearchTerm;
public SearchCursorLoader(Context context, String searchTerm) {
// The filter flags associated with the loader
private final EnumSet<FilterFlags> mFlags;
public SearchCursorLoader(Context context, String searchTerm, EnumSet<FilterFlags> flags) {
super(context);
mSearchTerm = searchTerm;
mFlags = flags;
}
@Override
public Cursor loadCursor() {
final long start = SystemClock.uptimeMillis();
final Cursor cursor = BrowserDB.filter(getContext().getContentResolver(), mSearchTerm, SEARCH_LIMIT);
final Cursor cursor = BrowserDB.filter(getContext().getContentResolver(), mSearchTerm, SEARCH_LIMIT, mFlags);
final long end = SystemClock.uptimeMillis();
final long took = end - start;
Telemetry.HistogramAdd(TELEMETRY_HISTOGRAM_LOAD_CURSOR, (int) Math.min(took, Integer.MAX_VALUE));

View File

@ -136,9 +136,8 @@ public class TopSitesGridItemView extends RelativeLayout {
public void blankOut() {
mUrl = "";
mTitle = "";
mType = TopSites.TYPE_BLANK;
updateType(TopSites.TYPE_BLANK);
updateTitleView();
mTitleView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
setLoadId(Favicons.NOT_LOADING);
Picasso.with(getContext()).cancelRequest(mThumbnailView);
displayThumbnail(R.drawable.top_site_add);
@ -182,12 +181,7 @@ public class TopSitesGridItemView extends RelativeLayout {
Picasso.with(getContext()).cancelRequest(mThumbnailView);
}
if (mType != type) {
mType = type;
int pinResourceId = (type == TopSites.TYPE_PINNED ? R.drawable.pin : 0);
mTitleView.setCompoundDrawablesWithIntrinsicBounds(pinResourceId, 0, 0, 0);
if (updateType(type)) {
changed = true;
}
@ -291,6 +285,24 @@ public class TopSitesGridItemView extends RelativeLayout {
}
}
/**
* Update the item type associated with this view. Returns true if
* the type has changed, false otherwise.
*/
private boolean updateType(int type) {
if (mType == type) {
return false;
}
mType = type;
refreshDrawableState();
int pinResourceId = (type == TopSites.TYPE_PINNED ? R.drawable.pin : 0);
mTitleView.setCompoundDrawablesWithIntrinsicBounds(pinResourceId, 0, 0, 0);
return true;
}
/**
* Update the title shown by this view. If both title and url
* are empty, mark the state as STATE_EMPTY and show a default text.
@ -302,9 +314,6 @@ public class TopSitesGridItemView extends RelativeLayout {
} else {
mTitleView.setText(R.string.home_top_sites_add);
}
// Refresh for state change.
refreshDrawableState();
}
public void setLoadId(int aLoadId) {

View File

@ -14,6 +14,7 @@ import org.mozilla.gecko.ThumbnailHelper;
import org.mozilla.gecko.db.BrowserContract.TopSites;
import org.mozilla.gecko.db.TopSitesCursorWrapper;
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
import org.mozilla.gecko.util.StringUtils;
import android.content.Context;
import android.content.res.TypedArray;
@ -106,7 +107,7 @@ public class TopSitesGridView extends GridView {
TopSitesGridItemView item = (TopSitesGridItemView) view;
// Decode "user-entered" URLs before loading them.
String url = HomeFragment.decodeUserEnteredUrl(item.getUrl());
String url = StringUtils.decodeUserEnteredUrl(item.getUrl());
int type = item.getType();
// If the url is empty, the user can pin a site.

View File

@ -356,7 +356,8 @@ public class TopSitesPanel extends HomeFragment {
if (itemId == R.id.top_sites_edit) {
// Decode "user-entered" URLs before showing them.
mEditPinnedSiteListener.onEditPinnedSite(info.position, decodeUserEnteredUrl(info.url));
mEditPinnedSiteListener.onEditPinnedSite(info.position,
StringUtils.decodeUserEnteredUrl(info.url));
Telemetry.sendUIEvent(TelemetryContract.Event.EDIT);
return true;
@ -378,10 +379,6 @@ public class TopSitesPanel extends HomeFragment {
ThreadUtils.reduceGeckoPriority(PRIORITY_RESET_TIMEOUT);
}
static String encodeUserEnteredUrl(String url) {
return Uri.fromParts("user-entered", url, null).toString();
}
/**
* Listener for editing pinned sites.
*/
@ -558,11 +555,14 @@ public class TopSitesPanel extends HomeFragment {
return;
}
// Make sure we query suggested images without the user-entered wrapper.
final String decodedUrl = StringUtils.decodeUserEnteredUrl(url);
// Suggested images have precedence over thumbnails, no need to wait
// for them to be loaded. See: CursorLoaderCallbacks.onLoadFinished()
final String imageUrl = BrowserDB.getSuggestedImageUrlForUrl(url);
final String imageUrl = BrowserDB.getSuggestedImageUrlForUrl(decodedUrl);
if (!TextUtils.isEmpty(imageUrl)) {
final int bgColor = BrowserDB.getSuggestedBackgroundColorForUrl(url);
final int bgColor = BrowserDB.getSuggestedBackgroundColorForUrl(decodedUrl);
view.displayThumbnail(imageUrl, bgColor);
return;
}

View File

@ -355,7 +355,7 @@
<string name="bookmarkdefaults_url_addons">https://addons.mozilla.org/@AB_CD@/android/</string>
<string name="bookmarkdefaults_title_support">@bookmarks_support@</string>
<string name="bookmarkdefaults_url_support">http://support.mozilla.org/@AB_CD@/products/mobile</string>
<string name="bookmarkdefaults_url_support">https://support.mozilla.org/@AB_CD@/products/mobile</string>
<string name="bookmarkdefaults_favicon_abouthome">chrome/chrome/content/branding/favicon64.png</string>
<!-- Icon is automatically generated from R.drawable.bookmarkdefaults_favicon_marketplace -->

View File

@ -10,7 +10,7 @@ public class StringHelper {
};
public static final String[] DEFAULT_BOOKMARKS_URLS = new String[] {
"about:firefox",
"http://support.mozilla.org/en-US/products/mobile",
"https://support.mozilla.org/en-US/products/mobile",
"https://addons.mozilla.org/en-US/android/"
};
public static final int DEFAULT_BOOKMARKS_COUNT = DEFAULT_BOOKMARKS_TITLES.length;

View File

@ -5,10 +5,12 @@
package org.mozilla.gecko.tests;
import java.io.File;
import java.util.EnumSet;
import java.util.Random;
import java.util.UUID;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserDB.FilterFlags;
import org.mozilla.gecko.db.BrowserProvider;
import org.mozilla.gecko.db.LocalBrowserDB;
import org.mozilla.gecko.util.FileUtils;
@ -270,7 +272,8 @@ public class testBrowserProviderPerf extends BaseRobocopTest {
// Make sure we're querying the right profile.
final LocalBrowserDB db = new LocalBrowserDB(mProfile);
final Cursor before = db.filter(mResolver, KNOWN_PREFIX, limit);
final Cursor before = db.filter(mResolver, KNOWN_PREFIX, limit,
EnumSet.noneOf(FilterFlags.class));
try {
mAsserter.is(before.getCount(), 0, "Starts empty");
} finally {
@ -295,7 +298,8 @@ public class testBrowserProviderPerf extends BaseRobocopTest {
// Time the query.
final long start = SystemClock.uptimeMillis();
final Cursor c = db.filter(mResolver, KNOWN_PREFIX, limit);
final Cursor c = db.filter(mResolver, KNOWN_PREFIX, limit,
EnumSet.noneOf(FilterFlags.class));
try {
final int count = c.getCount();

View File

@ -11,6 +11,7 @@ import android.text.TextUtils;
public class StringUtils {
private static final String FILTER_URL_PREFIX = "filter://";
private static final String USER_ENTERED_URL_PREFIX = "user-entered:";
/*
* This method tries to guess if the given string could be a search query or URL,
@ -160,4 +161,29 @@ public class StringUtils {
return !("about".equals(scheme) || "chrome".equals(scheme) ||
"file".equals(scheme) || "resource".equals(scheme));
}
public static boolean isUserEnteredUrl(String url) {
return (url != null && url.startsWith(USER_ENTERED_URL_PREFIX));
}
/**
* Given a url with a user-entered scheme, extract the
* scheme-specific component. For e.g, given "user-entered://www.google.com",
* this method returns "//www.google.com". If the passed url
* does not have a user-entered scheme, the same url will be returned.
*
* @param url to be decoded
* @return url component entered by user
*/
public static String decodeUserEnteredUrl(String url) {
Uri uri = Uri.parse(url);
if ("user-entered".equals(uri.getScheme())) {
return uri.getSchemeSpecificPart();
}
return url;
}
public static String encodeUserEnteredUrl(String url) {
return Uri.fromParts("user-entered", url, null).toString();
}
}

View File

@ -1027,7 +1027,7 @@ this.PlacesUtils = {
* The container node to search through.
* @returns true if the node contains uri nodes, false otherwise.
*/
hasChildURIs: function PU_hasChildURIs(aNode) {
hasChildURIs: function PU_hasChildURIs(aNode, aMultiple=false) {
if (!this.nodeIsContainer(aNode))
return false;
@ -1043,11 +1043,14 @@ this.PlacesUtils = {
root.containerOpen = true;
}
let foundFirst = !aMultiple;
let found = false;
for (let i = 0; i < root.childCount && !found; i++) {
let child = root.getChild(i);
if (this.nodeIsURI(child))
found = true;
if (this.nodeIsURI(child)) {
found = foundFirst;
foundFirst = true;
}
}
if (!wasOpen) {

View File

@ -165,6 +165,7 @@ function check_uri_nodes(aQuery, aOptions, aExpectedURINodes) {
root.containerOpen = true;
var node = root.getChild(0);
do_check_eq(PU.hasChildURIs(node), aExpectedURINodes > 0);
do_check_eq(PU.hasChildURIs(node, true), aExpectedURINodes > 1);
do_check_eq(PU.getURLsForContainerNode(node).length, aExpectedURINodes);
root.containerOpen = false;
}

View File

@ -124,6 +124,8 @@ exports.items = [
height = rect.height;
}
} else {
// Bug 961832: GCLI screenshot shows fixed position element in wrong position if
// we don't scroll to top
window.scrollTo(0,0);
width = window.innerWidth + window.scrollMaxX;
height = window.innerHeight + window.scrollMaxY;

View File

@ -49,7 +49,7 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({
this._ticks = [];
this._startTime = this._chromeWin.performance.now();
this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick);
this._rafID = this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick);
}, {
}),
@ -60,11 +60,8 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({
if (!this._recording) {
return [];
}
this._recording = false;
// We don't need to store the ticks array for future use, release it.
let ticks = this.getPendingTicks(beginAt, endAt);
this._ticks = null;
this.cancelRecording();
return ticks;
}, {
request: {
@ -74,6 +71,17 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({
response: { ticks: RetVal("array:number") }
}),
/**
* Stops monitoring framerate, without returning the recorded values.
*/
cancelRecording: method(function() {
this._chromeWin.cancelAnimationFrame(this._rafID);
this._recording = false;
this._ticks = null;
this._rafID = -1;
}, {
}),
/**
* Gets the refresh driver ticks recorded so far.
*/
@ -97,7 +105,7 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({
if (!this._recording) {
return;
}
this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick);
this._rafID = this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick);
// Store the amount of time passed since the recording started.
let currentTime = this._chromeWin.performance.now();
@ -113,58 +121,57 @@ let FramerateFront = exports.FramerateFront = protocol.FrontClass(FramerateActor
initialize: function(client, { framerateActor }) {
protocol.Front.prototype.initialize.call(this, client, { actor: framerateActor });
this.manage(this);
},
/**
* Plots the frames per second on a timeline.
*
* @param array ticks
* The raw data received from the framerate actor, which represents
* the elapsed time on each refresh driver tick.
* @param number interval
* The maximum amount of time to wait between calculations.
* @param number clamp
* The maximum allowed framerate value.
* @return array
* A collection of { delta, value } objects representing the
* framerate value at every delta time.
*/
plotFPS: function(ticks, interval = 100, clamp = 60) {
let timeline = [];
let totalTicks = ticks.length;
// If the refresh driver didn't get a chance to tick before the
// recording was stopped, assume framerate was 0.
if (totalTicks == 0) {
timeline.push({ delta: 0, value: 0 });
timeline.push({ delta: interval, value: 0 });
return timeline;
}
let frameCount = 0;
let prevTime = ticks[0];
for (let i = 1; i < totalTicks; i++) {
let currTime = ticks[i];
frameCount++;
let elapsedTime = currTime - prevTime;
if (elapsedTime < interval) {
continue;
}
let framerate = Math.min(1000 / (elapsedTime / frameCount), clamp);
timeline.push({ delta: prevTime, value: framerate });
timeline.push({ delta: currTime, value: framerate });
frameCount = 0;
prevTime = currTime;
}
return timeline;
}
});
/**
* Plots the frames per second on a timeline.
*
* @param array ticks
* The raw data received from the framerate actor, which represents
* the elapsed time on each refresh driver tick.
* @param number interval
* The maximum amount of time to wait between calculations.
* @param number clamp
* The maximum allowed framerate value.
* @return array
* A collection of { delta, value } objects representing the
* framerate value at every delta time.
*/
FramerateFront.plotFPS = function(ticks, interval = 100, clamp = 60) {
let timeline = [];
let totalTicks = ticks.length;
// If the refresh driver didn't get a chance to tick before the
// recording was stopped, assume framerate was 0.
if (totalTicks == 0) {
timeline.push({ delta: 0, value: 0 });
timeline.push({ delta: interval, value: 0 });
return timeline;
}
let frameCount = 0;
let prevTime = ticks[0];
for (let i = 1; i < totalTicks; i++) {
let currTime = ticks[i];
frameCount++;
let elapsedTime = currTime - prevTime;
if (elapsedTime < interval) {
continue;
}
let framerate = Math.min(1000 / (elapsedTime / frameCount), clamp);
timeline.push({ delta: prevTime, value: framerate });
timeline.push({ delta: currTime, value: framerate });
frameCount = 0;
prevTime = currTime;
}
return timeline;
};
/**
* Gets the top level browser window from a content window.

View File

@ -276,6 +276,12 @@ LayoutChangesObserver.prototype = Heritage.extend(Observable.prototype, {
* Calls itself in a loop.
*/
_startEventLoop: function() {
// Avoid emitting events if the tabActor has been detached (may happen
// during shutdown)
if (!this.tabActor.attached) {
return;
}
// Send any reflows we have
if (this.reflows && this.reflows.length) {
this.emit("reflows", this.reflows);

View File

@ -498,7 +498,8 @@ function ThreadActor(aHooks, aGlobal)
this._allEventsListener = this._allEventsListener.bind(this);
this._options = {
useSourceMaps: false
useSourceMaps: false,
autoBlackBox: false
};
this._gripDepth = 0;
@ -536,7 +537,7 @@ ThreadActor.prototype = {
get sources() {
if (!this._sources) {
this._sources = new ThreadSources(this, this._options.useSourceMaps,
this._sources = new ThreadSources(this, this._options,
this._allowSource, this.onNewSource);
}
return this._sources;
@ -4967,10 +4968,11 @@ exports.AddonThreadActor = AddonThreadActor;
* Manages the sources for a thread. Handles source maps, locations in the
* sources, etc for ThreadActors.
*/
function ThreadSources(aThreadActor, aUseSourceMaps, aAllowPredicate,
function ThreadSources(aThreadActor, aOptions, aAllowPredicate,
aOnNewSource) {
this._thread = aThreadActor;
this._useSourceMaps = aUseSourceMaps;
this._useSourceMaps = aOptions.useSourceMaps;
this._autoBlackBox = aOptions.autoBlackBox;
this._allow = aAllowPredicate;
this._onNewSource = aOnNewSource;
@ -4991,6 +4993,13 @@ function ThreadSources(aThreadActor, aUseSourceMaps, aAllowPredicate,
ThreadSources._blackBoxedSources = new Set(["self-hosted"]);
ThreadSources._prettyPrintedSources = new Map();
/**
* Matches strings of the form "foo.min.js" or "foo-min.js", etc. If the regular
* expression matches, we can be fairly sure that the source is minified, and
* treat it as such.
*/
const MINIFIED_SOURCE_REGEXP = /\bmin\.js$/;
ThreadSources.prototype = {
/**
* Return the source actor representing |url|, creating one if none
@ -5022,6 +5031,10 @@ ThreadSources.prototype = {
return this._sourceActors[url];
}
if (this._autoBlackBox && this._isMinifiedURL(url)) {
this.blackBox(url);
}
let actor = new SourceActor({
url: url,
thread: this._thread,
@ -5040,6 +5053,26 @@ ThreadSources.prototype = {
return actor;
},
/**
* Returns true if the URL likely points to a minified resource, false
* otherwise.
*
* @param String aURL
* The URL to test.
* @returns Boolean
*/
_isMinifiedURL: function (aURL) {
try {
let url = Services.io.newURI(aURL, null, null)
.QueryInterface(Ci.nsIURL);
return MINIFIED_SOURCE_REGEXP.test(url.fileName);
} catch (e) {
// Not a valid URL so don't try to parse out the filename, just test the
// whole thing with the minified source regexp.
return MINIFIED_SOURCE_REGEXP.test(aURL);
}
},
/**
* Only to be used when we aren't source mapping.
*/
@ -5182,7 +5215,7 @@ ThreadSources.prototype = {
getOriginalLocation: function ({ url, line, column }) {
if (url in this._sourceMapsByGeneratedSource) {
column = column || 0;
return this._sourceMapsByGeneratedSource[url]
.then((aSourceMap) => {
let { source: aSourceURL, line: aLine, column: aColumn } = aSourceMap.originalPositionFor({

View File

@ -318,7 +318,7 @@ TraceActor.prototype = {
* Called by the engine when a frame is entered. Sends an unsolicited packet
* to the client carrying requested trace information.
*
* @param aFrame Debugger.frame
* @param aFrame Debugger.Frame
* The stack frame that was entered.
*/
onEnterFrame: function(aFrame) {

View File

@ -23,6 +23,7 @@ support-files =
[test_framerate_02.html]
[test_framerate_03.html]
[test_framerate_04.html]
[test_framerate_05.html]
[test_highlighter-boxmodel_01.html]
[test_highlighter-boxmodel_02.html]
[test_highlighter-csstransform_01.html]

View File

@ -58,7 +58,7 @@ window.onload = function() {
function onRecordingStopped(front, rawData) {
ok(rawData, "There should be a recording available.");
var timeline = front.plotFPS(rawData);
var timeline = FramerateFront.plotFPS(rawData);
ok(timeline.length >= 2,
"There should be at least one measurement available, with two entries.");

View File

@ -47,7 +47,7 @@ window.onload = function() {
ok(rawData, "There should be a recording available.");
is(rawData.length, 0, "...but it should be empty.");
var timeline = front.plotFPS(rawData);
var timeline = FramerateFront.plotFPS(rawData);
is(timeline.length, 2,
"There should be one measurement plotted, with two entries.");

View File

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<!--
Bug 1034648 - Tests whether a framerate recording can be cancelled.
-->
<head>
<meta charset="utf-8">
<title>Framerate actor test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script>
window.onload = function() {
var Cu = Components.utils;
var Cc = Components.classes;
var Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm");
// Always log packets when running tests.
Services.prefs.setBoolPref("devtools.debugger.log", true);
SimpleTest.registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.debugger.log");
});
Cu.import("resource://gre/modules/devtools/Loader.jsm");
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
SimpleTest.waitForExplicitFinish();
var {FramerateFront} = devtools.require("devtools/server/actors/framerate");
DebuggerServer.init(function () { return true; });
DebuggerServer.addBrowserActors();
var client = new DebuggerClient(DebuggerServer.connectPipe());
client.connect(function onConnect() {
client.listTabs(function onListTabs(aResponse) {
var form = aResponse.tabs[aResponse.selected];
var front = FramerateFront(client, form);
front.startRecording().then(() => {
window.setTimeout(() => {
front.cancelRecording().then(() => {
window.setTimeout(() => {
front.getPendingTicks().then(rawTicks => {
ok(rawTicks,
"The returned pending ticks should be empty (1).");
is(rawTicks.length, 0,
"The returned pending ticks should be empty (2).");
front.stopRecording().then(rawData => {
ok(rawData,
"The returned raw data should be an empty array (1).");
is(rawData.length, 0,
"The returned raw data should be an empty array (2).");
client.close(() => {
DebuggerServer.destroy();
SimpleTest.finish()
});
});
});
}, 1000);
});
}, 1000);
});
});
});
}
</script>
</pre>
</body>
</html>

View File

@ -178,7 +178,10 @@ function attachTestThread(aClient, aTitle, aCallback) {
function onAttach(aResponse, aThreadClient) {
aCallback(aResponse, aTabClient, aThreadClient);
}
aTabClient.attachThread({ useSourceMaps: true }, onAttach);
aTabClient.attachThread({
useSourceMaps: true,
autoBlackBox: true
}, onAttach);
});
}

View File

@ -0,0 +1,62 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that sources whose URL ends with ".min.js" automatically get black
* boxed.
*/
var gDebuggee;
var gClient;
var gThreadClient;
function run_test()
{
initTestDebuggerServer();
gDebuggee = addTestGlobal("test-black-box");
gClient = new DebuggerClient(DebuggerServer.connectPipe());
gClient.connect(function() {
attachTestTabAndResume(gClient, "test-black-box", function(aResponse, aTabClient, aThreadClient) {
gThreadClient = aThreadClient;
testBlackBox();
});
});
do_test_pending();
}
const BLACK_BOXED_URL = "http://example.com/black-boxed.min.js";
const SOURCE_URL = "http://example.com/source.js";
const testBlackBox = Task.async(function* () {
yield executeOnNextTickAndWaitForPause(evalCode, gClient);
const { sources } = yield getSources(gThreadClient);
equal(sources.length, 2);
const blackBoxedSource = sources.filter(s => s.url === BLACK_BOXED_URL)[0];
equal(blackBoxedSource.isBlackBoxed, true);
const regularSource = sources.filter(s => s.url === SOURCE_URL)[0];
equal(regularSource.isBlackBoxed, false);
finishClient(gClient);
});
function evalCode() {
Components.utils.evalInSandbox(
"" + function blackBoxed() {},
gDebuggee,
"1.8",
BLACK_BOXED_URL,
1
);
Components.utils.evalInSandbox(
"" + function source() {}
+ "\ndebugger;",
gDebuggee,
"1.8",
SOURCE_URL,
1
);
}

View File

@ -21,6 +21,7 @@ LayoutChangesObserver.prototype._clearTimeout = function() {};
function MockTabActor() {
this.window = new MockWindow();
this.windows = [this.window];
this.attached = true;
}
function MockWindow() {}

View File

@ -32,6 +32,7 @@ support-files =
[test_blackboxing-04.js]
[test_blackboxing-05.js]
[test_blackboxing-06.js]
[test_blackboxing-07.js]
[test_frameactor-01.js]
[test_frameactor-02.js]
[test_frameactor-03.js]