This commit is contained in:
Wes Kocher 2015-06-05 16:03:46 -07:00
Родитель 183c9e5fd2 12f2b44c0e
Коммит 8f17e389c4
78 изменённых файлов: 1017 добавлений и 443 удалений

Просмотреть файл

@ -15,7 +15,7 @@
<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="ae4ef3f63b921fa46c20d9d4feb271713fb014ba"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d62b32408567f9f7cf1c71c1e5a0c6593be757b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -15,7 +15,7 @@
<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="ae4ef3f63b921fa46c20d9d4feb271713fb014ba"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d62b32408567f9f7cf1c71c1e5a0c6593be757b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae4ef3f63b921fa46c20d9d4feb271713fb014ba"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d62b32408567f9f7cf1c71c1e5a0c6593be757b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>

Просмотреть файл

@ -17,7 +17,7 @@
</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="ae4ef3f63b921fa46c20d9d4feb271713fb014ba"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d62b32408567f9f7cf1c71c1e5a0c6593be757b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5c487ecd9afbcea1d507b9e4dfd09b3a8787fa65"/>

Просмотреть файл

@ -15,7 +15,7 @@
<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="ae4ef3f63b921fa46c20d9d4feb271713fb014ba"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d62b32408567f9f7cf1c71c1e5a0c6593be757b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -15,7 +15,7 @@
<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="ae4ef3f63b921fa46c20d9d4feb271713fb014ba"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d62b32408567f9f7cf1c71c1e5a0c6593be757b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae4ef3f63b921fa46c20d9d4feb271713fb014ba"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d62b32408567f9f7cf1c71c1e5a0c6593be757b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>

Просмотреть файл

@ -15,7 +15,7 @@
<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="ae4ef3f63b921fa46c20d9d4feb271713fb014ba"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d62b32408567f9f7cf1c71c1e5a0c6593be757b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "ae4ef3f63b921fa46c20d9d4feb271713fb014ba",
"git_revision": "1d62b32408567f9f7cf1c71c1e5a0c6593be757b",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "d9730e79977fe0a3416596d1ec9e942ed6dc15a9",
"revision": "63c872ccb3541c2ddb0d67f112480eb8f2650cda",
"repo_path": "integration/gaia-central"
}

Просмотреть файл

@ -17,7 +17,7 @@
</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="ae4ef3f63b921fa46c20d9d4feb271713fb014ba"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d62b32408567f9f7cf1c71c1e5a0c6593be757b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5c487ecd9afbcea1d507b9e4dfd09b3a8787fa65"/>

Просмотреть файл

@ -15,7 +15,7 @@
<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="ae4ef3f63b921fa46c20d9d4feb271713fb014ba"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d62b32408567f9f7cf1c71c1e5a0c6593be757b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -171,10 +171,19 @@ const gXPInstallObserver = {
args = [brandShortName, Services.appinfo.version, install.name];
}
// Add Learn More link when refusing to install an unsigned add-on
if (install.error == AddonManager.ERROR_SIGNEDSTATE_REQUIRED) {
options.learnMoreURL =
Services.prefs.getCharPref("xpinstall.signatures.infoURL");
}
messageString = gNavigatorBundle.getFormattedString(error, args);
PopupNotifications.show(browser, notificationID, messageString, anchorID,
action, null, options);
// Can't have multiple notifications with the same ID, so stop here.
break;
}
this._removeProgressNotification(browser);
break; }

Просмотреть файл

@ -482,7 +482,6 @@ input[type=button] {
line-height: 52px;
padding-left: 15px;
font-weight: 600;
text-transform: uppercase;
cursor: default;
border-radius: 5px 5px 0px 0px;
}

Просмотреть файл

@ -34,7 +34,7 @@
<xul:panel id="newtab-customize-panel" orient="vertical" type="arrow"
noautohide="true" hidden="true">
<xul:hbox id="newtab-customize-title" class="newtab-customize-panel-item">
<xul:label>&newtab.customize.cog.title;</xul:label>
<xul:label>&newtab.customize.cog.title2;</xul:label>
</xul:hbox>
<xul:vbox class="newtab-customize-complex-option">
<xul:hbox id="newtab-customize-classic" class="newtab-customize-panel-superitem newtab-customize-panel-item selectable">

Просмотреть файл

@ -253,7 +253,6 @@ skip-if = e10s # bug 1102331 - does focus things on the content window which bre
[browser_bug749738.js]
[browser_bug763468_perwindowpb.js]
[browser_bug767836_perwindowpb.js]
[browser_bug771331.js]
[browser_bug783614.js]
[browser_bug817947.js]
[browser_bug822367.js]

Просмотреть файл

@ -576,11 +576,11 @@
// Array of nodes found by findNodes which should be opened
var nodesToOpen = [];
// A set of URIs of container-nodes that were previously searched,
// A set of GUIDs of container-nodes that were previously searched,
// and thus shouldn't be searched again. This is empty at the initial
// start of the recursion and gets filled in as the recursion
// progresses.
var nodesURIChecked = [];
var checkedGuidsSet = new Set();
/**
* Recursively search through a node's children for items
@ -606,20 +606,18 @@
ids.splice(index, 1);
}
var concreteGuid = PlacesUtils.getConcreteItemGuid(node);
if (ids.length == 0 || !PlacesUtils.nodeIsContainer(node) ||
nodesURIChecked.indexOf(node.uri) != -1)
checkedGuidsSet.has(concreteGuid))
return foundOne;
// Don't try to open a query or a shurtcut, since it may return
// any duplicate data and be infinitely nested. Though, if it has
// been explicitly opened by the caller, search into it.
let shouldOpen = aOpenContainers &&
node.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER;
// Only follow a query if it has been been explicitly opened by the caller.
let shouldOpen = aOpenContainers && PlacesUtils.nodeIsFolder(node);
PlacesUtils.asContainer(node);
if (!node.containerOpen && !shouldOpen)
return foundOne;
nodesURIChecked.push(node.uri);
checkedGuidsSet.add(concreteGuid);
// Remember the beginning state so that we can re-close
// this node if we don't find any additional results here.

Просмотреть файл

@ -4,6 +4,7 @@ support-files = head.js
[test_0_bug510634.xul]
[test_0_multiple_left_pane.xul]
[test_bug1163447_selectItems_through_shortcut.xul]
[test_bug427633_no_newfolder_if_noip.xul]
[test_bug485100-change-case-loses-tag.xul]
[test_bug549192.xul]

Просмотреть файл

@ -0,0 +1,89 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="1163447: selectItems in Places no longer selects items within Toolbar or Sidebar folders"
onload="runTest();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript" src="head.js" />
<body xmlns="http://www.w3.org/1999/xhtml" />
<tree id="tree"
type="places"
flex="1">
<treecols>
<treecol label="Title" id="title" anonid="title" primary="true" ordinal="1" flex="1"/>
</treecols>
<treechildren flex="1"/>
</tree>
<script type="application/javascript"><![CDATA[
/**
* Bug 1163447: places-tree should be able to select an item within the toolbar, and
* unfiled bookmarks. Yet not follow recursive folder-shortcuts infinitely.
*/
function runTest() {
SimpleTest.waitForExplicitFinish();
Task.spawn(function* () {
let bmu = PlacesUtils.bookmarks;
yield bmu.insert({
parentGuid: bmu.toolbarGuid,
index: bmu.DEFAULT_INDEX,
type: bmu.TYPE_BOOKMARK,
url: "place:folder=TOOLBAR",
title: "shortcut to self - causing infinite recursion if not handled properly"
});
yield bmu.insert({
parentGuid: bmu.toolbarGuid,
index: bmu.DEFAULT_INDEX,
type: bmu.TYPE_BOOKMARK,
url: "place:folder=UNFILED_BOOKMARKS",
title: "shortcut to unfiled, within toolbar"
});
let folder = yield bmu.insert({
parentGuid: bmu.unfiledGuid,
index: bmu.DEFAULT_INDEX,
type: bmu.TYPE_FOLDER,
title: "folder within unfiled"
});
// Setup the places tree contents.
let tree = document.getElementById("tree");
tree.place = "place:folder=TOOLBAR";
// Select the folder via the selectItems(itemId) API being tested
let itemId = yield PlacesUtils.promiseItemId(folder.guid);
tree.selectItems([itemId]);
is(tree.selectedNode && tree.selectedNode.itemId, itemId, "The node was selected through the shortcut");
// Cleanup
yield bmu.eraseEverything();
}).catch(err => {
ok(false, `Uncaught error: ${err}`);
}).then(SimpleTest.finish);
}
]]></script>
</window>

Просмотреть файл

@ -8,8 +8,7 @@
const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
let gluesvc = Cc["@mozilla.org/browser/browserglue;1"].
getService(Ci.nsIBrowserGlue).
QueryInterface(Ci.nsIObserver);
getService(Ci.nsIObserver);
// Avoid default bookmarks import.
gluesvc.observe(null, "initial-migration-will-import-default-bookmarks", "");

Просмотреть файл

@ -20,7 +20,7 @@ add_task(function* () {
do_register_cleanup(() => Services.prefs.clearUserPref("browser.bookmarks.autoExportHTML"));
// Initialize nsBrowserGlue before Places.
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIBrowserGlue);
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsISupports);
// Initialize Places through the History Service.
Cc["@mozilla.org/browser/nav-history-service;1"]

Просмотреть файл

@ -32,7 +32,7 @@ add_task(function* test_main() {
yield createCorruptDB();
// Initialize nsBrowserGlue before Places.
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIBrowserGlue);
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsISupports);
// Check the database was corrupt.
// nsBrowserGlue uses databaseStatus to manage initialization.

Просмотреть файл

@ -26,7 +26,7 @@ add_task(function* () {
yield createCorruptDB();
// Initialize nsBrowserGlue before Places.
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIBrowserGlue);
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsISupports);
// Check the database was corrupt.
// nsBrowserGlue uses databaseStatus to manage initialization.

Просмотреть файл

@ -24,7 +24,7 @@ add_task(function* () {
yield createCorruptDB();
// Initialize nsBrowserGlue before Places.
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIBrowserGlue);
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsISupports);
// Check the database was corrupt.
// nsBrowserGlue uses databaseStatus to manage initialization.

Просмотреть файл

@ -32,7 +32,7 @@ do_register_cleanup(function () {
add_task(function* test_main() {
// Initialize nsBrowserGlue before Places.
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIBrowserGlue);
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsISupports);
// Initialize Places through the History Service.
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].

Просмотреть файл

@ -110,8 +110,7 @@ var gOriginalOverrideURL;
this.__defineGetter__("gBG", function() {
delete this.gBG;
return this.gBG = Cc["@mozilla.org/browser/browserglue;1"].
getService(Ci.nsIBrowserGlue).
QueryInterface(Ci.nsIObserver);
getService(Ci.nsIObserver);
});
function test()

Просмотреть файл

@ -6,7 +6,7 @@
<!ENTITY newtab.pageTitle "New Tab">
<!ENTITY newtab.customize.classic "Show your top sites">
<!ENTITY newtab.customize.cog.enhanced "Include suggested sites">
<!ENTITY newtab.customize.cog.title "New Tab Controls">
<!ENTITY newtab.customize.cog.title2 "NEW TAB CONTROLS">
<!ENTITY newtab.customize.cog.learn "Learn about New Tab">
<!ENTITY newtab.customize.title "Customize your New Tab page">
<!ENTITY newtab.customize.suggested "Show suggested and your top sites">

Просмотреть файл

@ -729,7 +729,7 @@ struct BluetoothGattReadParam {
BluetoothGattServiceId mServiceId;
BluetoothGattId mCharId;
BluetoothGattId mDescriptorId;
uint32_t mValueType;
uint16_t mValueType;
uint16_t mValueLength;
uint8_t mValue[BLUETOOTH_GATT_MAX_ATTR_LEN];
uint8_t mStatus;

Просмотреть файл

@ -969,13 +969,13 @@ BluetoothDaemonGattModule::HandleRsp(
MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
size_t length = MOZ_ARRAY_LENGTH(HandleRsp) +
MOZ_ARRAY_LENGTH(HandleClientRsp);
bool isInGattArray = HandleRsp[aHeader.mOpcode];
bool isInGattClientArray = HandleClientRsp[aHeader.mOpcode];
bool isInGattArray = aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp) &&
HandleRsp[aHeader.mOpcode];
bool isInGattClientArray =
aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleClientRsp) &&
HandleClientRsp[aHeader.mOpcode];
if (NS_WARN_IF(!(aHeader.mOpcode < length)) ||
NS_WARN_IF(!(isInGattArray || isInGattClientArray))) {
if (NS_WARN_IF(!isInGattArray && !isInGattClientArray)) {
return;
}
@ -1065,13 +1065,13 @@ public:
return rv;
}
/* Read Length */
size_t length;
uint16_t length;
rv = UnpackPDU(pdu, length);
if (NS_FAILED(rv)) {
return rv;
}
/* Read Adv Data */
rv = UnpackPDU(pdu, aArg3);
rv = UnpackPDU(pdu, UnpackArray<uint8_t>(aArg3.mAdvData, length));
if (NS_FAILED(rv)) {
return rv;
}

Просмотреть файл

@ -1772,13 +1772,13 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattReadParam& aOut)
if (NS_FAILED(rv)) {
return rv;
}
/* unpack value type */
rv = UnpackPDU(aPDU, aOut.mValueType);
/* unpack status */
rv = UnpackPDU(aPDU, aOut.mStatus);
if (NS_FAILED(rv)) {
return rv;
}
/* unpack status */
rv = UnpackPDU(aPDU, aOut.mStatus);
/* unpack value type */
rv = UnpackPDU(aPDU, aOut.mValueType);
if (NS_FAILED(rv)) {
return rv;
}

Просмотреть файл

@ -939,12 +939,6 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothUuid& aOut)
return aPDU.Read(aOut.mUuid, sizeof(aOut.mUuid));
}
inline nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattAdvData& aOut)
{
return aPDU.Read(aOut.mAdvData, sizeof(aOut.mAdvData));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattId& aOut);

Просмотреть файл

@ -1439,6 +1439,15 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
LoadImage(src, false, aNotify, eImageLoadType_Normal);
}
}
if (mType == NS_FORM_INPUT_PASSWORD && IsInComposedDoc()) {
AsyncEventDispatcher* dispatcher =
new AsyncEventDispatcher(this,
NS_LITERAL_STRING("DOMInputPasswordAdded"),
true,
true);
dispatcher->PostDOMEvent();
}
}
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
@ -4598,11 +4607,20 @@ HTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
// And now make sure our state is up to date
UpdateState(false);
#ifdef EARLY_BETA_OR_EARLIER
if (mType == NS_FORM_INPUT_PASSWORD) {
if (IsInComposedDoc()) {
AsyncEventDispatcher* dispatcher =
new AsyncEventDispatcher(this,
NS_LITERAL_STRING("DOMInputPasswordAdded"),
true,
true);
dispatcher->PostDOMEvent();
}
#ifdef EARLY_BETA_OR_EARLIER
Telemetry::Accumulate(Telemetry::PWMGR_PASSWORD_INPUT_IN_FORM, !!mForm);
}
#endif
}
return rv;
}

Просмотреть файл

@ -368,7 +368,7 @@ nsVolumeService::FindVolumeByMountLockName(const nsAString& aMountLockName)
}
already_AddRefed<nsVolume>
nsVolumeService::FindVolumeByName(const nsAString& aName, nsVolume::Array::index_type* aIndex)
nsVolumeService::FindVolumeByName(const nsAString& aName)
{
mArrayMonitor.AssertCurrentThreadOwns();
@ -377,34 +377,52 @@ nsVolumeService::FindVolumeByName(const nsAString& aName, nsVolume::Array::index
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
if (vol->Name().Equals(aName)) {
if (aIndex) {
*aIndex = volIndex;
}
return vol.forget();
}
}
return nullptr;
}
//static
already_AddRefed<nsVolume>
nsVolumeService::CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake /*= false*/)
{
MonitorAutoLock autoLock(mArrayMonitor);
nsRefPtr<nsVolume> vol;
vol = FindVolumeByName(aName);
if (vol) {
return vol.forget();
}
// Volume not found - add a new one
vol = new nsVolume(aName);
vol->SetIsFake(aIsFake);
mVolumeArray.AppendElement(vol);
return vol.forget();
}
void
nsVolumeService::UpdateVolume(nsVolume* aVolume, bool aNotifyObservers)
nsVolumeService::UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers)
{
MOZ_ASSERT(NS_IsMainThread());
{
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::index_type volIndex;
nsRefPtr<nsVolume> vol = FindVolumeByName(aVolume->Name(), &volIndex);
if (!vol) {
mVolumeArray.AppendElement(aVolume);
} else if (vol->Equals(aVolume) || (!vol->IsFake() && aVolume->IsFake())) {
// Ignore if nothing changed or if a fake tries to override a real volume.
return;
} else {
mVolumeArray.ReplaceElementAt(volIndex, aVolume);
}
nsString volName;
aVolume->GetName(volName);
bool aIsFake;
aVolume->GetIsFake(&aIsFake);
nsRefPtr<nsVolume> vol = CreateOrFindVolumeByName(volName, aIsFake);
if (vol->Equals(aVolume)) {
// Nothing has really changed. Don't bother telling anybody.
return;
}
if (!vol->IsFake() && aIsFake) {
// Prevent an incoming fake volume from overriding an existing real volume.
return;
}
vol->Set(aVolume);
if (!aNotifyObservers) {
return;
}
@ -413,8 +431,8 @@ nsVolumeService::UpdateVolume(nsVolume* aVolume, bool aNotifyObservers)
if (!obs) {
return;
}
NS_ConvertUTF8toUTF16 stateStr(aVolume->StateStr());
obs->NotifyObservers(aVolume, NS_VOLUME_STATE_CHANGED, stateStr.get());
NS_ConvertUTF8toUTF16 stateStr(vol->StateStr());
obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get());
}
NS_IMETHODIMP
@ -453,7 +471,9 @@ nsVolumeService::SetFakeVolumeState(const nsAString& name, int32_t state)
return NS_ERROR_NOT_AVAILABLE;
}
// Clone the existing volume so we can replace it
// UpdateVolume expects the volume passed in to NOT be the
// same pointer as what CreateOrFindVolumeByName would return,
// which is why we allocate a temporary volume here.
nsRefPtr<nsVolume> volume = new nsVolume(name);
volume->Set(vol);
volume->SetState(state);
@ -482,15 +502,15 @@ nsVolumeService::RemoveFakeVolume(const nsAString& name)
void
nsVolumeService::RemoveVolumeByName(const nsAString& aName)
{
nsRefPtr<nsVolume> vol;
{
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::index_type volIndex;
nsRefPtr<nsVolume> vol = FindVolumeByName(aName, &volIndex);
if (!vol) {
return;
}
mVolumeArray.RemoveElementAt(volIndex);
vol = FindVolumeByName(aName);
}
if (!vol) {
return;
}
mVolumeArray.RemoveElement(vol);
if (XRE_GetProcessType() == GeckoProcessType_Default) {
nsCOMPtr<nsIObserverService> obs = GetObserverService();

Просмотреть файл

@ -47,7 +47,7 @@ public:
void DumpNoLock(const char* aLabel);
// To use this function, you have to create a new volume and pass it in.
void UpdateVolume(nsVolume* aVolume, bool aNotifyObservers = true);
void UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers = true);
void UpdateVolumeIOThread(const Volume* aVolume);
void RecvVolumesFromParent(const nsTArray<dom::VolumeInfo>& aVolumes);
@ -61,9 +61,8 @@ private:
void CheckMountLock(const nsAString& aMountLockName,
const nsAString& aMountLockState);
already_AddRefed<nsVolume> FindVolumeByMountLockName(const nsAString& aMountLockName);
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName,
nsVolume::Array::index_type* aIndex = nullptr);
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName);
already_AddRefed<nsVolume> CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake = false);
Monitor mArrayMonitor;
nsVolume::Array mVolumeArray;

Просмотреть файл

@ -273,8 +273,10 @@ RilConsumer::Send(UnixSocketRawData* aRawData)
void
RilConsumer::Close()
{
mSocket->Close();
mSocket = nullptr;
if (mSocket) {
mSocket->Close();
mSocket = nullptr;
}
}
// |StreamSocketConnector|

Просмотреть файл

@ -712,7 +712,7 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
if(stm->lastPosition == msec || msec < stm->lastCompensativePosition) {
if(stm->lastPosition == msec) {
compensation_msec =
(t.tv_sec*1000000000LL + t.tv_nsec - stm->lastPositionTimeStamp) / 1000000;
} else {
@ -733,14 +733,21 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
assert(maximum_position >= 0);
if (msec > mixer_latency) {
int64_t unadjusted_position =
samplerate * (msec - mixer_latency + compensation_msec) / 1000;
int64_t unadjusted_position;
if (stm->lastCompensativePosition > msec + compensation_msec) {
// Over compensation, use lastCompensativePosition.
unadjusted_position =
samplerate * (stm->lastCompensativePosition - mixer_latency) / 1000;
} else {
unadjusted_position =
samplerate * (msec - mixer_latency + compensation_msec) / 1000;
stm->lastCompensativePosition = msec + compensation_msec;
}
*position = unadjusted_position < maximum_position ?
unadjusted_position : maximum_position;
} else {
*position = 0;
}
stm->lastCompensativePosition = *position;
return CUBEB_OK;
}

Просмотреть файл

@ -73,3 +73,36 @@ android.applicationVariants.all { variant ->
def generateAssetsTask = tasks.findByName("generate${name.capitalize()}Assets")
generateAssetsTask.dependsOn buildOmnijarTask
}
apply plugin: 'spoon'
spoon {
// For now, let's be verbose.
debug = true
// It's not helpful to pass when we don't have a device connected.
failIfNoDeviceConnected = true
def spoonPackageName
if (gradle.startParameter.taskNames.contains('runBrowserTests')) {
spoonPackageName = 'org.mozilla.tests.browser.junit3'
}
if (project.hasProperty('spoonPackageName')) {
// Command line overrides everything.
spoonPackageName = project.spoonPackageName
}
if (spoonPackageName) {
instrumentationArgs = ['-e', "package=${spoonPackageName}".toString()]
}
}
// See discussion at https://github.com/stanfy/spoon-gradle-plugin/issues/9.
afterEvaluate {
tasks["spoon${android.testBuildType.capitalize()}AndroidTest"].outputs.upToDateWhen { false }
// This is an awkward way to define different sets of instrumentation tests.
// The task name itself is fished at runtime and the package name configured
// in the spoon configuration.
task runBrowserTests {
dependsOn tasks["spoonDebugAndroidTest"]
}
}

Просмотреть файл

@ -16,6 +16,17 @@ buildDir "${topobjdir}/mobile/android/gradle/build"
buildscript {
repositories {
jcenter()
// For spoon-gradle-plugin SNAPSHOT release. This needs to go before
// the snapshots repository, otherwise we find a remote 1.0.3-SNAPSHOT
// that doesn't include nalexander's local changes.
maven {
url "file://${topsrcdir}/mobile/android/gradle/m2repo"
}
// For spoon SNAPSHOT releases.
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots'
}
}
dependencies {
@ -23,6 +34,10 @@ buildscript {
// 1.0.0. There are major issues with the combination of 0.14.4, Gradle
// 2.2.1, and IntelliJ 14.0.2: see Bug 1120032.
classpath 'com.android.tools.build:gradle:1.0.0'
classpath('com.stanfy.spoon:spoon-gradle-plugin:1.0.3-SNAPSHOT') {
// Without these, we get errors linting.
exclude module: 'guava'
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.stanfy.spoon</groupId>
<artifactId>spoon-gradle-plugin</artifactId>
<version>1.0.3-SNAPSHOT</version>
<versioning>
<snapshot>
<localCopy>true</localCopy>
</snapshot>
<lastUpdated>20150603215211</lastUpdated>
</versioning>
</metadata>

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.stanfy.spoon</groupId>
<artifactId>spoon-gradle-plugin</artifactId>
<version>1.0.3-SNAPSHOT</version>
<name>Spoon Gradle Plugin</name>
<description>Gradle plugin for Spoon</description>
<url>https://github.com/stanfy/spoon-gradle-plugin</url>
<inceptionYear>2013</inceptionYear>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>rmazur</id>
<name>Roman Mazur</name>
<email>rmazur@stanfy.com.ua</email>
</developer>
</developers>
<scm>
<connection>scm:git:git@github.com:stanfy/spoon-gradle-plugin.git</connection>
<developerConnection>scm:git:git@github.com:stanfy/spoon-gradle-plugin.git</developerConnection>
<url>https://github.com/stanfy/spoon-gradle-plugin</url>
</scm>
<dependencies>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>0.7-groovy-2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.spoon</groupId>
<artifactId>spoon-runner</artifactId>
<version>1.1.10-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.android.tools.build</groupId>
<artifactId>gradle</artifactId>
<version>1.1.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.stanfy.spoon</groupId>
<artifactId>spoon-gradle-plugin</artifactId>
<version>1.0.3-SNAPSHOT</version>
<versioning>
<versions>
<version>1.0.3-SNAPSHOT</version>
</versions>
<lastUpdated>20150603215211</lastUpdated>
</versioning>
</metadata>

Просмотреть файл

@ -125,7 +125,7 @@ class MachCommands(MachCommandBase):
srcdir('app/src/robocop_harness/org/mozilla/gecko', 'build/mobile/robocop')
srcdir('app/src/robocop/org/mozilla/gecko/tests', 'mobile/android/tests/browser/robocop')
srcdir('app/src/background/org/mozilla/gecko', 'mobile/android/tests/background/junit3/src')
srcdir('app/src/browser/org/mozilla/gecko', 'mobile/android/tests/browser/junit3/src')
srcdir('app/src/browser', 'mobile/android/tests/browser/junit3/src')
# Test libraries.
srcdir('app/libs', 'build/mobile/robocop')

Просмотреть файл

@ -1,10 +1,10 @@
[DEFAULT]
subsuite = browser
[src/TestDistribution.java]
[src/TestGeckoSharedPrefs.java]
[src/TestImageDownloader.java]
[src/TestJarReader.java]
[src/TestRawResource.java]
[src/TestSuggestedSites.java]
[src/TestTopSitesCursorWrapper.java]
[src/org/mozilla/tests/browser/junit3/TestDistribution.java]
[src/org/mozilla/tests/browser/junit3/TestGeckoSharedPrefs.java]
[src/org/mozilla/tests/browser/junit3/TestImageDownloader.java]
[src/org/mozilla/tests/browser/junit3/TestJarReader.java]
[src/org/mozilla/tests/browser/junit3/TestRawResource.java]
[src/org/mozilla/tests/browser/junit3/TestSuggestedSites.java]
[src/org/mozilla/tests/browser/junit3/TestTopSitesCursorWrapper.java]

Просмотреть файл

@ -8,37 +8,20 @@ DEFINES['ANDROID_PACKAGE_NAME'] = CONFIG['ANDROID_PACKAGE_NAME']
jar = add_java_jar('browser-junit3')
jar.sources += [
'src/BrowserTestCase.java',
'src/harness/BrowserInstrumentationTestRunner.java',
'src/harness/BrowserTestListener.java',
'src/TestDistribution.java',
'src/TestGeckoBackgroundThread.java',
'src/TestGeckoMenu.java',
'src/TestGeckoProfilesProvider.java',
'src/TestGeckoSharedPrefs.java',
'src/TestImageDownloader.java',
'src/TestJarReader.java',
'src/TestRawResource.java',
'src/TestSuggestedSites.java',
'src/TestTopSitesCursorWrapper.java',
'src/org/mozilla/tests/browser/junit3/harness/BrowserInstrumentationTestRunner.java',
'src/org/mozilla/tests/browser/junit3/harness/BrowserTestListener.java',
'src/org/mozilla/tests/browser/junit3/TestDistribution.java',
'src/org/mozilla/tests/browser/junit3/TestGeckoBackgroundThread.java',
'src/org/mozilla/tests/browser/junit3/TestGeckoMenu.java',
'src/org/mozilla/tests/browser/junit3/TestGeckoProfilesProvider.java',
'src/org/mozilla/tests/browser/junit3/TestGeckoSharedPrefs.java',
'src/org/mozilla/tests/browser/junit3/TestImageDownloader.java',
'src/org/mozilla/tests/browser/junit3/TestJarReader.java',
'src/org/mozilla/tests/browser/junit3/TestRawResource.java',
'src/org/mozilla/tests/browser/junit3/TestSuggestedSites.java',
'src/org/mozilla/tests/browser/junit3/TestTopSitesCursorWrapper.java',
]
jar.generated_sources = [] # None yet -- try to keep it this way.
jar.javac_flags += ['-Xlint:all,-unchecked']
# Android Eclipse project.
main = add_android_eclipse_project('BrowserInstrumentationTests', OBJDIR + '/AndroidManifest.xml')
# The package name doesn't really matter, but it looks nicest if the
# generated classes (org.mozilla.gecko.browser.tests.{BuildConfig,R})
# are in the same hierarchy as the rest of the source files.
main.package_name = 'org.mozilla.gecko.browser.tests'
main.res = 'res'
main.recursive_make_targets += [
OBJDIR + '/AndroidManifest.xml',
]
main.recursive_make_targets += [OBJDIR + '/generated/' + f for f in jar.generated_sources]
main.referenced_projects += ['Fennec']
main.add_classpathentry('src', SRCDIR + '/src',
dstdir='src/org/mozilla/gecko')
jar.javac_flags += ['-Xlint:all']
ANDROID_INSTRUMENTATION_MANIFESTS += ['instrumentation.ini']

Просмотреть файл

@ -1,48 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko;
import org.mozilla.gecko.AppConstants;
import android.app.Activity;
import android.content.Context;
import android.test.ActivityInstrumentationTestCase2;
/**
* BrowserTestCase provides helper methods for testing.
*/
@SuppressWarnings("unchecked")
public class BrowserTestCase extends ActivityInstrumentationTestCase2<Activity> {
@SuppressWarnings("unused")
private static String LOG_TAG = "BrowserTestCase";
/**
* The Java Class instance that launches the browser.
* <p>
* This should always agree with {@link AppConstants#MOZ_ANDROID_BROWSER_INTENT_CLASS}.
*/
public static final Class<? extends Activity> BROWSER_INTENT_CLASS;
// Use reflection here so we don't have to either (a) preprocess this
// file, or (b) get access to Robocop's TestConstants class from these
// instrumentation tests.
static {
Class<? extends Activity> cl;
try {
cl = (Class<? extends Activity>) Class.forName(AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
} catch (ClassNotFoundException e) {
// Oh well.
cl = Activity.class;
}
BROWSER_INTENT_CLASS = cl;
}
public BrowserTestCase() {
super((Class<Activity>) BROWSER_INTENT_CLASS);
}
public Context getApplicationContext() {
return this.getInstrumentation().getTargetContext().getApplicationContext();
}
}

Просмотреть файл

@ -2,11 +2,12 @@
* 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;
package org.mozilla.tests.browser.junit3;
import android.test.InstrumentationTestCase;
import org.mozilla.gecko.distribution.ReferrerDescriptor;
public class TestDistribution extends BrowserTestCase {
public class TestDistribution extends InstrumentationTestCase {
private static final String TEST_REFERRER_STRING = "utm_source=campsource&utm_medium=campmed&utm_term=term%2Bhere&utm_content=content&utm_campaign=name";
private static final String TEST_MALFORMED_REFERRER_STRING = "utm_source=campsource&utm_medium=campmed&utm_term=term%2";

Просмотреть файл

@ -2,11 +2,12 @@
* 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;
package org.mozilla.tests.browser.junit3;
import android.test.InstrumentationTestCase;
import org.mozilla.gecko.util.ThreadUtils;
public class TestGeckoBackgroundThread extends BrowserTestCase {
public class TestGeckoBackgroundThread extends InstrumentationTestCase {
private boolean finishedTest;
private boolean ranFirstRunnable;

Просмотреть файл

@ -2,13 +2,14 @@
* 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;
package org.mozilla.tests.browser.junit3;
import android.test.InstrumentationTestCase;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.menu.GeckoMenu;
import org.mozilla.gecko.util.ThreadUtils;
public class TestGeckoMenu extends BrowserTestCase {
public class TestGeckoMenu extends InstrumentationTestCase {
private volatile Exception exception;
private void setException(Exception e) {
@ -16,7 +17,7 @@ public class TestGeckoMenu extends BrowserTestCase {
}
public void testMenuThreading() throws InterruptedException {
final GeckoMenu menu = new GeckoMenu(getActivity());
final GeckoMenu menu = new GeckoMenu(getInstrumentation().getTargetContext());
final Object semaphore = new Object();
ThreadUtils.postToUiThread(new Runnable() {

Просмотреть файл

@ -2,27 +2,27 @@
* 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.io.File;
import java.util.HashMap;
import java.util.Map;
import org.mozilla.gecko.db.BrowserContract;
package org.mozilla.tests.browser.junit3;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.test.InstrumentationTestCase;
import org.mozilla.gecko.db.BrowserContract;
public class TestGeckoProfilesProvider extends BrowserTestCase {
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class TestGeckoProfilesProvider extends InstrumentationTestCase {
private static final String[] NAME_AND_PATH = new String[] { BrowserContract.Profiles.NAME, BrowserContract.Profiles.PATH };
/**
* Ensure that the default profile is found in the results from the provider.
*/
public void testQueryDefault() throws RemoteException {
final ContentResolver contentResolver = getActivity().getContentResolver();
final ContentResolver contentResolver = getInstrumentation().getContext().getContentResolver();
final Uri uri = BrowserContract.PROFILES_AUTHORITY_URI.buildUpon().appendPath("profiles").build();
final Cursor c = contentResolver.query(uri, NAME_AND_PATH, null, null, null);
assertNotNull(c);

Просмотреть файл

@ -1,7 +1,17 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko;
package org.mozilla.tests.browser.junit3;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import android.test.InstrumentationTestCase;
import android.test.RenamingDelegatingContext;
import org.mozilla.gecko.GeckoProfile;
import org.mozilla.gecko.GeckoSharedPrefs;
import org.mozilla.gecko.GeckoSharedPrefs.Flags;
import java.util.Arrays;
import java.util.Collections;
@ -9,18 +19,10 @@ import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import org.mozilla.gecko.GeckoSharedPrefs.Flags;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import android.test.RenamingDelegatingContext;
/**
* Test GeckoSharedPrefs migrations.
*/
public class TestGeckoSharedPrefs extends BrowserTestCase {
public class TestGeckoSharedPrefs extends InstrumentationTestCase {
private static class TestContext extends RenamingDelegatingContext {
private static final String PREFIX = "TestGeckoSharedPrefs-";
@ -52,7 +54,7 @@ public class TestGeckoSharedPrefs extends BrowserTestCase {
private TestContext context;
protected void setUp() {
context = new TestContext(getApplicationContext());
context = new TestContext(getInstrumentation().getTargetContext());
}
protected void tearDown() {

Просмотреть файл

@ -1,15 +1,18 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko;
package org.mozilla.tests.browser.junit3;
import android.content.Context;
import android.content.res.Resources;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.net.Uri;
import android.test.mock.MockResources;
import android.test.InstrumentationTestCase;
import android.test.RenamingDelegatingContext;
import android.test.mock.MockResources;
import android.util.DisplayMetrics;
import org.mozilla.gecko.distribution.Distribution;
import org.mozilla.gecko.home.ImageLoader.ImageDownloader;
import java.io.File;
import java.io.IOException;
@ -19,10 +22,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.mozilla.gecko.distribution.Distribution;
import org.mozilla.gecko.home.ImageLoader.ImageDownloader;
public class TestImageDownloader extends BrowserTestCase {
public class TestImageDownloader extends InstrumentationTestCase {
private static class TestContext extends RenamingDelegatingContext {
private static final String PREFIX = "TestImageDownloader-";
@ -104,7 +104,7 @@ public class TestImageDownloader extends BrowserTestCase {
private ImageDownloader downloader;
protected void setUp() {
context = new TestContext(getApplicationContext());
context = new TestContext(getInstrumentation().getTargetContext());
resources = (TestResources) context.getResources();
distribution = new TestDistribution(context);
downloader = new ImageDownloader(context, distribution);

Просмотреть файл

@ -1,10 +1,11 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko;
package org.mozilla.tests.browser.junit3;
import java.io.InputStream;
import android.test.InstrumentationTestCase;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.util.GeckoJarReader;
@ -12,9 +13,9 @@ import org.mozilla.gecko.util.GeckoJarReader;
* A basic jar reader test. Tests reading a png from fennec's apk, as well as
* loading some invalid jar urls.
*/
public class TestJarReader extends BrowserTestCase {
public class TestJarReader extends InstrumentationTestCase {
public void testJarReader() {
String appPath = getActivity().getApplication().getPackageResourcePath();
String appPath = getInstrumentation().getTargetContext().getPackageResourcePath();
assertNotNull(appPath);
// Test reading a file from a jar url that looks correct.

Просмотреть файл

@ -1,24 +1,24 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko;
package org.mozilla.tests.browser.junit3;
import android.content.Context;
import android.content.res.Resources;
import android.test.InstrumentationTestCase;
import android.test.mock.MockContext;
import android.test.mock.MockResources;
import org.mozilla.gecko.util.RawResource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.mozilla.gecko.util.RawResource;
import android.content.Context;
import android.content.res.Resources;
import android.test.mock.MockContext;
import android.test.mock.MockResources;
/**
* Tests whether RawResource.getAsString() produces the right String
* result after reading the returned raw resource's InputStream.
*/
public class TestRawResource extends BrowserTestCase {
public class TestRawResource extends InstrumentationTestCase {
private static final int RAW_RESOURCE_ID = 1;
private static final String RAW_CONTENTS = "RAW";

Просмотреть файл

@ -1,7 +1,28 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko;
package org.mozilla.tests.browser.junit3;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.SystemClock;
import android.test.InstrumentationTestCase;
import android.test.RenamingDelegatingContext;
import android.test.mock.MockResources;
import org.json.JSONArray;
import org.json.JSONObject;
import org.mozilla.gecko.R;
import org.mozilla.gecko.GeckoSharedPrefs;
import org.mozilla.gecko.Locales;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.SuggestedSites;
import org.mozilla.gecko.distribution.Distribution;
import org.mozilla.gecko.preferences.GeckoPreferences;
import java.io.ByteArrayInputStream;
import java.io.File;
@ -16,26 +37,10 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.json.JSONArray;
import org.json.JSONObject;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.SuggestedSites;
import org.mozilla.gecko.distribution.Distribution;
import org.mozilla.gecko.preferences.GeckoPreferences;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.SystemClock;
import android.test.RenamingDelegatingContext;
import android.test.mock.MockResources;
public class TestSuggestedSites extends BrowserTestCase {
public class TestSuggestedSites extends InstrumentationTestCase {
private static class TestContext extends RenamingDelegatingContext {
private static final String PREFIX = "TestSuggestedSites-";
@ -119,18 +124,16 @@ public class TestSuggestedSites extends BrowserTestCase {
}
class TestObserver extends ContentObserver {
private final Object changeLock;
private final CountDownLatch changeLatch;
public TestObserver(Object changeLock) {
public TestObserver(CountDownLatch changeLatch) {
super(null);
this.changeLock = changeLock;
this.changeLatch = changeLatch;
}
@Override
public void onChange(boolean selfChange) {
synchronized(changeLock) {
changeLock.notifyAll();
}
changeLatch.countDown();
}
}
@ -211,7 +214,7 @@ public class TestSuggestedSites extends BrowserTestCase {
}
protected void setUp() {
context = new TestContext(getApplicationContext());
context = new TestContext(getInstrumentation().getTargetContext());
resources = (TestResources) context.getResources();
tempFiles = new ArrayList<File>();
}
@ -449,6 +452,14 @@ public class TestSuggestedSites extends BrowserTestCase {
tempFiles.add(distFile);
assertTrue(distFile.exists());
final CountDownLatch changeLatch = new CountDownLatch(1);
// Watch for change notifications on suggested sites.
ContentResolver cr = context.getContentResolver();
ContentObserver observer = new TestObserver(changeLatch);
cr.registerContentObserver(BrowserContract.SuggestedSites.CONTENT_URI,
false, observer);
// Init distribution with the mock file.
TestDistribution distribution = new TestDistribution(context);
distribution.setFileForLocale(Locale.getDefault(), distFile);
@ -459,14 +470,6 @@ public class TestSuggestedSites extends BrowserTestCase {
SuggestedSites suggestedSites =
new SuggestedSites(context, distribution, sitesFile);
Object changeLock = new Object();
// Watch for change notifications on suggested sites.
ContentResolver cr = context.getContentResolver();
ContentObserver observer = new TestObserver(changeLock);
cr.registerContentObserver(BrowserContract.SuggestedSites.CONTENT_URI,
false, observer);
// The initial query will not contain the distribution sites
// yet. This will happen asynchronously once the distribution
// is installed.
@ -480,12 +483,10 @@ public class TestSuggestedSites extends BrowserTestCase {
}
}
synchronized(changeLock) {
try {
changeLock.wait(5000);
} catch (InterruptedException ie) {
fail("No change notification after fetching distribution file");
}
try {
assertTrue(changeLatch.await(5, TimeUnit.SECONDS));
} catch (InterruptedException ie) {
fail("No change notification after fetching distribution file");
}
// Target file should exist after distribution is deployed.

Просмотреть файл

@ -1,23 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko;
package org.mozilla.tests.browser.junit3;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
import android.test.InstrumentationTestCase;
import android.text.TextUtils;
import java.util.Arrays;
import java.util.List;
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
import org.mozilla.gecko.db.BrowserContract.Combined;
import org.mozilla.gecko.db.BrowserContract.SuggestedSites;
import org.mozilla.gecko.db.BrowserContract.TopSites;
import org.mozilla.gecko.db.TopSitesCursorWrapper;
public class TestTopSitesCursorWrapper extends BrowserTestCase {
import java.util.Arrays;
import java.util.List;
public class TestTopSitesCursorWrapper extends InstrumentationTestCase {
private String[] TOP_SITES_COLUMNS = new String[] { Combined._ID,
Combined.URL,

Просмотреть файл

@ -1,7 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko.harness;
package org.mozilla.tests.browser.junit3.harness;
import android.os.Bundle;
import android.test.AndroidTestRunner;

Просмотреть файл

@ -1,12 +1,12 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.gecko.harness;
package org.mozilla.tests.browser.junit3.harness;
import android.util.Log;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestListener;
import android.util.Log;
/**
* BrowserTestListener turns JUnit 3 test events into log messages in the format

Просмотреть файл

@ -3,6 +3,8 @@ support-files =
authenticate.sjs
form_basic.html
[browser_DOMFormHasPassword.js]
[browser_DOMInputPasswordAdded.js]
[browser_filldoorhanger.js]
[browser_notifications.js]
[browser_passwordmgr_fields.js]

Просмотреть файл

@ -0,0 +1,87 @@
const HTML_NS = "http://www.w3.org/1999/xhtml";
const INPUT_ID = "input1";
const FORM1_ID = "form1";
const FORM2_ID = "form2";
const CHANGE_INPUT_ID = "input2";
const BODY_INPUT_ID = "input3";
function test() {
waitForExplicitFinish();
let tab = gBrowser.selectedTab =
gBrowser.addTab("data:text/html;charset=utf-8," +
"<html><body>" +
"<form id='" + FORM1_ID + "'><input id='" + CHANGE_INPUT_ID + "'></form>" +
"<form id='" + FORM2_ID + "'></form>" +
"</body></html>");
tab.linkedBrowser.addEventListener("load", tabLoad, true);
}
function unexpectedContentEvent(evt) {
ok(false, "Received a " + evt.type + " event on content");
}
var gDoc = null;
function tabLoad() {
let tab = gBrowser.selectedTab;
tab.linkedBrowser.removeEventListener("load", tabLoad, true);
gDoc = gBrowser.selectedBrowser.contentDocument;
// These events shouldn't escape to content.
gDoc.addEventListener("DOMInputPasswordAdded", unexpectedContentEvent, false);
gDoc.defaultView.setTimeout(test_inputAdd, 0);
}
function test_inputAdd() {
gBrowser.addEventListener("DOMInputPasswordAdded", test_inputAddHandler, false);
let input = gDoc.createElementNS(HTML_NS, "input");
input.setAttribute("type", "password");
input.setAttribute("id", INPUT_ID);
input.setAttribute("data-test", "unique-attribute");
gDoc.getElementById(FORM1_ID).appendChild(input);
info("Done appending the input element");
}
function test_inputAddHandler(evt) {
gBrowser.removeEventListener(evt.type, test_inputAddHandler, false);
is(evt.target.id, INPUT_ID,
evt.type + " event targets correct input element (added password element)");
gDoc.defaultView.setTimeout(test_inputAddOutsideForm, 0);
}
function test_inputAddOutsideForm() {
gBrowser.addEventListener("DOMInputPasswordAdded", test_inputAddOutsideFormHandler, false);
let input = gDoc.createElementNS(HTML_NS, "input");
input.setAttribute("type", "password");
input.setAttribute("id", BODY_INPUT_ID);
input.setAttribute("data-test", "unique-attribute");
gDoc.body.appendChild(input);
info("Done appending the input element to the body");
}
function test_inputAddOutsideFormHandler(evt) {
gBrowser.removeEventListener(evt.type, test_inputAddOutsideFormHandler, false);
is(evt.target.id, BODY_INPUT_ID,
evt.type + " event targets correct input element (added password element outside form)");
gDoc.defaultView.setTimeout(test_inputChangesType, 0);
}
function test_inputChangesType() {
gBrowser.addEventListener("DOMInputPasswordAdded", test_inputChangesTypeHandler, false);
let input = gDoc.getElementById(CHANGE_INPUT_ID);
input.setAttribute("type", "password");
}
function test_inputChangesTypeHandler(evt) {
gBrowser.removeEventListener(evt.type, test_inputChangesTypeHandler, false);
is(evt.target.id, CHANGE_INPUT_ID,
evt.type + " event targets correct input element (changed type)");
gDoc.defaultView.setTimeout(completeTest, 0);
}
function completeTest() {
ok(true, "Test completed");
gDoc.removeEventListener("DOMInputPasswordAdded", unexpectedContentEvent, false);
gBrowser.removeCurrentTab();
finish();
}

Просмотреть файл

@ -3610,12 +3610,14 @@ nsNavHistoryFolderResultNode::OnItemRemoved(int64_t aItemId,
const nsACString& aGUID,
const nsACString& aParentGUID)
{
// If this folder is a folder shortcut, we should never be notified for the
// removal of the shortcut (the parent node would be).
MOZ_ASSERT(mItemId == mTargetFolderItemId || aItemId != mItemId);
// Folder shortcuts should not be notified removal of the target folder.
MOZ_ASSERT_IF(mItemId != mTargetFolderItemId, aItemId != mTargetFolderItemId);
// Concrete folders should not be notified their own removal.
// Note aItemId may equal mItemId for recursive folder shortcuts.
MOZ_ASSERT_IF(mItemId == mTargetFolderItemId, aItemId != mItemId);
// In any case though, here we only care about the children removal.
if (mTargetFolderItemId == aItemId)
if (mTargetFolderItemId == aItemId || mItemId == aItemId)
return NS_OK;
MOZ_ASSERT(aParentFolder == mTargetFolderItemId, "Got wrong bookmark update");

Просмотреть файл

@ -409,17 +409,24 @@ loadListener.prototype = {
// Method to determine if we should be using geo-specific defaults
function geoSpecificDefaultsEnabled() {
// check to see if this is a partner build. Partner builds should not use geo-specific defaults.
let distroID;
try {
distroID = Services.prefs.getCharPref("distribution.id");
// Mozilla-provided builds (i.e. funnelcake) are not partner builds
if (distroID && !distroID.startsWith("mozilla")) {
return false;
}
} catch (e) {}
// if we make it here, the pref should dictate behaviour
let geoSpecificDefaults = false;
try {
geoSpecificDefaults = Services.prefs.getBoolPref("browser.search.geoSpecificDefaults");
} catch(e) {}
let distroID;
try {
distroID = Services.prefs.getCharPref("distribution.id");
} catch (e) {}
return (geoSpecificDefaults && !distroID);
return geoSpecificDefaults;
}
// Some notes on countryCode and region prefs:

Просмотреть файл

@ -336,6 +336,53 @@ function installTestEngine() {
});
}
/**
* Wrapper for nsIPrefBranch::setComplexValue.
* @param aPrefName
* The name of the pref to set.
*/
function setLocalizedPref(aPrefName, aValue) {
const nsIPLS = Ci.nsIPrefLocalizedString;
try {
var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
.createInstance(Ci.nsIPrefLocalizedString);
pls.data = aValue;
Services.prefs.setComplexValue(aPrefName, nsIPLS, pls);
} catch (ex) {}
}
/**
* Installs two test engines, sets them as default for US vs. general.
*/
function setUpGeoDefaults() {
removeMetadata();
removeCacheFile();
do_check_false(Services.search.isInitialized);
let engineDummyFile = gProfD.clone();
engineDummyFile.append("searchplugins");
engineDummyFile.append("test-search-engine.xml");
let engineDir = engineDummyFile.parent;
engineDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
do_get_file("data/engine.xml").copyTo(engineDir, "engine.xml");
engineDummyFile = gProfD.clone();
engineDummyFile.append("searchplugins");
engineDummyFile.append("test-search-engine2.xml");
do_get_file("data/engine2.xml").copyTo(engineDir, "engine2.xml");
setLocalizedPref("browser.search.defaultenginename", "Test search engine");
setLocalizedPref("browser.search.defaultenginename.US", "A second test engine");
do_register_cleanup(function() {
removeMetadata();
removeCacheFile();
});
}
/**
* Returns a promise that is resolved when an observer notification from the

Просмотреть файл

@ -0,0 +1,17 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function run_test() {
Services.prefs.setCharPref("browser.search.geoip.url", 'data:application/json,{"country_code": "US"}');
// funnelcake builds start with "mozilla"
Services.prefs.setCharPref("distribution.id", 'mozilla38');
setUpGeoDefaults();
Services.search.init(() => {
equal(Services.search.defaultEngine.name, "A second test engine");
do_test_finished();
run_next_test();
});
do_test_pending();
}

Просмотреть файл

@ -0,0 +1,16 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function run_test() {
Services.prefs.setCharPref("browser.search.geoip.url", 'data:application/json,{"country_code": "US"}');
Services.prefs.setCharPref("distribution.id", 'partner-1');
setUpGeoDefaults();
Services.search.init(() => {
equal(Services.search.defaultEngine.name, "Test search engine");
do_test_finished();
run_next_test();
});
do_test_pending();
}

Просмотреть файл

@ -38,6 +38,8 @@ support-files =
[test_location_migrate_countrycode_isUS.js]
[test_location_migrate_no_countrycode_isUS.js]
[test_location_migrate_no_countrycode_notUS.js]
[test_location_partner.js]
[test_location_funnelcake.js]
[test_location_sync.js]
[test_location_timeout.js]
[test_location_timeout_xhr.js]

Просмотреть файл

@ -1,23 +1,29 @@
/* 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/. */
/* globals nodesSelected, PluralForm */
"use strict";
const {Cc, Ci, Cu} = require("chrome");
const l10n = require("gcli/l10n");
require("devtools/server/actors/inspector");
const {BoxModelHighlighter} = require("devtools/server/actors/highlighter");
const {
BoxModelHighlighter,
HighlighterEnvironment
} = require("devtools/server/actors/highlighter");
XPCOMUtils.defineLazyGetter(this, "nodesSelected", function() {
return Services.strings.createBundle("chrome://global/locale/devtools/gclicommands.properties");
});
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm","resource://gre/modules/PluralForm.jsm");
const events = require("sdk/event/core");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
// How many maximum nodes can be highlighted in parallel
const MAX_HIGHLIGHTED_ELEMENTS = 100;
// Store the environment object used to create highlighters so it can be
// destroyed later.
let highlighterEnv;
// Stores the highlighters instances so they can be destroyed later.
// also export them so tests can access those and assert they got created
// correctly.
@ -31,6 +37,11 @@ function unhighlightAll() {
highlighter.destroy();
}
exports.highlighters.length = 0;
if (highlighterEnv) {
highlighterEnv.destroy();
highlighterEnv = null;
}
}
exports.items = [
@ -89,7 +100,7 @@ exports.items = [
name: "keep",
type: "boolean",
description: l10n.lookup("highlightKeepDesc"),
manual: l10n.lookup("highlightKeepManual"),
manual: l10n.lookup("highlightKeepManual")
}
]
}
@ -101,9 +112,11 @@ exports.items = [
}
let env = context.environment;
highlighterEnv = new HighlighterEnvironment();
highlighterEnv.initFromWindow(env.window);
// Unhighlight on navigate
events.on(env.__deprecatedTabActor, "will-navigate", unhighlightAll);
highlighterEnv.once("will-navigate", unhighlightAll);
let i = 0;
for (let node of args.selector) {
@ -111,7 +124,7 @@ exports.items = [
break;
}
let highlighter = new BoxModelHighlighter(env.__deprecatedTabActor);
let highlighter = new BoxModelHighlighter(highlighterEnv);
if (args.fill) {
highlighter.regionFill[args.region] = args.fill;
}
@ -122,7 +135,7 @@ exports.items = [
showOnly: args.region
});
exports.highlighters.push(highlighter);
i ++;
i++;
}
let highlightText = nodesSelected.GetStringFromName("highlightOutputConfirm2");

Просмотреть файл

@ -8,84 +8,88 @@ const EventEmitter = require("devtools/toolkit/event-emitter");
const eventEmitter = new EventEmitter();
const events = require("sdk/event/core");
const gcli = require("gcli/index");
const l10n = require("gcli/l10n");
require("devtools/server/actors/inspector");
const { RulersHighlighter } = require("devtools/server/actors/highlighter");
const { RulersHighlighter, HighlighterEnvironment } =
require("devtools/server/actors/highlighter");
const highlighters = new WeakMap();
let isRulersVisible = false;
exports.items = [
// The client rulers command is used to maintain the toolbar button state only
// and redirects to the server command to actually toggle the rulers (see
// rulers_server below).
{
name: "rulers",
runAt: "client",
description: l10n.lookup("rulersDesc"),
manual: l10n.lookup("rulersManual"),
buttonId: "command-button-rulers",
buttonClass: "command-button command-button-invertable",
tooltipText: l10n.lookup("rulersTooltip"),
state: {
isChecked: function(aTarget) {
if (aTarget.isLocalTab) {
let window = aTarget.tab.linkedBrowser.contentWindow;
if (window) {
return highlighters.has(window.document);
}
return false;
} else {
throw new Error("Unsupported target");
}
},
onChange: function(aTarget, aChangeHandler) {
eventEmitter.on("changed", aChangeHandler);
},
offChange: function(aTarget, aChangeHandler) {
eventEmitter.off("changed", aChangeHandler);
},
isChecked: () => isRulersVisible,
onChange: (target, handler) => eventEmitter.on("changed", handler),
offChange: (target, handler) => eventEmitter.off("changed", handler)
},
exec: function*(args, context) {
let { target } = context.environment;
// Pipe the call to the server command.
let response = yield context.updateExec("rulers_server");
isRulersVisible = response.data;
eventEmitter.emit("changed", { target });
// Toggle off the button when the page navigates because the rulers are
// removed automatically by the RulersHighlighter on the server then.
let onNavigate = () => {
isRulersVisible = false;
eventEmitter.emit("changed", { target });
};
target.off("will-navigate", onNavigate);
target.once("will-navigate", onNavigate);
}
},
// The server rulers command is hidden by default, it's just used by the
// client command.
{
name: "rulers_server",
runAt: "server",
hidden: true,
exec: function(args, context) {
let env = context.environment;
let { target } = env;
// Calling the command again after the rulers have been shown once hides
// them.
if (highlighters.has(env.document)) {
highlighters.get(env.document).highlighter.destroy();
return;
let { highlighter, environment } = highlighters.get(env.document);
highlighter.destroy();
environment.destroy();
return false;
}
// Build a tab context for the highlighter (which normally takes a
// TabActor as parameter to its constructor)
let tabContext = {
browser: env.chromeWindow.gBrowser.getBrowserForDocument(env.document),
window: env.window
};
// Otherwise, display the rulers.
let environment = new HighlighterEnvironment();
environment.initFromWindow(env.window);
let highlighter = new RulersHighlighter(environment);
let emitToContext = (type, data) =>
events.emit(tabContext, type, Object.assign({isTopLevel: true}, data))
target.once("navigate", emitToContext);
target.once("will-navigate", emitToContext);
let highlighter = new RulersHighlighter(tabContext);
highlighters.set(env.document, { highlighter, listener: emitToContext });
// Store the instance of the rulers highlighter for this document so we
// can hide it later.
highlighters.set(env.document, { highlighter, environment });
// Listen to the highlighter's destroy event which may happen if the
// window is refreshed or closed with the rulers shown.
events.once(highlighter, "destroy", () => {
if (highlighters.has(env.document)) {
let { highlighter, listener } = highlighters.get(env.document);
target.off("navigate", listener);
target.off("will-navigate", listener);
let { environment } = highlighters.get(env.document);
environment.destroy();
highlighters.delete(env.document);
}
eventEmitter.emit("changed", { target });
});
highlighter.show();
eventEmitter.emit("changed", { target });
return true;
}
}
];

Просмотреть файл

@ -266,10 +266,6 @@ const GcliActor = ActorClass({
get document() {
return tabActor.window.document;
},
get __deprecatedTabActor() {
return tabActor;
}
};

Просмотреть файл

@ -130,6 +130,8 @@ let HighlighterActor = exports.HighlighterActor = protocol.ActorClass({
this._inspector = inspector;
this._walker = this._inspector.walker;
this._tabActor = this._inspector.tabActor;
this._highlighterEnv = new HighlighterEnvironment();
this._highlighterEnv.initFromTabActor(this._tabActor);
this._highlighterReady = this._highlighterReady.bind(this);
this._highlighterHidden = this._highlighterHidden.bind(this);
@ -148,15 +150,15 @@ let HighlighterActor = exports.HighlighterActor = protocol.ActorClass({
},
_createHighlighter: function() {
this._isPreviousWindowXUL = isXUL(this._tabActor);
this._isPreviousWindowXUL = isXUL(this._tabActor.window);
if (!this._isPreviousWindowXUL) {
this._highlighter = new BoxModelHighlighter(this._tabActor,
this._inspector);
this._highlighter = new BoxModelHighlighter(this._highlighterEnv,
this._inspector);
this._highlighter.on("ready", this._highlighterReady);
this._highlighter.on("hide", this._highlighterHidden);
} else {
this._highlighter = new SimpleOutlineHighlighter(this._tabActor);
this._highlighter = new SimpleOutlineHighlighter(this._highlighterEnv);
}
},
@ -179,7 +181,7 @@ let HighlighterActor = exports.HighlighterActor = protocol.ActorClass({
}
// Only rebuild the highlighter if the window type changed.
if (isXUL(this._tabActor) !== this._isPreviousWindowXUL) {
if (isXUL(this._tabActor.window) !== this._isPreviousWindowXUL) {
this._destroyHighlighter();
this._createHighlighter();
}
@ -190,6 +192,10 @@ let HighlighterActor = exports.HighlighterActor = protocol.ActorClass({
this._destroyHighlighter();
events.off(this._tabActor, "navigate", this._onNavigate);
this._highlighterEnv.destroy();
this._highlighterEnv = null;
this._autohide = null;
this._inspector = null;
this._walker = null;
@ -357,7 +363,7 @@ let HighlighterActor = exports.HighlighterActor = protocol.ActorClass({
},
_startPickerListeners: function() {
let target = getPageListenerTarget(this._tabActor);
let target = this._highlighterEnv.pageListenerTarget;
target.addEventListener("mousemove", this._onHovered, true);
target.addEventListener("click", this._onPick, true);
target.addEventListener("mousedown", this._preventContentEvent, true);
@ -368,7 +374,7 @@ let HighlighterActor = exports.HighlighterActor = protocol.ActorClass({
},
_stopPickerListeners: function() {
let target = getPageListenerTarget(this._tabActor);
let target = this._highlighterEnv.pageListenerTarget;
target.removeEventListener("mousemove", this._onHovered, true);
target.removeEventListener("click", this._onPick, true);
target.removeEventListener("mousedown", this._preventContentEvent, true);
@ -425,8 +431,10 @@ let CustomHighlighterActor = exports.CustomHighlighterActor = protocol.ActorClas
// The assumption is that all custom highlighters need the canvasframe
// container to append their elements, so if this is a XUL window, bail out.
if (!isXUL(this._inspector.tabActor)) {
this._highlighter = new constructor(inspector.tabActor);
if (!isXUL(this._inspector.tabActor.window)) {
this._highlighterEnv = new HighlighterEnvironment();
this._highlighterEnv.initFromTabActor(inspector.tabActor);
this._highlighter = new constructor(this._highlighterEnv);
} else {
throw new Error("Custom " + typeName +
"highlighter cannot be created in a XUL window");
@ -441,6 +449,7 @@ let CustomHighlighterActor = exports.CustomHighlighterActor = protocol.ActorClas
destroy: function() {
protocol.Actor.prototype.destroy.call(this);
this.finalize();
this._inspector = null;
},
/**
@ -491,10 +500,16 @@ let CustomHighlighterActor = exports.CustomHighlighterActor = protocol.ActorClas
* is destroyed.
*/
finalize: method(function() {
if (this._highlighterEnv) {
this._highlighterEnv.destroy();
this._highlighterEnv = null;
}
if (this._highlighter) {
this._highlighter.destroy();
this._highlighter = null;
}
}, {
oneway: true
})
@ -515,23 +530,23 @@ let CustomHighlighterFront = protocol.FrontClass(CustomHighlighterActor, {});
* described in AnonymousContent.webidl.
* To retrieve the AnonymousContent instance, use the content getter.
*
* @param {TabActor} tabActor
* The tabactor which windows will be used to insert the node
* @param {HighlighterEnv} highlighterEnv
* The environemnt which windows will be used to insert the node.
* @param {Function} nodeBuilder
* A function that, when executed, returns a DOM node to be inserted into
* the canvasFrame
* the canvasFrame.
*/
function CanvasFrameAnonymousContentHelper(tabActor, nodeBuilder) {
this.tabActor = tabActor;
function CanvasFrameAnonymousContentHelper(highlighterEnv, nodeBuilder) {
this.highlighterEnv = highlighterEnv;
this.nodeBuilder = nodeBuilder;
this.anonymousContentDocument = this.tabActor.window.document;
this.anonymousContentDocument = this.highlighterEnv.document;
// XXX the next line is a wallpaper for bug 1123362.
this.anonymousContentGlobal = Cu.getGlobalForObject(this.anonymousContentDocument);
this._insert();
this._onNavigate = this._onNavigate.bind(this);
events.on(this.tabActor, "navigate", this._onNavigate);
this.highlighterEnv.on("navigate", this._onNavigate);
this.listeners = new Map();
}
@ -546,8 +561,8 @@ CanvasFrameAnonymousContentHelper.prototype = {
let doc = this.anonymousContentDocument;
doc.removeAnonymousContent(this._content);
} catch (e) {}
events.off(this.tabActor, "navigate", this._onNavigate);
this.tabActor = this.nodeBuilder = this._content = null;
this.highlighterEnv.off("navigate", this._onNavigate);
this.highlighterEnv = this.nodeBuilder = this._content = null;
this.anonymousContentDocument = null;
this.anonymousContentGlobal = null;
@ -557,11 +572,11 @@ CanvasFrameAnonymousContentHelper.prototype = {
_insert: function() {
// Insert the content node only if the page isn't in a XUL window, and if
// the document still exists.
if (!this.tabActor.window.document.documentElement ||
isXUL(this.tabActor)) {
if (!this.highlighterEnv.document.documentElement ||
isXUL(this.highlighterEnv.window)) {
return;
}
let doc = this.tabActor.window.document;
let doc = this.highlighterEnv.document;
// On B2G, for example, when connecting to keyboard just after startup,
// we connect to a hidden document, which doesn't accept
@ -581,17 +596,17 @@ CanvasFrameAnonymousContentHelper.prototype = {
// <style scoped> doesn't work inside anonymous content (see bug 1086532).
// If it did, highlighter.css would be injected as an anonymous content
// node using CanvasFrameAnonymousContentHelper instead.
installHelperSheet(this.tabActor.window,
installHelperSheet(this.highlighterEnv.window,
"@import url('" + HIGHLIGHTER_STYLESHEET_URI + "');");
let node = this.nodeBuilder();
this._content = doc.insertAnonymousContent(node);
},
_onNavigate: function({isTopLevel}) {
_onNavigate: function(e, {isTopLevel}) {
if (isTopLevel) {
this._removeAllListeners();
this._insert();
this.anonymousContentDocument = this.tabActor.window.document;
this.anonymousContentDocument = this.highlighterEnv.document;
}
},
@ -671,7 +686,7 @@ CanvasFrameAnonymousContentHelper.prototype = {
// If no one is listening for this type of event yet, add one listener.
if (!this.listeners.has(type)) {
let target = getPageListenerTarget(this.tabActor);
let target = this.highlighterEnv.pageListenerTarget;
target.addEventListener(type, this, true);
// Each type entry in the map is a map of ids:handlers.
this.listeners.set(type, new Map);
@ -697,7 +712,7 @@ CanvasFrameAnonymousContentHelper.prototype = {
// If no one is listening for event type anymore, remove the listener.
if (!this.listeners.has(type)) {
let target = getPageListenerTarget(this.tabActor);
let target = this.highlighterEnv.pageListenerTarget;
target.removeEventListener(type, this, true);
}
},
@ -741,8 +756,8 @@ CanvasFrameAnonymousContentHelper.prototype = {
},
_removeAllListeners: function() {
if (this.tabActor) {
let target = getPageListenerTarget(this.tabActor);
if (this.highlighterEnv) {
let target = this.highlighterEnv.pageListenerTarget;
for (let [type] of this.listeners) {
target.removeEventListener(type, this, true);
}
@ -829,11 +844,11 @@ CanvasFrameAnonymousContentHelper.prototype = {
* - hidden
* - updated
*/
function AutoRefreshHighlighter(tabActor) {
function AutoRefreshHighlighter(highlighterEnv) {
EventEmitter.decorate(this);
this.tabActor = tabActor;
this.win = tabActor.window;
this.highlighterEnv = highlighterEnv;
this.win = highlighterEnv.window;
this.currentNode = null;
this.currentQuads = {};
@ -985,7 +1000,7 @@ AutoRefreshHighlighter.prototype = {
destroy: function() {
this.hide();
this.tabActor = null;
this.highlighterEnv = null;
this.win = null;
this.currentNode = null;
this.layoutHelpers = null;
@ -1000,7 +1015,7 @@ AutoRefreshHighlighter.prototype = {
*
* Usage example:
*
* let h = new BoxModelHighlighter(browser);
* let h = new BoxModelHighlighter(env);
* h.show(node, options);
* h.hide();
* h.destroy();
@ -1048,10 +1063,10 @@ AutoRefreshHighlighter.prototype = {
* </div>
* </div>
*/
function BoxModelHighlighter(tabActor) {
AutoRefreshHighlighter.call(this, tabActor);
function BoxModelHighlighter(highlighterEnv) {
AutoRefreshHighlighter.call(this, highlighterEnv);
this.markup = new CanvasFrameAnonymousContentHelper(this.tabActor,
this.markup = new CanvasFrameAnonymousContentHelper(this.highlighterEnv,
this._buildMarkup.bind(this));
/**
@ -1664,10 +1679,10 @@ exports.BoxModelHighlighter = BoxModelHighlighter;
* transformed element and an outline around where it would be if untransformed
* as well as arrows connecting the 2 outlines' corners.
*/
function CssTransformHighlighter(tabActor) {
AutoRefreshHighlighter.call(this, tabActor);
function CssTransformHighlighter(highlighterEnv) {
AutoRefreshHighlighter.call(this, highlighterEnv);
this.markup = new CanvasFrameAnonymousContentHelper(this.tabActor,
this.markup = new CanvasFrameAnonymousContentHelper(this.highlighterEnv,
this._buildMarkup.bind(this));
}
@ -1894,8 +1909,8 @@ exports.CssTransformHighlighter = CssTransformHighlighter;
* document of the provided context node and then uses the BoxModelHighlighter
* to highlight the matching nodes
*/
function SelectorHighlighter(tabActor) {
this.tabActor = tabActor;
function SelectorHighlighter(highlighterEnv) {
this.highlighterEnv = highlighterEnv;
this._highlighters = [];
}
@ -1931,7 +1946,7 @@ SelectorHighlighter.prototype = {
break;
}
let highlighter = new BoxModelHighlighter(this.tabActor);
let highlighter = new BoxModelHighlighter(this.highlighterEnv);
if (options.fill) {
highlighter.regionFill[options.region || "border"] = options.fill;
}
@ -1952,7 +1967,7 @@ SelectorHighlighter.prototype = {
destroy: function() {
this.hide();
this.tabActor = null;
this.highlighterEnv = null;
}
};
register(SelectorHighlighter);
@ -1965,10 +1980,10 @@ exports.SelectorHighlighter = SelectorHighlighter;
* It also does *not* update dynamically, it only highlights a rect and remains
* there as long as it is shown.
*/
function RectHighlighter(tabActor) {
this.win = tabActor.window;
function RectHighlighter(highlighterEnv) {
this.win = highlighterEnv.window;
this.layoutHelpers = new LayoutHelpers(this.win);
this.markup = new CanvasFrameAnonymousContentHelper(tabActor,
this.markup = new CanvasFrameAnonymousContentHelper(highlighterEnv,
this._buildMarkup.bind(this));
}
@ -2134,13 +2149,13 @@ let GeoProp = {
* Note that the class name contains the word Editor because the aim is for the
* handles to be draggable in content to make the geometry editable.
*/
function GeometryEditorHighlighter(tabActor) {
AutoRefreshHighlighter.call(this, tabActor);
function GeometryEditorHighlighter(highlighterEnv) {
AutoRefreshHighlighter.call(this, highlighterEnv);
// The list of element geometry properties that can be set.
this.definedProperties = new Map();
this.markup = new CanvasFrameAnonymousContentHelper(tabActor,
this.markup = new CanvasFrameAnonymousContentHelper(highlighterEnv,
this._buildMarkup.bind(this));
}
@ -2650,9 +2665,9 @@ exports.GeometryEditorHighlighter = GeometryEditorHighlighter;
* vertical rules on the page, along the top and left edges, with pixel
* graduations, useful for users to quickly check distances
*/
function RulersHighlighter(tabActor) {
this.win = tabActor.window;
this.markup = new CanvasFrameAnonymousContentHelper(tabActor,
function RulersHighlighter(highlighterEnv) {
this.win = highlighterEnv.window;
this.markup = new CanvasFrameAnonymousContentHelper(highlighterEnv,
this._buildMarkup.bind(this));
this.win.addEventListener("scroll", this, true);
@ -2874,8 +2889,8 @@ exports.RulersHighlighter = RulersHighlighter;
* It is used by the HighlighterActor when canvasframe-based highlighters can't
* be used. This is the case for XUL windows.
*/
function SimpleOutlineHighlighter(tabActor) {
this.chromeDoc = tabActor.window.document;
function SimpleOutlineHighlighter(highlighterEnv) {
this.chromeDoc = highlighterEnv.document;
}
SimpleOutlineHighlighter.prototype = {
@ -2955,10 +2970,12 @@ function installHelperSheet(win, source, type="agent") {
}
/**
* Is the content window in this tabActor a XUL window
* Is this content window a XUL window?
* @param {Window} window
* @return {Boolean}
*/
function isXUL(tabActor) {
return tabActor.window.document.documentElement.namespaceURI === XUL_NS;
function isXUL(window) {
return window.document.documentElement.namespaceURI === XUL_NS;
}
/**
@ -3018,23 +3035,6 @@ function createNode(win, options) {
return node;
}
/**
* Get the right target for listening to events on the page (while picking an
* element for instance).
* - On a firefox desktop content page: tabActor is a BrowserTabActor from
* which the browser property will give us a target we can use to listen to
* events, even in nested iframes.
* - On B2G: tabActor is a ContentActor which doesn't have a browser but
* since it overrides BrowserTabActor, it does get a browser property
* anyway, which points to its window object.
* - When using the Browser Toolbox (to inspect firefox desktop): tabActor is
* the RootActor, in which case, the window property can be used to listen
* to events
*/
function getPageListenerTarget(tabActor) {
return tabActor.isRootActor ? tabActor.window : tabActor.chromeEventHandler;
}
/**
* Get a node's owner window.
*/
@ -3076,6 +3076,157 @@ function getOffsetParent(node) {
};
}
XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils)
/**
* The HighlighterEnvironment is an object that holds all the required data for
* highlighters to work: the window, docShell, event listener target, ...
* It also emits "will-navigate" and "navigate" events, similarly to the
* TabActor.
*
* It can be initialized either from a TabActor (which is the most frequent way
* of using it, since highlighters are usually initialized by the
* HighlighterActor or CustomHighlighterActor, which have a tabActor reference).
* It can also be initialized just with a window object (which is useful for
* when a highlighter is used outside of the debugger server context, for
* instance from a gcli command).
*/
function HighlighterEnvironment() {
this.relayTabActorNavigate = this.relayTabActorNavigate.bind(this);
this.relayTabActorWillNavigate = this.relayTabActorWillNavigate.bind(this);
EventEmitter.decorate(this);
}
exports.HighlighterEnvironment = HighlighterEnvironment;
HighlighterEnvironment.prototype = {
initFromTabActor: function(tabActor) {
this._tabActor = tabActor;
events.on(this._tabActor, "navigate", this.relayTabActorNavigate);
events.on(this._tabActor, "will-navigate", this.relayTabActorWillNavigate);
},
initFromWindow: function(win) {
this._win = win;
// We need a progress listener to know when the window will navigate/has
// navigated.
let self = this;
this.listener = {
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
Ci.nsISupports
]),
onStateChange: function(progress, request, flag) {
let isStart = flag & Ci.nsIWebProgressListener.STATE_START;
let isStop = flag & Ci.nsIWebProgressListener.STATE_STOP;
let isWindow = flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
let isDocument = flag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
if (progress.DOMWindow !== win) {
return;
}
if (isDocument && isStart) {
// One of the earliest events that tells us a new URI is being loaded
// in this window.
self.emit("will-navigate", {
window: win,
isTopLevel: true
});
}
if (isWindow && isStop) {
self.emit("navigate", {
window: win,
isTopLevel: true
});
}
}
};
this.webProgress.addProgressListener(this.listener,
Ci.nsIWebProgress.NOTIFY_STATUS |
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
},
get isInitialized() {
return this._win || this._tabActor;
},
get window() {
if (!this.isInitialized) {
throw new Error("Initialize HighlighterEnvironment with a tabActor " +
"or window first");
}
return this._tabActor ? this._tabActor.window : this._win;
},
get document() {
return this.window.document;
},
get docShell() {
return this.window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
},
get webProgress() {
return this.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
},
/**
* Get the right target for listening to events on the page.
* - If the environment was initialized from a TabActor *and* if we're in the
* Browser Toolbox (to inspect firefox desktop): the tabActor is the
* RootActor, in which case, the window property can be used to listen to
* events.
* - With firefox desktop, that tabActor is a BrowserTabActor, and with B2G,
* a ContentActor (which overrides BrowserTabActor). In both cases we use
* the chromeEventHandler which gives us a target we can use to listen to
* events, even from nested iframes.
* - If the environment was initialized from a window, we also use the
* chromeEventHandler.
*/
get pageListenerTarget() {
if (this._tabActor && this._tabActor.isRootActor) {
return this.window;
}
return this.docShell.chromeEventHandler;
},
relayTabActorNavigate: function(data) {
this.emit("navigate", data);
},
relayTabActorWillNavigate: function(data) {
this.emit("will-navigate", data);
},
destroy: function() {
if (this._tabActor) {
events.off(this._tabActor, "navigate", this.relayTabActorNavigate);
events.off(this._tabActor, "will-navigate", this.relayTabActorWillNavigate);
}
// In case the environment was initialized from a window, we need to remove
// the progress listener.
if (this._win) {
try {
this.webProgress.removeProgressListener(this.listener);
} catch(e) {
// Which may fail in case the window was already destroyed.
}
}
this._tabActor = null;
this._win = null;
}
};
XPCOMUtils.defineLazyGetter(this, "DOMUtils", function() {
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
});

Просмотреть файл

@ -9,7 +9,10 @@
// This makes sure the 'domnode' protocol actor type is known when importing
// highlighter.
require("devtools/server/actors/inspector");
const {CanvasFrameAnonymousContentHelper} = require("devtools/server/actors/highlighter");
const {
CanvasFrameAnonymousContentHelper,
HighlighterEnvironment
} = require("devtools/server/actors/highlighter");
const TEST_URL = "data:text/html;charset=utf-8,CanvasFrameAnonymousContentHelper test";
add_task(function*() {
@ -27,8 +30,9 @@ add_task(function*() {
};
info("Building the helper");
let helper = new CanvasFrameAnonymousContentHelper(
getMockTabActor(doc.defaultView), nodeBuilder);
let env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
let helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
ok(helper.content instanceof AnonymousContent,
"The helper owns the AnonymousContent object");
@ -70,6 +74,7 @@ add_task(function*() {
info("Destroying the helper");
helper.destroy();
env.destroy();
ok(!helper.getTextContentForElement("child-element"),
"No text content was retrieved after the helper was destroyed");

Просмотреть файл

@ -10,7 +10,10 @@
// This makes sure the 'domnode' protocol actor type is known when importing
// highlighter.
require("devtools/server/actors/inspector");
const {CanvasFrameAnonymousContentHelper} = require("devtools/server/actors/highlighter");
const {
CanvasFrameAnonymousContentHelper,
HighlighterEnvironment
} = require("devtools/server/actors/highlighter");
add_task(function*() {
let doc = yield addTab("about:preferences");
@ -27,12 +30,16 @@ add_task(function*() {
};
info("Building the helper");
let helper = new CanvasFrameAnonymousContentHelper(
getMockTabActor(doc.defaultView), nodeBuilder);
let env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
let helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
ok(!helper.content, "The AnonymousContent was not inserted in the window");
ok(!helper.getTextContentForElement("child-element"),
"No text content is returned");
env.destroy();
helper.destroy();
gBrowser.removeCurrentTab();
});

Просмотреть файл

@ -9,7 +9,10 @@
// This makes sure the 'domnode' protocol actor type is known when importing
// highlighter.
require("devtools/server/actors/inspector");
const {CanvasFrameAnonymousContentHelper} = require("devtools/server/actors/highlighter");
const {
CanvasFrameAnonymousContentHelper,
HighlighterEnvironment
} = require("devtools/server/actors/highlighter");
const TEST_URL = "data:text/html;charset=utf-8,CanvasFrameAnonymousContentHelper test";
add_task(function*() {
@ -26,8 +29,9 @@ add_task(function*() {
};
info("Building the helper");
let helper = new CanvasFrameAnonymousContentHelper(
getMockTabActor(doc.defaultView), nodeBuilder);
let env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
let helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
let el = helper.getElement("child-element");
@ -36,7 +40,7 @@ add_task(function*() {
function onMouseDown(e, id) {
is(id, "child-element", "The mousedown event was triggered on the element");
ok(!e.originalTarget, "The originalTarget property isn't available");
mouseDownHandled ++;
mouseDownHandled++;
}
el.addEventListener("mousedown", onMouseDown);
@ -70,6 +74,7 @@ add_task(function*() {
el.addEventListener("mousedown", onMouseDown);
info("Destroying the helper");
env.destroy();
helper.destroy();
info("Synthesizing another event after the helper has been destroyed");

Просмотреть файл

@ -10,7 +10,10 @@
// This makes sure the 'domnode' protocol actor type is known when importing
// highlighter.
require("devtools/server/actors/inspector");
const {CanvasFrameAnonymousContentHelper} = require("devtools/server/actors/highlighter");
const {
CanvasFrameAnonymousContentHelper,
HighlighterEnvironment
} = require("devtools/server/actors/highlighter");
const events = require("sdk/event/core");
const TEST_URL_1 = "data:text/html;charset=utf-8,CanvasFrameAnonymousContentHelper test 1";
const TEST_URL_2 = "data:text/html;charset=utf-8,CanvasFrameAnonymousContentHelper test 2";
@ -18,8 +21,6 @@ const TEST_URL_2 = "data:text/html;charset=utf-8,CanvasFrameAnonymousContentHelp
add_task(function*() {
let doc = yield addTab(TEST_URL_2);
let tabActor = getMockTabActor(doc.defaultView);
let nodeBuilder = () => {
let root = doc.createElement("div");
let child = doc.createElement("div");
@ -32,7 +33,9 @@ add_task(function*() {
};
info("Building the helper");
let helper = new CanvasFrameAnonymousContentHelper(tabActor, nodeBuilder);
let env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
let helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
info("Get an element from the helper");
let el = helper.getElement("child-element");
@ -63,9 +66,6 @@ add_task(function*() {
yield loaded;
doc = gBrowser.selectedBrowser.contentWindow.document;
info("And faking the 'navigate' event on the tabActor");
events.emit(tabActor, "navigate", tabActor);
info("Try to access the element again");
is(el.getAttribute("class"), "child-element",
"The attribute is correct after navigation");
@ -79,6 +79,7 @@ add_task(function*() {
is(mouseDownHandled, 1, "The mousedown event was not handled after navigation");
info("Destroying the helper");
env.destroy();
helper.destroy();
gBrowser.removeCurrentTab();

Просмотреть файл

@ -10,7 +10,10 @@
// This makes sure the 'domnode' protocol actor type is known when importing
// highlighter.
require("devtools/server/actors/inspector");
const {CanvasFrameAnonymousContentHelper} = require("devtools/server/actors/highlighter");
const {
CanvasFrameAnonymousContentHelper,
HighlighterEnvironment
} = require("devtools/server/actors/highlighter");
const TEST_URL = "data:text/html;charset=utf-8,CanvasFrameAnonymousContentHelper test";
add_task(function*() {
@ -33,8 +36,9 @@ add_task(function*() {
};
info("Building the helper");
let helper = new CanvasFrameAnonymousContentHelper(
getMockTabActor(doc.defaultView), nodeBuilder);
let env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
let helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
info("Getting the parent and child elements");
let parentEl = helper.getElement("parent-element");
@ -89,6 +93,9 @@ add_task(function*() {
info("Removing the parent listener");
parentEl.removeEventListener("mousedown", onMouseDown);
env.destroy();
helper.destroy();
gBrowser.removeCurrentTab();
});

Просмотреть файл

@ -10,7 +10,10 @@
// This makes sure the 'domnode' protocol actor type is known when importing
// highlighter.
require("devtools/server/actors/inspector");
const {CanvasFrameAnonymousContentHelper} = require("devtools/server/actors/highlighter");
const {
CanvasFrameAnonymousContentHelper,
HighlighterEnvironment
} = require("devtools/server/actors/highlighter");
const TEST_URL = "data:text/html;charset=utf-8,CanvasFrameAnonymousContentHelper test";
add_task(function*() {
@ -33,8 +36,9 @@ add_task(function*() {
};
info("Building the helper");
let helper = new CanvasFrameAnonymousContentHelper(
getMockTabActor(doc.defaultView), nodeBuilder);
let env = new HighlighterEnvironment();
env.initFromWindow(doc.defaultView);
let helper = new CanvasFrameAnonymousContentHelper(env, nodeBuilder);
info("Getting the parent and child elements");
let parentEl = helper.getElement("parent-element");
@ -77,6 +81,9 @@ add_task(function*() {
parentEl.removeEventListener("mousedown", onParentMouseDown);
childEl.removeEventListener("mousedown", onChildMouseDown);
env.destroy();
helper.destroy();
gBrowser.removeCurrentTab();
});