зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
1f6cfe0ec7
|
@ -21,7 +21,7 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
|
@ -137,7 +137,7 @@
|
|||
<default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/>
|
||||
<!-- Emulator specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="49f5591508df408fab7d7d8322681b004a2750f3"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="566810728cd485ff2f30766499d32ada7cbd487a"/>
|
||||
<project name="platform_bionic" path="bionic" remote="b2g" revision="3e85c4683c121530c1c3a48c696a569bf5f587e2"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="39bdda3051dd1d96da3ab369bc654290cb8d463c"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
|
||||
|
@ -145,7 +145,7 @@
|
|||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="c0dd0098328f3992e1ca09d6d4355729243863d5"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="5f4b68c799927b6e078f987b12722c3a6ccd4a45"/>
|
||||
<project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
|
||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="6a1bb59af65b6485b1090522f66fac95c3f9e22c"/>
|
||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="0c0c050518705d49531375012fa2b4e95e1b3693"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
|
||||
<project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
|
||||
</manifest>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "efd70ba6a54849dcef696abf1652cf74daa07899",
|
||||
"git_revision": "619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "687b7b7814ff8a089fda4c4d6be564305a0a2b69",
|
||||
"revision": "d74e738cd626558fb9dc289500ad28ae29deab03",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
|
|
@ -135,11 +135,17 @@
|
|||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("errorShortDescText_forbidden");
|
||||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("whyForbiddenButton");
|
||||
el.parentNode.removeChild(el);
|
||||
} else {
|
||||
el = document.getElementById("ignoreWarningButton");
|
||||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("reportButton");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
// Remove red style: A "forbidden site" does not warrant the same level
|
||||
// of anxiety as a security concern.
|
||||
document.documentElement.className = "";
|
||||
}
|
||||
|
||||
// Set sitename
|
||||
|
@ -197,7 +203,7 @@
|
|||
<h1 id="errorTitleText_phishing">&safeb.blocked.phishingPage.title;</h1>
|
||||
<h1 id="errorTitleText_malware">&safeb.blocked.malwarePage.title;</h1>
|
||||
<h1 id="errorTitleText_unwanted">&safeb.blocked.unwantedPage.title;</h1>
|
||||
<h1 id="errorTitleText_forbidden">&safeb.blocked.forbiddenPage.title;</h1>
|
||||
<h1 id="errorTitleText_forbidden">&safeb.blocked.forbiddenPage.title2;</h1>
|
||||
</div>
|
||||
|
||||
<div id="errorLongContent">
|
||||
|
@ -207,7 +213,7 @@
|
|||
<p id="errorShortDescText_phishing">&safeb.blocked.phishingPage.shortDesc;</p>
|
||||
<p id="errorShortDescText_malware">&safeb.blocked.malwarePage.shortDesc;</p>
|
||||
<p id="errorShortDescText_unwanted">&safeb.blocked.unwantedPage.shortDesc;</p>
|
||||
<p id="errorShortDescText_forbidden">&safeb.blocked.forbiddenPage.shortDesc;</p>
|
||||
<p id="errorShortDescText_forbidden">&safeb.blocked.forbiddenPage.shortDesc2;</p>
|
||||
</div>
|
||||
|
||||
<!-- Long Description -->
|
||||
|
@ -222,6 +228,7 @@
|
|||
<!-- Commands handled in browser.js -->
|
||||
<button id="getMeOutButton">&safeb.palm.accept.label;</button>
|
||||
<button id="reportButton">&safeb.palm.reportPage.label;</button>
|
||||
<button id="whyForbiddenButton">&safeb.palm.whyForbidden.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ignoreWarning">
|
||||
|
|
|
@ -2913,6 +2913,12 @@ var BrowserOnClick = {
|
|||
this.ignoreWarningButton(reason);
|
||||
}
|
||||
break;
|
||||
|
||||
case "whyForbiddenButton":
|
||||
// This is the "Why is this site blocked" button for family friendly browsing
|
||||
// for Fennec. There's no desktop focused support page yet.
|
||||
gBrowser.loadURI("https://support.mozilla.org/kb/controlledaccess");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -6031,8 +6031,11 @@
|
|||
// visual status to selected until after we receive confirmation that its content has painted.
|
||||
this._logicallySelected = val;
|
||||
|
||||
// If we're non-e10s we should update the visual selection as well at the same time
|
||||
if (!gMultiProcessBrowser) {
|
||||
// If we're non-e10s we should update the visual selection as well at the same time,
|
||||
// *or* if we're e10s and the visually selected tab isn't changing, in which case the
|
||||
// tab switcher code won't run and update anything else (like the before- and after-
|
||||
// selected attributes).
|
||||
if (!gMultiProcessBrowser || (val && this.hasAttribute("visuallyselected"))) {
|
||||
this._visuallySelected = val;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,4 +4,3 @@ support-files =
|
|||
file_reflect_cookie_into_title.html
|
||||
|
||||
[browser_usercontext.js]
|
||||
skip-if = e10s
|
||||
|
|
|
@ -161,7 +161,7 @@ FirefoxProfileMigrator.prototype._getResourcesInternal = function(sourceProfileD
|
|||
}
|
||||
}
|
||||
|
||||
// FHR related migrations.
|
||||
// Telemetry related migrations.
|
||||
let times = {
|
||||
name: "times", // name is used only by tests.
|
||||
type: types.OTHERDATA,
|
||||
|
@ -178,69 +178,60 @@ FirefoxProfileMigrator.prototype._getResourcesInternal = function(sourceProfileD
|
|||
);
|
||||
}
|
||||
};
|
||||
let healthReporter = {
|
||||
name: "healthreporter", // name is used only by tests...
|
||||
let telemetry = {
|
||||
name: "telemetry", // name is used only by tests...
|
||||
type: types.OTHERDATA,
|
||||
migrate: aCallback => {
|
||||
// the health-reporter can't have been initialized yet so it's safe to
|
||||
// copy the SQL file.
|
||||
let createSubDir = (name) => {
|
||||
let dir = currentProfileDir.clone();
|
||||
dir.append(name);
|
||||
dir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
return dir;
|
||||
};
|
||||
|
||||
// We only support the default database name - copied from healthreporter.jsm
|
||||
const DEFAULT_DATABASE_NAME = "healthreport.sqlite";
|
||||
let path = OS.Path.join(sourceProfileDir.path, DEFAULT_DATABASE_NAME);
|
||||
let sqliteFile = FileUtils.File(path);
|
||||
if (sqliteFile.exists()) {
|
||||
sqliteFile.copyTo(currentProfileDir, "");
|
||||
}
|
||||
// In unusual cases there may be 2 additional files - a "write ahead log"
|
||||
// (-wal) file and a "shared memory file" (-shm). The wal file contains
|
||||
// data that will be replayed when the DB is next opened, while the shm
|
||||
// file is ignored in that case - the replay happens using only the wal.
|
||||
// So we *do* copy a wal if it exists, but not a shm.
|
||||
// See https://www.sqlite.org/tempfiles.html for more.
|
||||
// (Note also we attempt these copies even if we can't find the DB, and
|
||||
// rely on FHR itself to do the right thing if it can)
|
||||
path = OS.Path.join(sourceProfileDir.path, DEFAULT_DATABASE_NAME + "-wal");
|
||||
let sqliteWal = FileUtils.File(path);
|
||||
if (sqliteWal.exists()) {
|
||||
sqliteWal.copyTo(currentProfileDir, "");
|
||||
}
|
||||
|
||||
// If the 'healthreport' directory exists we copy everything from it.
|
||||
let subdir = this._getFileObject(sourceProfileDir, "healthreport");
|
||||
// If the 'datareporting' directory exists we migrate files from it.
|
||||
let haveStateFile = false;
|
||||
let subdir = this._getFileObject(sourceProfileDir, "datareporting");
|
||||
if (subdir && subdir.isDirectory()) {
|
||||
// Copy all regular files.
|
||||
let dest = currentProfileDir.clone();
|
||||
dest.append("healthreport");
|
||||
dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE,
|
||||
FileUtils.PERMS_DIRECTORY);
|
||||
// Copy only specific files.
|
||||
let toCopy = ["state.json", "session-state.json"];
|
||||
|
||||
let dest = createSubDir("datareporting");
|
||||
let enumerator = subdir.directoryEntries;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let file = enumerator.getNext().QueryInterface(Components.interfaces.nsIFile);
|
||||
if (file.isDirectory()) {
|
||||
let file = enumerator.getNext().QueryInterface(Ci.nsIFile);
|
||||
if (file.isDirectory() || toCopy.indexOf(file.leafName) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file.leafName == "state.json") {
|
||||
haveStateFile = true;
|
||||
}
|
||||
file.copyTo(dest, "");
|
||||
}
|
||||
}
|
||||
// If the 'datareporting' directory exists we copy just state.json
|
||||
subdir = this._getFileObject(sourceProfileDir, "datareporting");
|
||||
if (subdir && subdir.isDirectory()) {
|
||||
let stateFile = this._getFileObject(subdir, "state.json");
|
||||
if (stateFile) {
|
||||
let dest = currentProfileDir.clone();
|
||||
dest.append("datareporting");
|
||||
dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE,
|
||||
FileUtils.PERMS_DIRECTORY);
|
||||
stateFile.copyTo(dest, "");
|
||||
|
||||
if (!haveStateFile) {
|
||||
// Fall back to migrating the state file that contains the client id from healthreport/.
|
||||
// We first moved the client id management from the FHR implementation to the datareporting
|
||||
// service.
|
||||
// Consequently, we try to migrate an existing FHR state file here as a fallback.
|
||||
let subdir = this._getFileObject(sourceProfileDir, "healthreport");
|
||||
if (subdir && subdir.isDirectory()) {
|
||||
let stateFile = this._getFileObject(subdir, "state.json");
|
||||
if (stateFile) {
|
||||
let dest = createSubDir("healthreport");
|
||||
stateFile.copyTo(dest, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aCallback(true);
|
||||
}
|
||||
}
|
||||
|
||||
return [places, cookies, passwords, formData, dictionary, bookmarksBackups,
|
||||
session, times, healthReporter].filter(r => r);
|
||||
session, times, telemetry].filter(r => r);
|
||||
};
|
||||
|
||||
Object.defineProperty(FirefoxProfileMigrator.prototype, "startupOnlyMigrator", {
|
||||
|
|
|
@ -77,6 +77,13 @@ function writeToFile(dir, leafName, contents) {
|
|||
outputStream.close();
|
||||
}
|
||||
|
||||
function createSubDir(dir, subDirName) {
|
||||
let subDir = dir.clone();
|
||||
subDir.append(subDirName);
|
||||
subDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
return subDir;
|
||||
}
|
||||
|
||||
function promiseMigrator(name, srcDir, targetDir) {
|
||||
let migrator = Cc["@mozilla.org/profile/migrator;1?app=browser&type=firefox"]
|
||||
.createInstance(Ci.nsISupports)
|
||||
|
@ -92,150 +99,168 @@ function promiseMigrator(name, srcDir, targetDir) {
|
|||
throw new Error("failed to find the " + name + " migrator");
|
||||
}
|
||||
|
||||
function promiseFHRMigrator(srcDir, targetDir) {
|
||||
return promiseMigrator("healthreporter", srcDir, targetDir);
|
||||
function promiseTelemetryMigrator(srcDir, targetDir) {
|
||||
return promiseMigrator("telemetry", srcDir, targetDir);
|
||||
}
|
||||
|
||||
add_task(function* test_empty() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
let ok = yield promiseTelemetryMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true with empty directories");
|
||||
// check both are empty
|
||||
checkDirectoryContains(srcDir, {});
|
||||
checkDirectoryContains(targetDir, {});
|
||||
});
|
||||
|
||||
add_task(function* test_just_sqlite() {
|
||||
add_task(function* test_migrate_files() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
let contents = "hello there\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite", contents);
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true with sqlite file copied");
|
||||
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport.sqlite": contents,
|
||||
// Set up datareporting files, some to copy, some not.
|
||||
let stateContent = JSON.stringify({
|
||||
clientId: "68d5474e-19dc-45c1-8e9a-81fca592707c",
|
||||
});
|
||||
});
|
||||
let sessionStateContent = "foobar 5432";
|
||||
let subDir = createSubDir(srcDir, "datareporting");
|
||||
writeToFile(subDir, "state.json", stateContent);
|
||||
writeToFile(subDir, "session-state.json", sessionStateContent);
|
||||
writeToFile(subDir, "other.file", "do not copy");
|
||||
|
||||
add_task(function* test_sqlite_extras() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
let archived = createSubDir(subDir, "archived");
|
||||
writeToFile(archived, "other.file", "do not copy");
|
||||
|
||||
let contents_sqlite = "hello there\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite", contents_sqlite);
|
||||
// Set up FHR files, they should not be copied.
|
||||
writeToFile(srcDir, "healthreport.sqlite", "do not copy");
|
||||
writeToFile(srcDir, "healthreport.sqlite-wal", "do not copy");
|
||||
subDir = createSubDir(srcDir, "healthreport");
|
||||
writeToFile(subDir, "state.json", "do not copy");
|
||||
writeToFile(subDir, "other.file", "do not copy");
|
||||
|
||||
let contents_wal = "this is the wal\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite-wal", contents_wal);
|
||||
|
||||
// and the -shm - this should *not* be copied.
|
||||
writeToFile(srcDir, "healthreport.sqlite-shm", "whatever");
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true with sqlite file copied");
|
||||
// Perform migration.
|
||||
let ok = yield promiseTelemetryMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true with important telemetry files copied");
|
||||
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport.sqlite": contents_sqlite,
|
||||
"healthreport.sqlite-wal": contents_wal,
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_sqlite_healthreport_not_dir() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
let contents = "hello there\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite", contents);
|
||||
writeToFile(srcDir, "healthreport", "I'm a file but should be a directory");
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true even though the directory was a file");
|
||||
// We should have only the sqlite file
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport.sqlite": contents,
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_sqlite_healthreport_empty() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
let contents = "hello there\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite", contents);
|
||||
|
||||
// create an empty 'healthreport' subdir.
|
||||
let subDir = srcDir.clone();
|
||||
subDir.append("healthreport");
|
||||
subDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
// we should end up with the .sqlite file and an empty subdir in the target.
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport.sqlite": contents,
|
||||
"healthreport": {},
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_sqlite_healthreport_contents() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
let contents = "hello there\n\n";
|
||||
writeToFile(srcDir, "healthreport.sqlite", contents);
|
||||
|
||||
// create an empty 'healthreport' subdir.
|
||||
let subDir = srcDir.clone();
|
||||
subDir.append("healthreport");
|
||||
subDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
writeToFile(subDir, "file1", "this is file 1");
|
||||
writeToFile(subDir, "file2", "this is file 2");
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
// we should end up with the .sqlite file and an empty subdir in the target.
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport.sqlite": contents,
|
||||
"healthreport": {
|
||||
"file1": "this is file 1",
|
||||
"file2": "this is file 2",
|
||||
"datareporting": {
|
||||
"state.json": stateContent,
|
||||
"session-state.json": sessionStateContent,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_fallback_fhr_state() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
// Test that we fall back to migrating FHR state if the datareporting
|
||||
// state file does not exist.
|
||||
let stateContent = JSON.stringify({
|
||||
clientId: "68d5474e-19dc-45c1-8e9a-81fca592707c",
|
||||
});
|
||||
let subDir = createSubDir(srcDir, "healthreport");
|
||||
writeToFile(subDir, "state.json", stateContent);
|
||||
|
||||
// Perform migration.
|
||||
let ok = yield promiseTelemetryMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
checkDirectoryContains(targetDir, {
|
||||
"healthreport": {
|
||||
"state.json": stateContent,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
add_task(function* test_datareporting_not_dir() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
writeToFile(srcDir, "datareporting", "I'm a file but should be a directory");
|
||||
|
||||
let ok = yield promiseTelemetryMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true even though the directory was a file");
|
||||
|
||||
checkDirectoryContains(targetDir, {});
|
||||
});
|
||||
|
||||
add_task(function* test_datareporting_empty() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
// create an empty 'datareporting' subdir.
|
||||
let subDir = srcDir.clone();
|
||||
subDir.append("datareporting");
|
||||
subDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
// Migrate with an empty 'datareporting' subdir.
|
||||
let subDir = createSubDir(srcDir, "datareporting");
|
||||
let ok = yield promiseTelemetryMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
// we should end up with nothing at all in the destination - state.json was
|
||||
// missing so we didn't even create the target dir.
|
||||
// We should end up with no migrated files.
|
||||
checkDirectoryContains(targetDir, {
|
||||
"datareporting": {},
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_healthreport_empty() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
// Migrate with no 'datareporting' and an empty 'healthreport' subdir.
|
||||
let subDir = createSubDir(srcDir, "healthreport");
|
||||
let ok = yield promiseTelemetryMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
// We should end up with no migrated files.
|
||||
checkDirectoryContains(targetDir, {});
|
||||
});
|
||||
|
||||
add_task(function* test_datareporting_many() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
// create an empty 'datareporting' subdir.
|
||||
let subDir = srcDir.clone();
|
||||
subDir.append("datareporting");
|
||||
subDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
|
||||
writeToFile(subDir, "state.json", "should be copied");
|
||||
// Create some datareporting files.
|
||||
let subDir = createSubDir(srcDir, "datareporting");
|
||||
let shouldBeCopied = "should be copied";
|
||||
writeToFile(subDir, "state.json", shouldBeCopied);
|
||||
writeToFile(subDir, "session-state.json", shouldBeCopied);
|
||||
writeToFile(subDir, "something.else", "should not");
|
||||
createSubDir(subDir, "emptyDir");
|
||||
|
||||
let ok = yield promiseFHRMigrator(srcDir, targetDir);
|
||||
let ok = yield promiseTelemetryMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
checkDirectoryContains(targetDir, {
|
||||
"datareporting" : {
|
||||
"state.json": "should be copied",
|
||||
"state.json": shouldBeCopied,
|
||||
"session-state.json": shouldBeCopied,
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_no_session_state() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
// Check that migration still works properly if we only have state.json.
|
||||
let subDir = createSubDir(srcDir, "datareporting");
|
||||
let stateContent = "abcd984";
|
||||
writeToFile(subDir, "state.json", stateContent);
|
||||
|
||||
let ok = yield promiseTelemetryMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
checkDirectoryContains(targetDir, {
|
||||
"datareporting" : {
|
||||
"state.json": stateContent,
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_no_state() {
|
||||
let [srcDir, targetDir] = getTestDirs();
|
||||
|
||||
// Check that migration still works properly if we only have session-state.json.
|
||||
let subDir = createSubDir(srcDir, "datareporting");
|
||||
let sessionStateContent = "abcd512";
|
||||
writeToFile(subDir, "session-state.json", sessionStateContent);
|
||||
|
||||
let ok = yield promiseTelemetryMigrator(srcDir, targetDir);
|
||||
Assert.ok(ok, "callback should have been true");
|
||||
|
||||
checkDirectoryContains(targetDir, {
|
||||
"datareporting" : {
|
||||
"session-state.json": sessionStateContent,
|
||||
}
|
||||
});
|
||||
});
|
|
@ -12,7 +12,7 @@ skip-if = os != "mac" # Relies on ULibDir
|
|||
[test_Chrome_passwords.js]
|
||||
skip-if = os != "win"
|
||||
[test_Edge_availability.js]
|
||||
[test_fx_fhr.js]
|
||||
[test_fx_telemetry.js]
|
||||
[test_IE_bookmarks.js]
|
||||
skip-if = os != "win"
|
||||
[test_IE_cookies.js]
|
||||
|
|
|
@ -11,15 +11,20 @@ function retrieveUserContextId(browser) {
|
|||
|
||||
add_task(function() {
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
let tab = gBrowser.addTab("about:blank");
|
||||
let tab = gBrowser.addTab("http://example.com/", {userContextId: i});
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
yield promiseBrowserLoaded(browser);
|
||||
yield promiseTabState(tab, { userContextId: i, entries: [{ url: "http://example.com/" }] });
|
||||
|
||||
let userContextId = yield retrieveUserContextId(browser);
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
let browser2 = tab2.linkedBrowser;
|
||||
yield promiseTabRestored(tab2)
|
||||
|
||||
let userContextId = yield retrieveUserContextId(browser2);
|
||||
is(userContextId, i, "The docShell has the correct userContextId");
|
||||
|
||||
yield promiseRemoveTab(tab);
|
||||
yield promiseRemoveTab(tab2);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<!ENTITY safeb.palm.decline.label "Ignore this warning">
|
||||
<!ENTITY safeb.palm.notforgery.label2 "This isn't a web forgery…">
|
||||
<!ENTITY safeb.palm.reportPage.label "Why was this page blocked?">
|
||||
<!ENTITY safeb.palm.whyForbidden.label "Why was this page blocked?">
|
||||
|
||||
<!ENTITY safeb.blocked.malwarePage.title "Reported Attack Page!">
|
||||
<!-- Localization note (safeb.blocked.malwarePage.shortDesc) - Please don't translate the contents of the <span id="malware_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
|
@ -22,7 +23,7 @@
|
|||
<!ENTITY safeb.blocked.phishingPage.shortDesc "This web page at <span id='phishing_sitename'/> has been reported as a web forgery and has been blocked based on your security preferences.">
|
||||
<!ENTITY safeb.blocked.phishingPage.longDesc "<p>Web forgeries are designed to trick you into revealing personal or financial information by imitating sources you may trust.</p><p>Entering any information on this web page may result in identity theft or other fraud.</p>">
|
||||
|
||||
<!ENTITY safeb.blocked.forbiddenPage.title "Forbidden Site">
|
||||
<!-- Localization note (safeb.blocked.forbiddenPage.shortDesc) - Please don't translate the contents of the <span id="forbidden_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!ENTITY safeb.blocked.forbiddenPage.shortDesc "This Web page at <span id='forbidden_sitename'/> has been blocked based on your browser configuration.">
|
||||
<!ENTITY safeb.blocked.forbiddenPage.title2 "Blocked Site">
|
||||
<!-- Localization note (safeb.blocked.forbiddenPage.shortDesc2) - Please don't translate the contents of the <span id="forbidden_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!ENTITY safeb.blocked.forbiddenPage.shortDesc2 "The Web page at <span id='forbidden_sitename'/> has been blocked by your admin profile.">
|
||||
|
||||
|
|
|
@ -26,5 +26,9 @@ DIRS += [
|
|||
if CONFIG['MAKENSISU']:
|
||||
DIRS += ['installer/windows']
|
||||
|
||||
TEST_DIRS += [
|
||||
'tools/mozscreenshots',
|
||||
]
|
||||
|
||||
DIST_SUBDIR = 'browser'
|
||||
export('DIST_SUBDIR')
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
[DEFAULT]
|
||||
subsuite = screenshots
|
||||
support-files =
|
||||
head.js
|
||||
|
||||
[browser_screenshots.js]
|
||||
tags = screenshots
|
|
@ -0,0 +1,18 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
|
||||
add_task(function* test() {
|
||||
let { TestRunner } = Cu.import("chrome://mozscreenshots/content/TestRunner.jsm", {});
|
||||
let sets = ["TabsInTitlebar", "Tabs", "WindowSize", "Toolbars", "LightweightThemes"];
|
||||
let setsEnv = env.get("MOZSCREENSHOTS_SETS");
|
||||
if (setsEnv) {
|
||||
sets = setsEnv.trim().split(",");
|
||||
}
|
||||
|
||||
yield TestRunner.start(sets);
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {AddonWatcher} = Cu.import("resource://gre/modules/AddonWatcher.jsm", {});
|
||||
let TestRunner;
|
||||
|
||||
function setup() {
|
||||
requestLongerTimeout(10);
|
||||
|
||||
info("Checking for mozscreenshots extension");
|
||||
AddonManager.getAddonByID("mozscreenshots@mozilla.org", function(aAddon) {
|
||||
isnot(aAddon, null, "The mozscreenshots extension should be installed");
|
||||
AddonWatcher.ignoreAddonPermanently(aAddon.id);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(setup);
|
|
@ -0,0 +1,11 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['browser.ini']
|
||||
|
||||
TEST_DIRS += [
|
||||
'mozscreenshots/extension',
|
||||
]
|
|
@ -0,0 +1,12 @@
|
|||
# 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/.
|
||||
|
||||
TEST_EXTENSIONS_DIR = $(DEPTH)/_tests/testing/mochitest/extensions
|
||||
GENERATED_DIRS = $(TEST_EXTENSIONS_DIR)
|
||||
XPI_PKGNAME = mozscreenshots@mozilla.org
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
(cd $(DIST)/xpi-stage && tar $(TAR_CREATE_FLAGS) - $(XPI_NAME)) | (cd $(TEST_EXTENSIONS_DIR) && tar -xf -)
|
|
@ -0,0 +1,175 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Screenshot"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
// Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref.
|
||||
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
|
||||
const PREF_LOG_LEVEL = "extensions.mozscreenshots@mozilla.org.loglevel";
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let ConsoleAPI = Cu.import("resource://gre/modules/Console.jsm", {}).ConsoleAPI;
|
||||
let consoleOptions = {
|
||||
maxLogLevel: "info",
|
||||
maxLogLevelPref: PREF_LOG_LEVEL,
|
||||
prefix: "mozscreenshots",
|
||||
};
|
||||
return new ConsoleAPI(consoleOptions);
|
||||
});
|
||||
|
||||
let Screenshot = {
|
||||
_extensionPath: null,
|
||||
_path: null,
|
||||
_imagePrefix: "",
|
||||
_imageExtension: ".png",
|
||||
_screenshotFunction: null,
|
||||
|
||||
init(path, extensionPath, imagePrefix = "") {
|
||||
this._path = path;
|
||||
|
||||
let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
dir.initWithPath(this._path);
|
||||
if (!dir.exists()) {
|
||||
dir.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
|
||||
}
|
||||
|
||||
this._extensionPath = extensionPath;
|
||||
this._imagePrefix = imagePrefix;
|
||||
switch (Services.appinfo.OS) {
|
||||
case "WINNT":
|
||||
this._screenshotFunction = this._screenshotWindows;
|
||||
break;
|
||||
case "Darwin":
|
||||
this._screenshotFunction = this._screenshotOSX;
|
||||
break;
|
||||
case "Linux":
|
||||
this._screenshotFunction = this._screenshotLinux;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported operating system");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_buildImagePath(baseName) {
|
||||
return OS.Path.join(this._path, this._imagePrefix + baseName + this._imageExtension);
|
||||
},
|
||||
|
||||
// Capture the whole screen using an external application.
|
||||
captureExternal(filename) {
|
||||
let imagePath = this._buildImagePath(filename);
|
||||
return this._screenshotFunction(imagePath).then(() => {
|
||||
log.debug("saved screenshot: " + filename);
|
||||
});
|
||||
},
|
||||
|
||||
///// helpers /////
|
||||
|
||||
_screenshotWindows(filename) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let exe = Services.dirsvc.get("GreBinD", Ci.nsIFile);
|
||||
exe.append("screenshot.exe");
|
||||
if (!exe.exists()) {
|
||||
exe = this._extensionPath.QueryInterface(Ci.nsIFileURL).file;
|
||||
exe.append("lib");
|
||||
exe.append("screenshot.exe");
|
||||
}
|
||||
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
|
||||
process.init(exe);
|
||||
|
||||
let args = [filename];
|
||||
process.runAsync(args, args.length, this._processObserver(resolve, reject));
|
||||
});
|
||||
},
|
||||
|
||||
_screenshotOSX: Task.async(function*(filename) {
|
||||
let screencapture = (windowID = null) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Get the screencapture executable
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.initWithPath("/usr/sbin/screencapture");
|
||||
|
||||
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
|
||||
process.init(file);
|
||||
|
||||
// Run the process.
|
||||
let args = ["-x", "-t", "png"];
|
||||
// Darwin version number for OS X 10.6 is 10.x
|
||||
if (windowID && Services.sysinfo.getProperty("version").indexOf("10.") !== 0) {
|
||||
// Capture only that window on 10.7+
|
||||
args.push("-l");
|
||||
args.push(windowID);
|
||||
}
|
||||
args.push(filename);
|
||||
process.runAsync(args, args.length, this._processObserver(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
function readWindowID() {
|
||||
let decoder = new TextDecoder();
|
||||
let promise = OS.File.read("/tmp/mozscreenshots-windowid");
|
||||
return promise.then(function onSuccess(array) {
|
||||
return decoder.decode(array);
|
||||
});
|
||||
}
|
||||
|
||||
let promiseWindowID = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Get the window ID of the application (assuming its front-most)
|
||||
let osascript = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
osascript.initWithPath("/bin/bash");
|
||||
|
||||
let osascriptP = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
|
||||
osascriptP.init(osascript);
|
||||
let osaArgs = ["-c", "/usr/bin/osascript -e 'tell application (path to frontmost application as text) to set winID to id of window 1' > /tmp/mozscreenshots-windowid"];
|
||||
osascriptP.runAsync(osaArgs, osaArgs.length, this._processObserver(resolve, reject));
|
||||
});
|
||||
};
|
||||
|
||||
yield promiseWindowID();
|
||||
let windowID = yield readWindowID();
|
||||
yield screencapture(windowID);
|
||||
}),
|
||||
|
||||
_screenshotLinux(filename) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let file = Services.dirsvc.get("GreBinD", Ci.nsIFile);
|
||||
file.append("screentopng");
|
||||
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
|
||||
process.init(file);
|
||||
|
||||
let args = [filename];
|
||||
process.runAsync(args, args.length, this._processObserver(resolve, reject));
|
||||
});
|
||||
},
|
||||
|
||||
_processObserver(resolve, reject) {
|
||||
return {
|
||||
observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "process-finished":
|
||||
try {
|
||||
// Wait 1s after process to resolve
|
||||
setTimeout(resolve, 1000);
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reject(topic);
|
||||
break;
|
||||
};
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
|
@ -0,0 +1,256 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["TestRunner"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
const defaultSetNames = ["TabsInTitlebar", "Tabs", "WindowSize", "Toolbars", "LightweightThemes"];
|
||||
const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
Cu.import("chrome://mozscreenshots/content/Screenshot.jsm");
|
||||
|
||||
// Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref.
|
||||
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
|
||||
const PREF_LOG_LEVEL = "extensions.mozscreenshots@mozilla.org.loglevel";
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let ConsoleAPI = Cu.import("resource://gre/modules/Console.jsm", {}).ConsoleAPI;
|
||||
let consoleOptions = {
|
||||
maxLogLevel: "info",
|
||||
maxLogLevelPref: PREF_LOG_LEVEL,
|
||||
prefix: "mozscreenshots",
|
||||
};
|
||||
return new ConsoleAPI(consoleOptions);
|
||||
});
|
||||
|
||||
this.TestRunner = {
|
||||
combos: null,
|
||||
completedCombos: 0,
|
||||
currentComboIndex: 0,
|
||||
_lastCombo: null,
|
||||
_libDir: null,
|
||||
|
||||
init(extensionPath) {
|
||||
let subDirs = ["mozscreenshots",
|
||||
(new Date()).toISOString().replace(/:/g, "-") + "_" + Services.appinfo.OS];
|
||||
let screenshotPath = FileUtils.getFile("TmpD", subDirs).path;
|
||||
|
||||
const MOZ_UPLOAD_DIR = env.get("MOZ_UPLOAD_DIR");
|
||||
if (MOZ_UPLOAD_DIR) {
|
||||
screenshotPath = MOZ_UPLOAD_DIR;
|
||||
}
|
||||
|
||||
log.info("Saving screenshots to:", screenshotPath);
|
||||
log.debug("TestRunner.init");
|
||||
|
||||
let screenshotPrefix = Services.appinfo.appBuildID + "_";
|
||||
Screenshot.init(screenshotPath, extensionPath, screenshotPrefix);
|
||||
this._libDir = extensionPath.QueryInterface(Ci.nsIFileURL).file.clone();
|
||||
this._libDir.append("chrome");
|
||||
this._libDir.append("mozscreenshots");
|
||||
this._libDir.append("lib");
|
||||
|
||||
// Setup some prefs
|
||||
Services.prefs.setCharPref("browser.aboutHomeSnippets.updateUrl", "data:");
|
||||
Services.prefs.setCharPref("extensions.ui.lastCategory", "addons://list/extension");
|
||||
// Don't let the caret blink since it causes false positives for image diffs
|
||||
Services.prefs.setIntPref("ui.caretBlinkTime", -1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Load specified sets, execute all combinations of them, and capture screenshots.
|
||||
*/
|
||||
start(setNames = null) {
|
||||
setNames = setNames || defaultSetNames;
|
||||
let sets = this.loadSets(setNames);
|
||||
|
||||
log.info(sets.length + " sets:", setNames);
|
||||
this.combos = new LazyProduct(sets);
|
||||
log.info(this.combos.length + " combinations");
|
||||
|
||||
this.currentComboIndex = this.completedCombos = 0;
|
||||
this._lastCombo = null;
|
||||
|
||||
return Task.spawn(function* doStart() {
|
||||
for (let i = 0; i < this.combos.length;
|
||||
i++){
|
||||
this.currentComboIndex = i;
|
||||
yield* this._performCombo(this.combos.item(this.currentComboIndex));
|
||||
}
|
||||
|
||||
log.info("Done: Completed " + this.completedCombos + " out of " +
|
||||
this.combos.length + " configurations.");
|
||||
this.cleanup();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Load sets of configurations from JSMs.
|
||||
* @param {String[]} setNames - array of set names (e.g. ["Tabs", "WindowSize"].
|
||||
* @return {Object[]} Array of sets containing `name` and `configurations` properties.
|
||||
*/
|
||||
loadSets(setNames) {
|
||||
let sets = [];
|
||||
for (let setName of setNames) {
|
||||
try {
|
||||
let imported = {};
|
||||
Cu.import("chrome://mozscreenshots/content/configurations/" + setName + ".jsm",
|
||||
imported);
|
||||
imported[setName].init(this._libDir);
|
||||
let configurationNames = Object.keys(imported[setName].configurations);
|
||||
if (!configurationNames.length) {
|
||||
throw new Error(setName + " has no configurations for this environment");
|
||||
}
|
||||
for (let config of configurationNames) {
|
||||
// Automatically set the name property of the configuration object to
|
||||
// its name from the configuration object.
|
||||
imported[setName].configurations[config].name = config;
|
||||
}
|
||||
sets.push(imported[setName].configurations);
|
||||
} catch (ex) {
|
||||
log.error("Error loading set: " + setName);
|
||||
log.error(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
return sets;
|
||||
},
|
||||
|
||||
cleanup() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
}
|
||||
gBrowser.unpinTab(gBrowser.selectedTab);
|
||||
gBrowser.selectedBrowser.loadURI("data:text/html;charset=utf-8,<h1>Done!");
|
||||
browserWindow.restore();
|
||||
},
|
||||
|
||||
///// helpers /////
|
||||
|
||||
_performCombo: function*(combo) {
|
||||
let paddedComboIndex = padLeft(this.currentComboIndex + 1, String(this.combos.length).length);
|
||||
log.info("Combination " + paddedComboIndex + "/" + this.combos.length + ": " +
|
||||
this._comboName(combo).substring(1));
|
||||
|
||||
function changeConfig(config) {
|
||||
log.debug("calling " + config.name);
|
||||
let promise = config.applyConfig();
|
||||
log.debug("called " + config.name);
|
||||
return promise;
|
||||
}
|
||||
|
||||
try {
|
||||
// First go through and actually apply all of the configs
|
||||
for (let i = 0; i < combo.length; i++) {
|
||||
let config = combo[i];
|
||||
if (!this._lastCombo || config !== this._lastCombo[i]) {
|
||||
log.debug("promising", config.name);
|
||||
yield changeConfig(config);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the lastCombo since it's now been applied regardless of whether it's accepted below.
|
||||
log.debug("fulfilled all applyConfig so setting lastCombo.");
|
||||
this._lastCombo = combo;
|
||||
|
||||
// Then ask configs if the current setup is valid. We can't can do this in
|
||||
// the applyConfig methods of the config since it doesn't know what configs
|
||||
// later in the loop will do that may invalidate the combo.
|
||||
for (let i = 0; i < combo.length; i++) {
|
||||
let config = combo[i];
|
||||
// A configuration can specify an optional verifyConfig method to indicate
|
||||
// if the current config is valid for a screenshot. This gets called even
|
||||
// if the this config was used in the lastCombo since another config may
|
||||
// have invalidated it.
|
||||
if (config.verifyConfig) {
|
||||
log.debug("checking if the combo is valid with", config.name);
|
||||
yield config.verifyConfig();
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
log.warn("\tskipped configuration: " + ex);
|
||||
// Don't set lastCombo here so that we properly know which configurations
|
||||
// need to be applied since the last screenshot
|
||||
|
||||
// Return so we don't take a screenshot.
|
||||
return;
|
||||
}
|
||||
|
||||
yield this._onConfigurationReady(combo);
|
||||
},
|
||||
|
||||
_onConfigurationReady(combo) {
|
||||
let delayedScreenshot = () => {
|
||||
let filename = padLeft(this.currentComboIndex + 1,
|
||||
String(this.combos.length).length) + this._comboName(combo);
|
||||
return Screenshot.captureExternal(filename)
|
||||
.then(() => {
|
||||
this.completedCombos++;
|
||||
});
|
||||
};
|
||||
|
||||
log.debug("_onConfigurationReady");
|
||||
return Task.spawn(delayedScreenshot);
|
||||
},
|
||||
|
||||
_comboName(combo) {
|
||||
return combo.reduce(function(a, b) {
|
||||
return a + "_" + b.name;
|
||||
}, "");
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to lazily compute the Cartesian product of all of the sets of configurations.
|
||||
**/
|
||||
function LazyProduct(sets) {
|
||||
/**
|
||||
* An entry for each set with the value being:
|
||||
* [the number of permutations of the sets with lower index,
|
||||
* the number of items in the set at the index]
|
||||
*/
|
||||
this.sets = sets;
|
||||
this.lookupTable = [];
|
||||
let combinations = 1;
|
||||
for (let i = this.sets.length - 1; i >= 0; i--) {
|
||||
let set = this.sets[i];
|
||||
let setLength = Object.keys(set).length;
|
||||
this.lookupTable[i] = [combinations, setLength];
|
||||
combinations *= setLength;
|
||||
}
|
||||
}
|
||||
LazyProduct.prototype = {
|
||||
get length() {
|
||||
let last = this.lookupTable[0];
|
||||
if (!last)
|
||||
return 0;
|
||||
return last[0] * last[1];
|
||||
},
|
||||
|
||||
item(n) {
|
||||
// For set i, get the item from the set with the floored value of
|
||||
// (n / the number of permutations of the sets already chosen from) modulo the length of set i
|
||||
let result = [];
|
||||
for (let i = this.sets.length - 1; i >= 0; i--) {
|
||||
let priorCombinations = this.lookupTable[i][0];
|
||||
let setLength = this.lookupTable[i][1];
|
||||
let keyIndex = Math.floor(n / priorCombinations) % setLength;
|
||||
let keys = Object.keys(this.sets[i]);
|
||||
result[i] = this.sets[i][keys[keyIndex]];
|
||||
}
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
||||
function padLeft(number, width, padding = "0") {
|
||||
return padding.repeat(Math.max(0, width - String(number).length)) + number;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
#if 0
|
||||
Workaround a build system bug where this file doesn't get packaged if not pre-processed.
|
||||
#endif
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TestRunner",
|
||||
"chrome://mozscreenshots/content/TestRunner.jsm");
|
||||
|
||||
function install(data, reason) {
|
||||
if (!isAppSupported()) {
|
||||
uninstallExtension(data);
|
||||
return;
|
||||
}
|
||||
|
||||
AddonManager.getAddonByID(data.id, function(addon) {
|
||||
// Enable on install in case the user disabled a prior version
|
||||
if (addon) {
|
||||
addon.userDisabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function startup(data, reason) {
|
||||
if (!isAppSupported()) {
|
||||
uninstallExtension(data);
|
||||
return;
|
||||
}
|
||||
|
||||
AddonManager.getAddonByID(data.id, function(addon) {
|
||||
let extensionPath = addon.getResourceURI();
|
||||
TestRunner.init(extensionPath);
|
||||
});
|
||||
}
|
||||
|
||||
function shutdown(data, reason) { }
|
||||
|
||||
function uninstall(data, reason) { }
|
||||
|
||||
/**
|
||||
* @return boolean whether the test suite applies to the application.
|
||||
*/
|
||||
function isAppSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function uninstallExtension(data) {
|
||||
AddonManager.getAddonByID(data.id, function(addon) {
|
||||
addon.uninstall();
|
||||
});
|
||||
}
|
||||
|
||||
function startRun() {
|
||||
let env = Cc["@mozilla.org/process/environment;1"]
|
||||
.getService(Ci.nsIEnvironment);
|
||||
let setsEnv = env.get("MOZSCREENSHOTS_SETS");
|
||||
let sets = setsEnv ? setsEnv.split(",") : null;
|
||||
TestRunner.start(sets);
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["AppMenu"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.AppMenu = {
|
||||
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
appMenuClosed: {
|
||||
applyConfig: Task.async(function*() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.PanelUI.hide();
|
||||
}),
|
||||
},
|
||||
|
||||
appMenuMainView: {
|
||||
applyConfig() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let promise = browserWindow.PanelUI.show();
|
||||
browserWindow.PanelUI.showMainView();
|
||||
return promise;
|
||||
},
|
||||
},
|
||||
|
||||
appMenuHistorySubview: {
|
||||
applyConfig() {
|
||||
// History has a footer
|
||||
if (isCustomizing()) {
|
||||
return Promise.reject("Can't show subviews while customizing");
|
||||
}
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let promise = browserWindow.PanelUI.show();
|
||||
return promise.then(() => {
|
||||
browserWindow.PanelUI.showMainView();
|
||||
browserWindow.document.getElementById("history-panelmenu").click();
|
||||
});
|
||||
},
|
||||
|
||||
verifyConfig: verifyConfigHelper,
|
||||
},
|
||||
|
||||
appMenuHelpSubview: {
|
||||
applyConfig() {
|
||||
if (isCustomizing()) {
|
||||
return Promise.reject("Can't show subviews while customizing");
|
||||
}
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let promise = browserWindow.PanelUI.show();
|
||||
return promise.then(() => {
|
||||
browserWindow.PanelUI.showMainView();
|
||||
browserWindow.document.getElementById("PanelUI-help").click();
|
||||
});
|
||||
},
|
||||
|
||||
verifyConfig: verifyConfigHelper,
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
function verifyConfigHelper() {
|
||||
if (isCustomizing()) {
|
||||
return Promise.reject("AppMenu verifyConfigHelper");
|
||||
}
|
||||
return Promise.resolve("AppMenu verifyConfigHelper");
|
||||
}
|
||||
|
||||
function isCustomizing() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.document.documentElement.hasAttribute("customizing")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Buttons"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource:///modules/CustomizableUI.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.Buttons = {
|
||||
|
||||
init(libDir) {
|
||||
createWidget();
|
||||
},
|
||||
|
||||
configurations: {
|
||||
navBarButtons: {
|
||||
applyConfig: Task.async(() =>{
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
CustomizableUI.addWidgetToArea("screenshot-widget", CustomizableUI.AREA_NAVBAR);
|
||||
}),
|
||||
},
|
||||
|
||||
tabsToolbarButtons: {
|
||||
applyConfig: Task.async(() => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
CustomizableUI.addWidgetToArea("screenshot-widget", CustomizableUI.AREA_TABSTRIP);
|
||||
}),
|
||||
},
|
||||
|
||||
menuPanelButtons: {
|
||||
applyConfig: Task.async(() => {
|
||||
CustomizableUI.addWidgetToArea("screenshot-widget", CustomizableUI.AREA_PANEL);
|
||||
}),
|
||||
|
||||
verifyConfig() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.PanelUI.panel.state == "closed") {
|
||||
return Promise.reject("The button isn't shown when the panel isn't open.");
|
||||
}
|
||||
return Promise.resolve("menuPanelButtons.verifyConfig");
|
||||
},
|
||||
},
|
||||
|
||||
custPaletteButtons: {
|
||||
applyConfig: Task.async(() => {
|
||||
CustomizableUI.removeWidgetFromArea("screenshot-widget");
|
||||
}),
|
||||
|
||||
verifyConfig() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.document.documentElement.getAttribute("customizing") != "true") {
|
||||
return Promise.reject("The button isn't shown when we're not in customize mode.");
|
||||
}
|
||||
return Promise.resolve("custPaletteButtons.verifyConfig");
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function createWidget() {
|
||||
let id = "screenshot-widget";
|
||||
let spec = {
|
||||
id: id,
|
||||
label: "My Button",
|
||||
removable: true,
|
||||
tooltiptext: "",
|
||||
type: "button",
|
||||
};
|
||||
CustomizableUI.createWidget(spec);
|
||||
|
||||
// Append a <style> for the image
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let st = browserWindow.document.createElementNS("http://www.w3.org/1999/xhtml", "style");
|
||||
let styles = "" +
|
||||
"#screenshot-widget > .toolbarbutton-icon {" +
|
||||
" list-style-image: url(chrome://browser/skin/Toolbar.png);" +
|
||||
" -moz-image-region: rect(0px, 18px, 18px, 0px);" +
|
||||
"}";
|
||||
st.appendChild(browserWindow.document.createTextNode(styles));
|
||||
browserWindow.document.documentElement.appendChild(st);
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["CustomizeMode"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
this.CustomizeMode = {
|
||||
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
notCustomizing: {
|
||||
applyConfig() {
|
||||
return new Promise((resolve) => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (!browserWindow.document.documentElement.hasAttribute("customizing")) {
|
||||
resolve("notCustomizing: already not customizing");
|
||||
return;
|
||||
}
|
||||
function onCustomizationEnds() {
|
||||
browserWindow.gNavToolbox.removeEventListener("aftercustomization",
|
||||
onCustomizationEnds);
|
||||
// Wait for final changes
|
||||
setTimeout(() => resolve("notCustomizing: onCustomizationEnds"), 500);
|
||||
}
|
||||
browserWindow.gNavToolbox.addEventListener("aftercustomization",
|
||||
onCustomizationEnds);
|
||||
browserWindow.gCustomizeMode.exit();
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
customizing: {
|
||||
applyConfig() {
|
||||
return new Promise((resolve) => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.document.documentElement.hasAttribute("customizing")) {
|
||||
resolve("customizing: already customizing");
|
||||
return;
|
||||
}
|
||||
function onCustomizing() {
|
||||
browserWindow.gNavToolbox.removeEventListener("customizationready",
|
||||
onCustomizing);
|
||||
// Wait for final changes
|
||||
setTimeout(() => resolve("customizing: onCustomizing"), 500);
|
||||
}
|
||||
browserWindow.gNavToolbox.addEventListener("customizationready",
|
||||
onCustomizing);
|
||||
browserWindow.gCustomizeMode.enter();
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DevEdition"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
const THEME_ID = "firefox-devedition@mozilla.org";
|
||||
|
||||
Cu.import("resource://gre/modules/LightweightThemeManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.DevEdition = {
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
devEditionLight: {
|
||||
applyConfig: Task.async(() => {
|
||||
Services.prefs.setCharPref("devtools.theme", "light");
|
||||
LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme(THEME_ID);
|
||||
Services.prefs.setBoolPref("browser.devedition.theme.showCustomizeButton", true);
|
||||
}),
|
||||
},
|
||||
devEditionDark: {
|
||||
applyConfig: Task.async(() => {
|
||||
Services.prefs.setCharPref("devtools.theme", "dark");
|
||||
LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme(THEME_ID);
|
||||
Services.prefs.setBoolPref("browser.devedition.theme.showCustomizeButton", true);
|
||||
}),
|
||||
},
|
||||
devEditionOff: {
|
||||
applyConfig: Task.async(() => {
|
||||
Services.prefs.clearUserPref("devtools.theme");
|
||||
LightweightThemeManager.currentTheme = null;
|
||||
Services.prefs.clearUserPref("browser.devedition.theme.showCustomizeButton");
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
|
@ -0,0 +1,50 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DevTools"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://devtools/client/framework/gDevTools.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let TargetFactory = devtools.TargetFactory;
|
||||
|
||||
function getTargetForSelectedTab() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let target = TargetFactory.forTab(browserWindow.gBrowser.selectedTab);
|
||||
return target;
|
||||
}
|
||||
|
||||
this.DevTools = {
|
||||
init(libDir) {
|
||||
let panels = ["options", "webconsole", "inspector", "jsdebugger", "netmonitor"];
|
||||
panels.forEach(panel => {
|
||||
this.configurations[panel] = {};
|
||||
this.configurations[panel].applyConfig = () => {
|
||||
return gDevTools.showToolbox(getTargetForSelectedTab(), panel, "bottom");
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
configurations: {
|
||||
bottomToolbox: {
|
||||
applyConfig() {
|
||||
return gDevTools.showToolbox(getTargetForSelectedTab(), "inspector", "bottom");
|
||||
},
|
||||
},
|
||||
sideToolbox: {
|
||||
applyConfig() {
|
||||
return gDevTools.showToolbox(getTargetForSelectedTab(), "inspector", "side");
|
||||
},
|
||||
},
|
||||
undockedToolbox: {
|
||||
applyConfig() {
|
||||
return gDevTools.showToolbox(getTargetForSelectedTab(), "inspector", "window");
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
|
@ -0,0 +1,92 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["LightweightThemes"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/LightweightThemeManager.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
this.LightweightThemes = {
|
||||
init(libDir) {
|
||||
// convert -size 3000x200 canvas:black black_theme.png
|
||||
let blackImage = libDir.clone();
|
||||
blackImage.append("black_theme.png");
|
||||
this._blackImageURL = Services.io.newFileURI(blackImage).spec;
|
||||
|
||||
// convert -size 3000x200 canvas:white white_theme.png
|
||||
let whiteImage = libDir.clone();
|
||||
whiteImage.append("white_theme.png");
|
||||
this._whiteImageURL = Services.io.newFileURI(whiteImage).spec;
|
||||
},
|
||||
|
||||
configurations: {
|
||||
noLWT: {
|
||||
applyConfig: Task.async(function*() {
|
||||
LightweightThemeManager.currentTheme = null;
|
||||
}),
|
||||
},
|
||||
|
||||
darkLWT: {
|
||||
applyConfig() {
|
||||
LightweightThemeManager.setLocalTheme({
|
||||
id: "black",
|
||||
name: "black",
|
||||
headerURL: LightweightThemes._blackImageURL,
|
||||
footerURL: LightweightThemes._blackImageURL,
|
||||
textcolor: "#ffffff",
|
||||
accentcolor: "#111111",
|
||||
});
|
||||
|
||||
// Wait for LWT listener
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve("darkLWT");
|
||||
}, 500);
|
||||
});
|
||||
},
|
||||
|
||||
verifyConfig: verifyConfigHelper,
|
||||
},
|
||||
|
||||
lightLWT: {
|
||||
applyConfig() {
|
||||
LightweightThemeManager.setLocalTheme({
|
||||
id: "white",
|
||||
name: "white",
|
||||
headerURL: LightweightThemes._whiteImageURL,
|
||||
footerURL: LightweightThemes._whiteImageURL,
|
||||
textcolor: "#000000",
|
||||
accentcolor: "#eeeeee",
|
||||
});
|
||||
// Wait for LWT listener
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve("lightLWT");
|
||||
}, 500);
|
||||
});
|
||||
},
|
||||
|
||||
verifyConfig: verifyConfigHelper,
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
function verifyConfigHelper() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.document.documentElement.hasAttribute("lwtheme")) {
|
||||
resolve("verifyConfigHelper");
|
||||
} else {
|
||||
reject("The @lwtheme attribute wasn't present so themes may not be available");
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Preferences"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
this.Preferences = {
|
||||
|
||||
init(libDir) {
|
||||
Services.prefs.setBoolPref("browser.preferences.inContent", true);
|
||||
|
||||
let panes = [
|
||||
["paneGeneral", null],
|
||||
["paneSearch", null],
|
||||
["paneContent", null],
|
||||
["paneApplications", null],
|
||||
["panePrivacy", null],
|
||||
["paneSecurity", null],
|
||||
["paneSync", null],
|
||||
["paneAdvanced", "generalTab"],
|
||||
["paneAdvanced", "dataChoicesTab"],
|
||||
["paneAdvanced", "networkTab"],
|
||||
["paneAdvanced", "updateTab"],
|
||||
["paneAdvanced", "encryptionTab"],
|
||||
];
|
||||
for (let [primary, advanced] of panes) {
|
||||
let configName = primary + ("-" + advanced || "");
|
||||
this.configurations[configName] = {};
|
||||
this.configurations[configName].applyConfig = prefHelper.bind(null, primary, advanced);
|
||||
}
|
||||
},
|
||||
|
||||
configurations: {},
|
||||
};
|
||||
|
||||
function prefHelper(primary, advanced) {
|
||||
return new Promise((resolve) => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (primary == "paneAdvanced") {
|
||||
browserWindow.openAdvancedPreferences(advanced);
|
||||
} else {
|
||||
browserWindow.openPreferences(primary);
|
||||
}
|
||||
setTimeout(resolve, 50);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Tabs"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
const CUST_TAB = "chrome://browser/skin/customizableui/customizeFavicon.ico";
|
||||
const PREFS_TAB = "chrome://browser/skin/preferences/in-content/favicon.ico";
|
||||
const DEFAULT_FAVICON_TAB = `data:text/html,<meta charset="utf-8">
|
||||
<title>No favicon</title>`;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.Tabs = {
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
fiveTabs: {
|
||||
applyConfig: Task.async(function*() {
|
||||
fiveTabsHelper();
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
hoverTab(browserWindow.gBrowser.tabs[3]);
|
||||
}),
|
||||
},
|
||||
|
||||
fourPinned: {
|
||||
applyConfig: Task.async(function*() {
|
||||
fiveTabsHelper();
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let tab = browserWindow.gBrowser.addTab(PREFS_TAB);
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
tab = browserWindow.gBrowser.addTab(CUST_TAB);
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
tab = browserWindow.gBrowser.addTab("about:privatebrowsing");
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
tab = browserWindow.gBrowser.addTab("about:home");
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
browserWindow.gBrowser.selectTabAtIndex(5);
|
||||
hoverTab(browserWindow.gBrowser.tabs[2]);
|
||||
// also hover the new tab button
|
||||
let newTabButton = browserWindow.document.getAnonymousElementByAttribute(browserWindow.
|
||||
gBrowser.tabContainer, "class", "tabs-newtab-button");
|
||||
hoverTab(newTabButton);
|
||||
browserWindow.gBrowser.tabs[browserWindow.gBrowser.tabs.length - 1].
|
||||
setAttribute("beforehovered", true);
|
||||
}),
|
||||
},
|
||||
|
||||
twoPinnedWithOverflow: {
|
||||
applyConfig: Task.async(function*() {
|
||||
fiveTabsHelper();
|
||||
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.gBrowser.loadTabs([
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
], true, true);
|
||||
let tab = browserWindow.gBrowser.addTab(PREFS_TAB);
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
tab = browserWindow.gBrowser.addTab(CUST_TAB);
|
||||
browserWindow.gBrowser.pinTab(tab);
|
||||
browserWindow.gBrowser.selectTabAtIndex(4);
|
||||
hoverTab(browserWindow.gBrowser.tabs[6]);
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/* helpers */
|
||||
|
||||
function fiveTabsHelper() {
|
||||
// some with no favicon and some with. Selected tab in middle.
|
||||
closeAllButOneTab("about:addons");
|
||||
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.gBrowser.loadTabs([
|
||||
"about:addons",
|
||||
"about:home",
|
||||
DEFAULT_FAVICON_TAB,
|
||||
"about:newtab",
|
||||
CUST_TAB,
|
||||
], true, true);
|
||||
browserWindow.gBrowser.selectTabAtIndex(1);
|
||||
}
|
||||
|
||||
function closeAllButOneTab(url = "about:blank") {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
// Close all tabs except the last so we don't quit the browser.
|
||||
while (gBrowser.tabs.length > 1)
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
gBrowser.selectedBrowser.loadURI(url);
|
||||
if (gBrowser.selectedTab.pinned)
|
||||
gBrowser.unpinTab(gBrowser.selectedTab);
|
||||
let newTabButton = browserWindow.document.getAnonymousElementByAttribute(browserWindow.gBrowser.tabContainer, "class", "tabs-newtab-button");
|
||||
hoverTab(newTabButton, false);
|
||||
}
|
||||
|
||||
function hoverTab(tab, hover = true) {
|
||||
const inIDOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
if (hover) {
|
||||
inIDOMUtils.addPseudoClassLock(tab, ":hover");
|
||||
} else {
|
||||
inIDOMUtils.clearPseudoClassLocks(tab);
|
||||
}
|
||||
// XXX TODO: this isn't necessarily testing what we ship
|
||||
if (tab.nextElementSibling)
|
||||
tab.nextElementSibling.setAttribute("afterhovered", hover || null);
|
||||
if (tab.previousElementSibling)
|
||||
tab.previousElementSibling.setAttribute("beforehovered", hover || null);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["TabsInTitlebar"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
const PREF_TABS_IN_TITLEBAR = "browser.tabs.drawInTitlebar";
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.TabsInTitlebar = {
|
||||
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
tabsInTitlebar: {
|
||||
applyConfig: Task.async(function*() {
|
||||
if (Services.appinfo.OS == "Linux") {
|
||||
return Promise.reject("TabsInTitlebar isn't supported on Linux");
|
||||
}
|
||||
Services.prefs.setBoolPref(PREF_TABS_IN_TITLEBAR, true);
|
||||
}),
|
||||
},
|
||||
|
||||
tabsOutsideTitlebar: {
|
||||
applyConfig: Task.async(function*() {
|
||||
Services.prefs.setBoolPref(PREF_TABS_IN_TITLEBAR, false);
|
||||
}),
|
||||
},
|
||||
|
||||
},
|
||||
};
|
|
@ -0,0 +1,56 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Toolbars"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.Toolbars = {
|
||||
init(libDir) {},
|
||||
|
||||
configurations: {
|
||||
onlyNavBar: {
|
||||
applyConfig: Task.async(function*() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let personalToolbar = browserWindow.document.getElementById("PersonalToolbar");
|
||||
browserWindow.setToolbarVisibility(personalToolbar, false);
|
||||
toggleMenubarIfNecessary(false);
|
||||
}),
|
||||
},
|
||||
|
||||
allToolbars: {
|
||||
applyConfig: Task.async(function*() { // Boookmarks and menubar
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let personalToolbar = browserWindow.document.getElementById("PersonalToolbar");
|
||||
browserWindow.setToolbarVisibility(personalToolbar, true);
|
||||
toggleMenubarIfNecessary(true);
|
||||
}),
|
||||
|
||||
verifyConfig: Task.async(function*() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (browserWindow.fullScreen) {
|
||||
return Promise.reject("The bookmark toolbar and menubar are not shown in fullscreen.");
|
||||
}
|
||||
}),
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
///// helpers /////
|
||||
|
||||
function toggleMenubarIfNecessary(visible) {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
// The menubar is not shown on OS X or while in fullScreen
|
||||
if (Services.appinfo.OS != "Darwin" /*&& !browserWindow.fullScreen*/) {
|
||||
let menubar = browserWindow.document.getElementById("toolbar-menubar");
|
||||
browserWindow.setToolbarVisibility(menubar, visible);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["WindowSize"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
this.WindowSize = {
|
||||
|
||||
init(libDir) {
|
||||
Services.prefs.setBoolPref("browser.fullscreen.autohide", false);
|
||||
},
|
||||
|
||||
configurations: {
|
||||
maximized: {
|
||||
applyConfig: Task.async(function*() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.fullScreen = false;
|
||||
|
||||
// Wait for the Lion fullscreen transition to end as there doesn't seem to be an event
|
||||
// and trying to maximize while still leaving fullscreen doesn't work.
|
||||
yield new Promise((resolve, reject) => {
|
||||
setTimeout(function waitToLeaveFS() {
|
||||
browserWindow.maximize();
|
||||
resolve();
|
||||
}, Services.appinfo.OS == "Darwin" ? 1500 : 0);
|
||||
});
|
||||
}),
|
||||
},
|
||||
|
||||
normal: {
|
||||
applyConfig: Task.async(() => {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.fullScreen = false;
|
||||
browserWindow.restore();
|
||||
}),
|
||||
},
|
||||
|
||||
fullScreen: {
|
||||
applyConfig: Task.async(function*() {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWindow.fullScreen = true;
|
||||
// OS X Lion fullscreen transition takes a while
|
||||
yield new Promise((resolve, reject) => {
|
||||
setTimeout(function waitAfterEnteringFS() {
|
||||
resolve();
|
||||
}, Services.appinfo.OS == "Darwin" ? 1500 : 0);
|
||||
});
|
||||
}),
|
||||
},
|
||||
|
||||
},
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>mozscreenshots@mozilla.org</em:id>
|
||||
#expand <em:version>__MOZILLA_VERSION_U__</em:version>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
|
||||
<!-- for running custom screenshot binaries -->
|
||||
<em:unpack>true</em:unpack>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>mozscreenshots</em:name>
|
||||
<em:description>Take screenshots of Mozilla applications in various UI configurations.</em:description>
|
||||
<em:creator>Mozilla</em:creator>
|
||||
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<!-- Firefox -->
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
#expand <em:minVersion>__MOZILLA_VERSION_U__</em:minVersion>
|
||||
<em:maxVersion>*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
</Description>
|
||||
</RDF>
|
|
@ -0,0 +1,6 @@
|
|||
mozscreenshots.jar:
|
||||
% content mozscreenshots chrome/mozscreenshots/
|
||||
Screenshot.jsm
|
||||
TestRunner.jsm
|
||||
configurations/ (configurations/*.jsm)
|
||||
lib/ (lib/*.png)
|
Двоичные данные
browser/tools/mozscreenshots/mozscreenshots/extension/lib/black_theme.png
Normal file
Двоичные данные
browser/tools/mozscreenshots/mozscreenshots/extension/lib/black_theme.png
Normal file
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 343 B |
Двоичные данные
browser/tools/mozscreenshots/mozscreenshots/extension/lib/white_theme.png
Normal file
Двоичные данные
browser/tools/mozscreenshots/mozscreenshots/extension/lib/white_theme.png
Normal file
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 522 B |
|
@ -0,0 +1,17 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPI_NAME = 'mozscreenshots'
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
USE_EXTENSION_MANIFEST = True
|
||||
NO_JS_MANIFEST = True
|
||||
|
||||
FINAL_TARGET_PP_FILES += [
|
||||
'bootstrap.js',
|
||||
'install.rdf',
|
||||
]
|
|
@ -81,8 +81,6 @@ var CallsListView = Heritage.extend(WidgetMethods, {
|
|||
gutter.appendChild(index);
|
||||
contents.appendChild(gutter);
|
||||
|
||||
// Not all function calls have a caller that was stringified (e.g.
|
||||
// context calls have a "gl" or "ctx" caller preview).
|
||||
if (call.callerPreview) {
|
||||
let context = document.createElement("label");
|
||||
context.className = "plain call-item-context";
|
||||
|
|
|
@ -40,7 +40,7 @@ function* ifTestingSupported() {
|
|||
is(functionCalls[0].line, 25,
|
||||
"The called function's line is correct.");
|
||||
|
||||
is(functionCalls[0].callerPreview, "ctx",
|
||||
is(functionCalls[0].callerPreview, "Object",
|
||||
"The called function's caller preview is correct.");
|
||||
is(functionCalls[0].argsPreview, "0, 0, 128, 128",
|
||||
"The called function's args preview is correct.");
|
||||
|
|
|
@ -41,7 +41,7 @@ function* ifTestingSupported() {
|
|||
"The first called function's line is correct.");
|
||||
is(functionCalls[0].argsPreview, "0, 0, 128, 128",
|
||||
"The first called function's args preview is correct.");
|
||||
is(functionCalls[0].callerPreview, "ctx",
|
||||
is(functionCalls[0].callerPreview, "Object",
|
||||
"The first called function's caller preview is correct.");
|
||||
|
||||
is(functionCalls[6].type, CallWatcherFront.METHOD_FUNCTION,
|
||||
|
@ -54,7 +54,7 @@ function* ifTestingSupported() {
|
|||
"The penultimate called function's line is correct.");
|
||||
is(functionCalls[6].argsPreview, "10, 10, 55, 50",
|
||||
"The penultimate called function's args preview is correct.");
|
||||
is(functionCalls[6].callerPreview, "ctx",
|
||||
is(functionCalls[6].callerPreview, "Object",
|
||||
"The penultimate called function's caller preview is correct.");
|
||||
|
||||
is(functionCalls[7].type, CallWatcherFront.METHOD_FUNCTION,
|
||||
|
@ -67,7 +67,7 @@ function* ifTestingSupported() {
|
|||
"The last called function's line is correct.");
|
||||
ok(functionCalls[7].argsPreview.includes("Function"),
|
||||
"The last called function's args preview is correct.");
|
||||
is(functionCalls[7].callerPreview, "",
|
||||
is(functionCalls[7].callerPreview, "Object",
|
||||
"The last called function's caller preview is correct.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
|
|
|
@ -41,7 +41,7 @@ function* ifTestingSupported() {
|
|||
"The first called function's line is correct.");
|
||||
is(functionCalls[0].argsPreview, "0, 0, 128, 128",
|
||||
"The first called function's args preview is correct.");
|
||||
is(functionCalls[0].callerPreview, "ctx",
|
||||
is(functionCalls[0].callerPreview, "Object",
|
||||
"The first called function's caller preview is correct.");
|
||||
|
||||
is(functionCalls[6].type, CallWatcherFront.METHOD_FUNCTION,
|
||||
|
@ -54,7 +54,7 @@ function* ifTestingSupported() {
|
|||
"The penultimate called function's line is correct.");
|
||||
is(functionCalls[6].argsPreview, "10, 10, 55, 50",
|
||||
"The penultimate called function's args preview is correct.");
|
||||
is(functionCalls[6].callerPreview, "ctx",
|
||||
is(functionCalls[6].callerPreview, "Object",
|
||||
"The penultimate called function's caller preview is correct.");
|
||||
|
||||
is(functionCalls[7].type, CallWatcherFront.METHOD_FUNCTION,
|
||||
|
@ -67,7 +67,7 @@ function* ifTestingSupported() {
|
|||
"The last called function's line is correct.");
|
||||
ok(functionCalls[7].argsPreview.includes("Function"),
|
||||
"The last called function's args preview is correct.");
|
||||
is(functionCalls[7].callerPreview, "",
|
||||
is(functionCalls[7].callerPreview, "Object",
|
||||
"The last called function's caller preview is correct.");
|
||||
|
||||
let firstNonDrawCall = yield functionCalls[1].getDetails();
|
||||
|
|
|
@ -21,22 +21,22 @@ function* ifTestingSupported() {
|
|||
"All the function calls should now be displayed in the UI.");
|
||||
|
||||
testItem(CallsListView.getItemAtIndex(0),
|
||||
"1", "ctx", "clearRect", "(0, 0, 128, 128)", "doc_simple-canvas.html:25");
|
||||
"1", "Object", "clearRect", "(0, 0, 128, 128)", "doc_simple-canvas.html:25");
|
||||
|
||||
testItem(CallsListView.getItemAtIndex(1),
|
||||
"2", "ctx", "fillStyle", " = rgb(192, 192, 192)", "doc_simple-canvas.html:20");
|
||||
"2", "Object", "fillStyle", " = rgb(192, 192, 192)", "doc_simple-canvas.html:20");
|
||||
testItem(CallsListView.getItemAtIndex(2),
|
||||
"3", "ctx", "fillRect", "(0, 0, 128, 128)", "doc_simple-canvas.html:21");
|
||||
"3", "Object", "fillRect", "(0, 0, 128, 128)", "doc_simple-canvas.html:21");
|
||||
|
||||
testItem(CallsListView.getItemAtIndex(3),
|
||||
"4", "ctx", "fillStyle", " = rgba(0, 0, 192, 0.5)", "doc_simple-canvas.html:20");
|
||||
"4", "Object", "fillStyle", " = rgba(0, 0, 192, 0.5)", "doc_simple-canvas.html:20");
|
||||
testItem(CallsListView.getItemAtIndex(4),
|
||||
"5", "ctx", "fillRect", "(30, 30, 55, 50)", "doc_simple-canvas.html:21");
|
||||
"5", "Object", "fillRect", "(30, 30, 55, 50)", "doc_simple-canvas.html:21");
|
||||
|
||||
testItem(CallsListView.getItemAtIndex(5),
|
||||
"6", "ctx", "fillStyle", " = rgba(192, 0, 0, 0.5)", "doc_simple-canvas.html:20");
|
||||
"6", "Object", "fillStyle", " = rgba(192, 0, 0, 0.5)", "doc_simple-canvas.html:20");
|
||||
testItem(CallsListView.getItemAtIndex(6),
|
||||
"7", "ctx", "fillRect", "(10, 10, 55, 50)", "doc_simple-canvas.html:21");
|
||||
"7", "Object", "fillRect", "(10, 10, 55, 50)", "doc_simple-canvas.html:21");
|
||||
|
||||
testItem(CallsListView.getItemAtIndex(7),
|
||||
"8", "", "requestAnimationFrame", "(Function)", "doc_simple-canvas.html:30");
|
||||
|
@ -53,7 +53,7 @@ function* ifTestingSupported() {
|
|||
is($(".call-item-context", item.target).getAttribute("value"), context,
|
||||
"The item's context label has the correct text.");
|
||||
} else {
|
||||
is($(".call-item-context", item.target), null,
|
||||
is($(".call-item-context", item.target) + "", "[object XULElement]",
|
||||
"The item's context label should not be available.");
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ function* ifTestingSupported() {
|
|||
"The visible item's line has the expected value.");
|
||||
is(CallsListView.visibleItems[0].attachment.actor.argsPreview, "0, 0, 128, 128",
|
||||
"The visible item's args have the expected value.");
|
||||
is(CallsListView.visibleItems[0].attachment.actor.callerPreview, "ctx",
|
||||
is(CallsListView.visibleItems[0].attachment.actor.callerPreview, "Object",
|
||||
"The visible item's caller has the expected value.");
|
||||
|
||||
let secondRecordingFinished = once(window, EVENTS.SNAPSHOT_RECORDING_FINISHED);
|
||||
|
|
|
@ -28,7 +28,10 @@ let promise = require("promise");
|
|||
|
||||
const TEST_DIR = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
|
||||
const CHROME_URL_ROOT = TEST_DIR + "/";
|
||||
const URL_ROOT = CHROME_URL_ROOT.replace("chrome://mochitests/content/", "http://example.com/");
|
||||
const URL_ROOT = CHROME_URL_ROOT.replace("chrome://mochitests/content/",
|
||||
"http://example.com/");
|
||||
const URL_ROOT_SSL = CHROME_URL_ROOT.replace("chrome://mochitests/content/",
|
||||
"https://example.com/");
|
||||
|
||||
// All test are asynchronous
|
||||
waitForExplicitFinish();
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
const {PropertyView} =
|
||||
require("devtools/client/inspector/computed/computed");
|
||||
const TEST_URI = TEST_URL_ROOT + "doc_matched_selectors.html";
|
||||
const TEST_URI = URL_ROOT + "doc_matched_selectors.html";
|
||||
|
||||
add_task(function*() {
|
||||
yield addTab(TEST_URI);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
// Tests that we correctly display appropriate media query titles in the
|
||||
// property view.
|
||||
|
||||
const TEST_URI = TEST_URL_ROOT + "doc_media_queries.html";
|
||||
const TEST_URI = URL_ROOT + "doc_media_queries.html";
|
||||
|
||||
var {PropertyView} = require("devtools/client/inspector/computed/computed");
|
||||
var {CssLogic} = require("devtools/shared/inspector/css-logic");
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
// Tests that the computed view shows the original source link when source maps
|
||||
// are enabled.
|
||||
|
||||
const TESTCASE_URI = TEST_URL_ROOT_SSL + "doc_sourcemaps.html";
|
||||
const TESTCASE_URI = URL_ROOT_SSL + "doc_sourcemaps.html";
|
||||
const PREF = "devtools.styleeditor.source-maps-enabled";
|
||||
const SCSS_LOC = "doc_sourcemaps.scss:4";
|
||||
const CSS_LOC = "doc_sourcemaps.css:1";
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
// Tests that pseudoelements are displayed correctly in the rule view.
|
||||
|
||||
const TEST_URI = TEST_URL_ROOT + "doc_pseudoelement.html";
|
||||
const TEST_URI = URL_ROOT + "doc_pseudoelement.html";
|
||||
|
||||
add_task(function*() {
|
||||
yield addTab(TEST_URI);
|
||||
|
|
|
@ -19,7 +19,9 @@ add_task(function*() {
|
|||
|
||||
info("Changing the node's style and waiting for the update");
|
||||
let onUpdated = inspector.once("computed-view-refreshed");
|
||||
getNode("#testdiv").style.cssText = "font-size: 15px; color: red;";
|
||||
// FIXME: use the testActor to set style on the node.
|
||||
content.document.querySelector("#testdiv")
|
||||
.style.cssText = "font-size: 15px; color: red;";
|
||||
yield onUpdated;
|
||||
|
||||
fontSize = getComputedViewPropertyValue(view, "font-size");
|
||||
|
|
|
@ -44,7 +44,7 @@ add_task(function*() {
|
|||
yield checkSelectAll(view);
|
||||
});
|
||||
|
||||
function checkCopySelection(view) {
|
||||
function* checkCopySelection(view) {
|
||||
info("Testing selection copy");
|
||||
|
||||
let contentDocument = view.styleDocument;
|
||||
|
@ -63,16 +63,15 @@ function checkCopySelection(view) {
|
|||
"font-size: 16px;[\\r\\n]+" +
|
||||
"font-variant-caps: small-caps;[\\r\\n]*";
|
||||
|
||||
return waitForClipboard(() => {
|
||||
fireCopyEvent(props[0]);
|
||||
}, () => {
|
||||
return checkClipboardData(expectedPattern);
|
||||
}).then(() => {}, () => {
|
||||
try {
|
||||
yield waitForClipboard(() => fireCopyEvent(props[0]),
|
||||
() => checkClipboardData(expectedPattern));
|
||||
} catch (e) {
|
||||
failedClipboard(expectedPattern);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function checkSelectAll(view) {
|
||||
function* checkSelectAll(view) {
|
||||
info("Testing select-all copy");
|
||||
|
||||
let contentDoc = view.styleDocument;
|
||||
|
@ -86,13 +85,12 @@ function checkSelectAll(view) {
|
|||
"font-size: 16px;[\\r\\n]+" +
|
||||
"font-variant-caps: small-caps;[\\r\\n]*";
|
||||
|
||||
return waitForClipboard(() => {
|
||||
fireCopyEvent(prop);
|
||||
}, () => {
|
||||
return checkClipboardData(expectedPattern);
|
||||
}).then(() => {}, () => {
|
||||
try {
|
||||
yield waitForClipboard(() => fireCopyEvent(prop),
|
||||
() => checkClipboardData(expectedPattern));
|
||||
} catch (e) {
|
||||
failedClipboard(expectedPattern);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function checkClipboardData(expectedPattern) {
|
||||
|
|
|
@ -1,137 +1,31 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
let Cu = Components.utils;
|
||||
let {gDevTools} = Cu.import("resource://devtools/client/framework/gDevTools.jsm", {});
|
||||
let {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
let {TargetFactory} = require("devtools/client/framework/target");
|
||||
let {CssComputedView} =
|
||||
require("devtools/client/inspector/computed/computed");
|
||||
let DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
let promise = require("promise");
|
||||
let {console} =
|
||||
Components.utils.import("resource://gre/modules/Console.jsm", {});
|
||||
// Import the inspector's head.js first (which itself imports shared-head.js).
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/inspector/test/head.js",
|
||||
this);
|
||||
|
||||
// All tests are asynchronous
|
||||
waitForExplicitFinish();
|
||||
|
||||
const TEST_URL_ROOT =
|
||||
"http://example.com/browser/devtools/client/inspector/computed/test/";
|
||||
const TEST_URL_ROOT_SSL =
|
||||
"https://example.com/browser/devtools/client/inspector/computed/test/";
|
||||
const ROOT_TEST_DIR = getRootDirectory(gTestPath);
|
||||
const FRAME_SCRIPT_URL = ROOT_TEST_DIR + "doc_frame_script.js";
|
||||
|
||||
// Auto clean-up when a test ends
|
||||
registerCleanupFunction(function*() {
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
yield gDevTools.closeToolbox(target);
|
||||
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
});
|
||||
|
||||
// Uncomment this pref to dump all devtools emitted events to the console.
|
||||
// Services.prefs.setBoolPref("devtools.dump.emit", true);
|
||||
|
||||
// Set the testing flag on gDevTools and reset it when the test ends
|
||||
DevToolsUtils.testing = true;
|
||||
registerCleanupFunction(() => DevToolsUtils.testing = false);
|
||||
|
||||
// Clean-up all prefs that might have been changed during a test run
|
||||
// (safer here because if the test fails, then the pref is never reverted)
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
|
||||
Services.prefs.clearUserPref("devtools.dump.emit");
|
||||
Services.prefs.clearUserPref("devtools.defaultColorUnit");
|
||||
});
|
||||
|
||||
/**
|
||||
* The functions found below are here to ease test development and maintenance.
|
||||
* Most of these functions are stateless and will require some form of context
|
||||
* (the instance of the current toolbox, or inspector panel for instance).
|
||||
*
|
||||
* Most of these functions are async too and return promises.
|
||||
*
|
||||
* All tests should follow the following pattern:
|
||||
*
|
||||
* add_task(function*() {
|
||||
* yield addTab(TEST_URI);
|
||||
* let {toolbox, inspector, view} = yield openComputedView();
|
||||
*
|
||||
* yield selectNode("#test", inspector);
|
||||
* yield someAsyncTestFunction(view);
|
||||
* });
|
||||
*
|
||||
* add_task is the way to define the testcase in the test file. It accepts
|
||||
* a single generator-function argument.
|
||||
* The generator function should yield any async call.
|
||||
*
|
||||
* There is no need to clean tabs up at the end of a test as this is done
|
||||
* automatically.
|
||||
*
|
||||
* It is advised not to store any references on the global scope. There
|
||||
* shouldn't be a need to anyway. Thanks to add_task, test steps, even
|
||||
* though asynchronous, can be described in a nice flat way, and
|
||||
* if/for/while/... control flow can be used as in sync code, making it
|
||||
* possible to write the outline of the test case all in add_task, and delegate
|
||||
* actual processing and assertions to other functions.
|
||||
* Open the toolbox, with the inspector tool visible, and the computed-view
|
||||
* sidebar tab selected.
|
||||
* @return a promise that resolves when the inspector is ready and the computed
|
||||
* view is visible and ready
|
||||
*/
|
||||
|
||||
/* *********************************************
|
||||
* UTILS
|
||||
* *********************************************
|
||||
* General test utilities.
|
||||
* Add new tabs, open the toolbox and switch to the various panels, select
|
||||
* nodes, get node references, ...
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add a new test tab in the browser and load the given url.
|
||||
*
|
||||
* @param {String} url
|
||||
* The url to be loaded in the new tab
|
||||
* @return a promise that resolves to the tab object when the url is loaded
|
||||
*/
|
||||
function addTab(url) {
|
||||
info("Adding a new tab with URL: '" + url + "'");
|
||||
let def = promise.defer();
|
||||
|
||||
window.focus();
|
||||
|
||||
let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
info("Loading the helper frame script " + FRAME_SCRIPT_URL);
|
||||
browser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
|
||||
|
||||
browser.addEventListener("load", function onload() {
|
||||
browser.removeEventListener("load", onload, true);
|
||||
info("URL '" + url + "' loading complete");
|
||||
|
||||
def.resolve(tab);
|
||||
}, true);
|
||||
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple DOM node accesor function that takes either a node or a string css
|
||||
* selector as argument and returns the corresponding node
|
||||
*
|
||||
* @param {String|DOMNode} nodeOrSelector
|
||||
* @return {DOMNode|CPOW} Note that in e10s mode a CPOW object is returned which
|
||||
* doesn't implement *all* of the DOMNode's properties
|
||||
*/
|
||||
function getNode(nodeOrSelector) {
|
||||
info("Getting the node for '" + nodeOrSelector + "'");
|
||||
return typeof nodeOrSelector === "string" ?
|
||||
content.document.querySelector(nodeOrSelector) :
|
||||
nodeOrSelector;
|
||||
function openComputedView() {
|
||||
return openInspectorSidebarTab("computedview").then(objects => {
|
||||
return {
|
||||
toolbox: objects.toolbox,
|
||||
inspector: objects.inspector,
|
||||
view: objects.view.view
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,187 +40,6 @@ function getNodeFront(selector, {walker}) {
|
|||
return walker.querySelector(walker.rootNode, selector);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the inspector's current selection to a node or to the first match of the
|
||||
* given css selector.
|
||||
*
|
||||
* @param {String|NodeFront} data
|
||||
* The node to select
|
||||
* @param {InspectorPanel} inspector
|
||||
* The instance of InspectorPanel currently loaded in the toolbox
|
||||
* @param {String} reason
|
||||
* Defaults to "test" which instructs the inspector not
|
||||
* to highlight the node upon selection
|
||||
* @return {Promise} Resolves when the inspector is updated with the new node
|
||||
*/
|
||||
var selectNode = Task.async(function*(data, inspector, reason="test") {
|
||||
info("Selecting the node for '" + data + "'");
|
||||
let nodeFront = data;
|
||||
if (!data._form) {
|
||||
nodeFront = yield getNodeFront(data, inspector);
|
||||
}
|
||||
let updated = inspector.once("inspector-updated");
|
||||
inspector.selection.setNodeFront(nodeFront, reason);
|
||||
yield updated;
|
||||
});
|
||||
|
||||
/**
|
||||
* Open the toolbox, with the inspector tool visible.
|
||||
*
|
||||
* @return a promise that resolves when the inspector is ready
|
||||
*/
|
||||
var openInspector = Task.async(function*() {
|
||||
info("Opening the inspector");
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
|
||||
let inspector, toolbox;
|
||||
|
||||
// Checking if the toolbox and the inspector are already loaded
|
||||
// The inspector-updated event should only be waited for if the inspector
|
||||
// isn't loaded yet
|
||||
toolbox = gDevTools.getToolbox(target);
|
||||
if (toolbox) {
|
||||
inspector = toolbox.getPanel("inspector");
|
||||
if (inspector) {
|
||||
info("Toolbox and inspector already open");
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
inspector: inspector
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
info("Opening the toolbox");
|
||||
toolbox = yield gDevTools.showToolbox(target, "inspector");
|
||||
yield waitForToolboxFrameFocus(toolbox);
|
||||
inspector = toolbox.getPanel("inspector");
|
||||
|
||||
info("Waiting for the inspector to update");
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
inspector: inspector
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Wait for the toolbox frame to receive focus after it loads
|
||||
*
|
||||
* @param {Toolbox} toolbox
|
||||
* @return a promise that resolves when focus has been received
|
||||
*/
|
||||
function waitForToolboxFrameFocus(toolbox) {
|
||||
info("Making sure that the toolbox's frame is focused");
|
||||
let def = promise.defer();
|
||||
let win = toolbox.frame.contentWindow;
|
||||
waitForFocus(def.resolve, win);
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the toolbox, with the inspector tool visible, and the sidebar that
|
||||
* corresponds to the given id selected
|
||||
*
|
||||
* @return a promise that resolves when the inspector is ready and the sidebar
|
||||
* view is visible and ready
|
||||
*/
|
||||
var openInspectorSideBar = Task.async(function*(id) {
|
||||
let {toolbox, inspector} = yield openInspector();
|
||||
|
||||
if (!hasSideBarTab(inspector, id)) {
|
||||
info("Waiting for the " + id + " sidebar to be ready");
|
||||
yield inspector.sidebar.once(id + "-ready");
|
||||
}
|
||||
|
||||
info("Selecting the " + id + " sidebar");
|
||||
inspector.sidebar.select(id);
|
||||
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
inspector: inspector,
|
||||
view: inspector.sidebar.getWindowForTab(id)[id].view
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Open the toolbox, with the inspector tool visible, and the computed-view
|
||||
* sidebar tab selected.
|
||||
*
|
||||
* @return a promise that resolves when the inspector is ready and the computed
|
||||
* view is visible and ready
|
||||
*/
|
||||
function openComputedView() {
|
||||
return openInspectorSideBar("computedview");
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for eventName on target to be delivered a number of times.
|
||||
*
|
||||
* @param {Object} target
|
||||
* An observable object that either supports on/off or
|
||||
* addEventListener/removeEventListener
|
||||
* @param {String} eventName
|
||||
* @param {Number} numTimes
|
||||
* Number of deliveries to wait for.
|
||||
* @param {Boolean} useCapture
|
||||
* Optional, for addEventListener/removeEventListener
|
||||
* @return A promise that resolves when the event has been handled
|
||||
*/
|
||||
function waitForNEvents(target, eventName, numTimes, useCapture = false) {
|
||||
info("Waiting for event: '" + eventName + "' on " + target + ".");
|
||||
|
||||
let deferred = promise.defer();
|
||||
let count = 0;
|
||||
|
||||
for (let [add, remove] of [
|
||||
["addEventListener", "removeEventListener"],
|
||||
["addListener", "removeListener"],
|
||||
["on", "off"]
|
||||
]) {
|
||||
if ((add in target) && (remove in target)) {
|
||||
target[add](eventName, function onEvent(...aArgs) {
|
||||
if (++count == numTimes) {
|
||||
target[remove](eventName, onEvent, useCapture);
|
||||
deferred.resolve.apply(deferred, aArgs);
|
||||
}
|
||||
}, useCapture);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for eventName on target.
|
||||
*
|
||||
* @param {Object} target
|
||||
* An observable object that either supports on/off or
|
||||
* addEventListener/removeEventListener
|
||||
* @param {String} eventName
|
||||
* @param {Boolean} useCapture
|
||||
* Optional, for addEventListener/removeEventListener
|
||||
* @return A promise that resolves when the event has been handled
|
||||
*/
|
||||
function once(target, eventName, useCapture=false) {
|
||||
return waitForNEvents(target, eventName, 1, useCapture);
|
||||
}
|
||||
|
||||
/**
|
||||
* This shouldn't be used in the tests, but is useful when writing new tests or
|
||||
* debugging existing tests in order to introduce delays in the test steps
|
||||
*
|
||||
* @param {Number} ms
|
||||
* The time to wait
|
||||
* @return A promise that resolves when the time is passed
|
||||
*/
|
||||
function wait(ms) {
|
||||
let def = promise.defer();
|
||||
content.setTimeout(def.resolve, ms);
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for a new tab to open and return a promise that resolves when one
|
||||
* does and completes the load event.
|
||||
|
@ -343,23 +56,6 @@ var waitForTab = Task.async(function*() {
|
|||
return tab;
|
||||
});
|
||||
|
||||
/**
|
||||
* @see SimpleTest.waitForClipboard
|
||||
*
|
||||
* @param {Function} setup
|
||||
* Function to execute before checking for the
|
||||
* clipboard content
|
||||
* @param {String|Boolean} expected
|
||||
* An expected string or validator function
|
||||
* @return a promise that resolves when the expected string has been found or
|
||||
* the validator function has returned true, rejects otherwise.
|
||||
*/
|
||||
function waitForClipboard(setup, expected) {
|
||||
let def = promise.defer();
|
||||
SimpleTest.waitForClipboard(expected, setup, def.resolve, def.reject);
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch the copy event on the given element
|
||||
*/
|
||||
|
@ -369,18 +65,6 @@ function fireCopyEvent(element) {
|
|||
element.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the inspector's sidebar corresponding to the given id already
|
||||
* exists
|
||||
*
|
||||
* @param {InspectorPanel}
|
||||
* @param {String}
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function hasSideBarTab(inspector, id) {
|
||||
return !!inspector.sidebar.getWindowForTab(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate the key input for the given input in the window.
|
||||
*
|
||||
|
@ -395,13 +79,6 @@ function synthesizeKeys(input, win) {
|
|||
}
|
||||
}
|
||||
|
||||
/* *********************************************
|
||||
* COMPUTED-VIEW
|
||||
* *********************************************
|
||||
* Computed-view related utility functions.
|
||||
* Allows to get properties, links, expand properties, ...
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get references to the name and value span nodes corresponding to a given
|
||||
* property name in the computed-view
|
||||
|
@ -534,77 +211,3 @@ function getComputedViewLinkByIndex(view, index) {
|
|||
let links = view.styleDocument.querySelectorAll(".rule-link .link");
|
||||
return links[index];
|
||||
}
|
||||
|
||||
/* *********************************************
|
||||
* STYLE-EDITOR
|
||||
* *********************************************
|
||||
* Style-editor related utility functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Wait for the toolbox to emit the styleeditor-selected event and when done
|
||||
* wait for the stylesheet identified by href to be loaded in the stylesheet
|
||||
* editor
|
||||
*
|
||||
* @param {Toolbox} toolbox
|
||||
* @param {String} href
|
||||
* Optional, if not provided, wait for the first editor to be ready
|
||||
* @return a promise that resolves to the editor when the stylesheet editor is
|
||||
* ready
|
||||
*/
|
||||
function waitForStyleEditor(toolbox, href) {
|
||||
let def = promise.defer();
|
||||
|
||||
info("Waiting for the toolbox to switch to the styleeditor");
|
||||
toolbox.once("styleeditor-selected").then(() => {
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
ok(panel && panel.UI, "Styleeditor panel switched to front");
|
||||
|
||||
// A helper that resolves the promise once it receives an editor that
|
||||
// matches the expected href. Returns false if the editor was not correct.
|
||||
let gotEditor = (event, editor) => {
|
||||
let currentHref = editor.styleSheet.href;
|
||||
if (!href || (href && currentHref.endsWith(href))) {
|
||||
info("Stylesheet editor selected");
|
||||
panel.UI.off("editor-selected", gotEditor);
|
||||
|
||||
editor.getSourceEditor().then(sourceEditor => {
|
||||
info("Stylesheet editor fully loaded");
|
||||
def.resolve(sourceEditor);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
info("The editor was incorrect. Waiting for editor-selected event.");
|
||||
return false;
|
||||
};
|
||||
|
||||
// The expected editor may already be selected. Check the if the currently
|
||||
// selected editor is the expected one and if not wait for an
|
||||
// editor-selected event.
|
||||
if (!gotEditor("styleeditor-selected", panel.UI.selectedEditor)) {
|
||||
// The expected editor is not selected (yet). Wait for it.
|
||||
panel.UI.on("editor-selected", gotEditor);
|
||||
}
|
||||
});
|
||||
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the current page and wait for the inspector to be initialized after
|
||||
* the navigation
|
||||
*
|
||||
* @param {InspectorPanel} inspector
|
||||
* The instance of InspectorPanel currently loaded in the toolbox
|
||||
* @return a promise that resolves after page reload and inspector
|
||||
* initialization
|
||||
*/
|
||||
function reloadPage(inspector) {
|
||||
let onNewRoot = inspector.once("new-root");
|
||||
content.location.reload();
|
||||
return onNewRoot.then(() => {
|
||||
inspector.markup._waitForChildren();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,23 +5,23 @@
|
|||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
const TEST_URI = BASE_URI + "browser_fontinspector.html";
|
||||
const TEST_URI = URL_ROOT + "browser_fontinspector.html";
|
||||
const FONTS = [
|
||||
{name: "Ostrich Sans Medium", remote: true, url: BASE_URI + "ostrich-regular.ttf",
|
||||
{name: "Ostrich Sans Medium", remote: true, url: URL_ROOT + "ostrich-regular.ttf",
|
||||
format: "truetype", cssName: "bar"},
|
||||
{name: "Ostrich Sans Black", remote: true, url: BASE_URI + "ostrich-black.ttf",
|
||||
{name: "Ostrich Sans Black", remote: true, url: URL_ROOT + "ostrich-black.ttf",
|
||||
format: "", cssName: "bar"},
|
||||
{name: "Ostrich Sans Black", remote: true, url: BASE_URI + "ostrich-black.ttf",
|
||||
{name: "Ostrich Sans Black", remote: true, url: URL_ROOT + "ostrich-black.ttf",
|
||||
format: "", cssName: "bar"},
|
||||
{name: "Ostrich Sans Medium", remote: true, url: BASE_URI + "ostrich-regular.ttf",
|
||||
{name: "Ostrich Sans Medium", remote: true, url: URL_ROOT + "ostrich-regular.ttf",
|
||||
format: "", cssName: "barnormal"},
|
||||
];
|
||||
|
||||
add_task(function*() {
|
||||
let { inspector, fontInspector } = yield openFontInspectorForURL(TEST_URI);
|
||||
ok(!!fontInspector, "Font inspector document is alive.");
|
||||
let { inspector, view } = yield openFontInspectorForURL(TEST_URI);
|
||||
ok(!!view, "Font inspector document is alive.");
|
||||
|
||||
let viewDoc = fontInspector.chromeDoc;
|
||||
let viewDoc = view.chromeDoc;
|
||||
|
||||
yield testBodyFonts(inspector, viewDoc);
|
||||
yield testDivFonts(inspector, viewDoc);
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
// Test that correct previews are shown if the text is edited after 'Show all'
|
||||
// button is pressed.
|
||||
|
||||
const TEST_URI = BASE_URI + "browser_fontinspector.html";
|
||||
const TEST_URI = URL_ROOT + "browser_fontinspector.html";
|
||||
|
||||
add_task(function*() {
|
||||
let { inspector, fontInspector } = yield openFontInspectorForURL(TEST_URI);
|
||||
let viewDoc = fontInspector.chromeDoc;
|
||||
let { inspector, view } = yield openFontInspectorForURL(TEST_URI);
|
||||
let viewDoc = view.chromeDoc;
|
||||
|
||||
info("Selecting a node that doesn't contain all document fonts.");
|
||||
yield selectNode(".normal-text", inspector);
|
||||
|
@ -36,7 +36,7 @@ add_task(function*() {
|
|||
"The .normal-text didn't show all fonts.");
|
||||
|
||||
info("Editing the preview text.");
|
||||
yield updatePreviewText(fontInspector, "The quick brown");
|
||||
yield updatePreviewText(view, "The quick brown");
|
||||
|
||||
let numPreviews = viewDoc.querySelectorAll("#all-fonts .font-preview").length;
|
||||
is(numPreviews, allFontsNumPreviews,
|
||||
|
|
|
@ -7,25 +7,25 @@
|
|||
// exact preview images because they are drawn on a canvas causing them to vary
|
||||
// between systems, platforms and software versions.
|
||||
|
||||
const TEST_URI = BASE_URI + "browser_fontinspector.html";
|
||||
const TEST_URI = URL_ROOT + "browser_fontinspector.html";
|
||||
|
||||
add_task(function*() {
|
||||
let { inspector, fontInspector } = yield openFontInspectorForURL(TEST_URI);
|
||||
let viewDoc = fontInspector.chromeDoc;
|
||||
let {view} = yield openFontInspectorForURL(TEST_URI);
|
||||
let viewDoc = view.chromeDoc;
|
||||
|
||||
let previews = viewDoc.querySelectorAll("#all-fonts .font-preview");
|
||||
let initialPreviews = [...previews].map(p => p.src);
|
||||
|
||||
info("Typing 'Abc' to check that the reference previews are correct.");
|
||||
yield updatePreviewText(fontInspector, "Abc");
|
||||
yield updatePreviewText(view, "Abc");
|
||||
checkPreviewImages(viewDoc, initialPreviews, true);
|
||||
|
||||
info("Typing something else to the preview box.");
|
||||
yield updatePreviewText(fontInspector, "The quick brown");
|
||||
yield updatePreviewText(view, "The quick brown");
|
||||
checkPreviewImages(viewDoc, initialPreviews, false);
|
||||
|
||||
info("Blanking the input to restore default previews.");
|
||||
yield updatePreviewText(fontInspector, "");
|
||||
yield updatePreviewText(view, "");
|
||||
checkPreviewImages(viewDoc, initialPreviews, true);
|
||||
});
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ requestLongerTimeout(2);
|
|||
|
||||
const { getTheme, setTheme } = require("devtools/client/shared/theme");
|
||||
|
||||
const TEST_URI = BASE_URI + "browser_fontinspector.html";
|
||||
const TEST_URI = URL_ROOT + "browser_fontinspector.html";
|
||||
const originalTheme = getTheme();
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
|
@ -18,8 +18,8 @@ registerCleanupFunction(() => {
|
|||
});
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, fontInspector } = yield openFontInspectorForURL(TEST_URI);
|
||||
let { chromeDoc: doc } = fontInspector;
|
||||
let { inspector, view } = yield openFontInspectorForURL(TEST_URI);
|
||||
let { chromeDoc: doc } = view;
|
||||
|
||||
yield selectNode(".normal-text", inspector);
|
||||
|
||||
|
|
|
@ -2,79 +2,21 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// shared-head.js handles imports, constants, and utility functions
|
||||
Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js", this);
|
||||
|
||||
const BASE_URI = "http://mochi.test:8888/browser/devtools/client/inspector/fonts/test/";
|
||||
|
||||
/**
|
||||
* Open the toolbox, with the inspector tool visible.
|
||||
* @param {Function} cb Optional callback, if you don't want to use the returned
|
||||
* promise
|
||||
* @return a promise that resolves when the inspector is ready
|
||||
*/
|
||||
var openInspector = Task.async(function*(cb) {
|
||||
info("Opening the inspector");
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
|
||||
let inspector, toolbox;
|
||||
|
||||
// Checking if the toolbox and the inspector are already loaded
|
||||
// The inspector-updated event should only be waited for if the inspector
|
||||
// isn't loaded yet
|
||||
toolbox = gDevTools.getToolbox(target);
|
||||
if (toolbox) {
|
||||
inspector = toolbox.getPanel("inspector");
|
||||
if (inspector) {
|
||||
info("Toolbox and inspector already open");
|
||||
if (cb) {
|
||||
return cb(inspector, toolbox);
|
||||
} else {
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
inspector: inspector
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info("Opening the toolbox");
|
||||
toolbox = yield gDevTools.showToolbox(target, "inspector");
|
||||
yield waitForToolboxFrameFocus(toolbox);
|
||||
inspector = toolbox.getPanel("inspector");
|
||||
|
||||
info("Waiting for the inspector to update");
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
if (cb) {
|
||||
return cb(inspector, toolbox);
|
||||
} else {
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
inspector: inspector
|
||||
};
|
||||
}
|
||||
});
|
||||
// Import the inspector's head.js first (which itself imports shared-head.js).
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/inspector/test/head.js",
|
||||
this);
|
||||
|
||||
/**
|
||||
* Adds a new tab with the given URL, opens the inspector and selects the
|
||||
* font-inspector tab.
|
||||
*
|
||||
* @return Object
|
||||
* {
|
||||
* toolbox,
|
||||
* inspector,
|
||||
* fontInspector
|
||||
* }
|
||||
* @return {Promise} resolves to a {toolbox, inspector, view} object
|
||||
*/
|
||||
var openFontInspectorForURL = Task.async(function* (url) {
|
||||
info("Opening tab " + url);
|
||||
var openFontInspectorForURL = Task.async(function*(url) {
|
||||
yield addTab(url);
|
||||
|
||||
let { toolbox, inspector } = yield openInspector();
|
||||
let {toolbox, inspector} = yield openInspectorSidebarTab("fontinspector");
|
||||
|
||||
/**
|
||||
* Call selectNode to trigger font-inspector update so that we don't timeout
|
||||
|
@ -88,74 +30,29 @@ var openFontInspectorForURL = Task.async(function* (url) {
|
|||
* FontInspector.update that emits the 'fontinspector-updated' event.
|
||||
*/
|
||||
let onUpdated = inspector.once("fontinspector-updated");
|
||||
|
||||
yield selectNode("body", inspector);
|
||||
inspector.sidebar.select("fontinspector");
|
||||
|
||||
info("Waiting for font-inspector to update.");
|
||||
yield onUpdated;
|
||||
|
||||
info("Font Inspector ready.");
|
||||
|
||||
let { fontInspector } = inspector.sidebar.getWindowForTab("fontinspector");
|
||||
return {
|
||||
fontInspector,
|
||||
toolbox,
|
||||
inspector,
|
||||
toolbox
|
||||
view: inspector.sidebar.getWindowForTab("fontinspector").fontInspector
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Select a node in the inspector given its selector.
|
||||
*/
|
||||
var selectNode = Task.async(function*(selector, inspector, reason="test") {
|
||||
info("Selecting the node for '" + selector + "'");
|
||||
let nodeFront = yield getNodeFront(selector, inspector);
|
||||
let updated = inspector.once("inspector-updated");
|
||||
inspector.selection.setNodeFront(nodeFront, reason);
|
||||
yield updated;
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the NodeFront for a given css selector, via the protocol
|
||||
* @param {String|NodeFront} selector
|
||||
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
||||
* loaded in the toolbox
|
||||
* @return {Promise} Resolves to the NodeFront instance
|
||||
*/
|
||||
function getNodeFront(selector, {walker}) {
|
||||
if (selector._form) {
|
||||
return selector;
|
||||
}
|
||||
return walker.querySelector(walker.rootNode, selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the toolbox frame to receive focus after it loads
|
||||
* @param {Toolbox} toolbox
|
||||
* @return a promise that resolves when focus has been received
|
||||
*/
|
||||
function waitForToolboxFrameFocus(toolbox) {
|
||||
info("Making sure that the toolbox's frame is focused");
|
||||
let def = promise.defer();
|
||||
let win = toolbox.frame.contentWindow;
|
||||
waitForFocus(def.resolve, win);
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the preview input field, types new text into it and waits for the
|
||||
* preview images to be updated.
|
||||
*
|
||||
* @param {FontInspector} fontInspector - The FontInspector instance.
|
||||
* @param {FontInspector} view - The FontInspector instance.
|
||||
* @param {String} text - The text to preview.
|
||||
*/
|
||||
function* updatePreviewText(fontInspector, text) {
|
||||
function* updatePreviewText(view, text) {
|
||||
info(`Changing the preview text to '${text}'`);
|
||||
|
||||
let doc = fontInspector.chromeDoc;
|
||||
let doc = view.chromeDoc;
|
||||
let input = doc.getElementById("preview-text-input");
|
||||
let update = fontInspector.inspector.once("fontinspector-updated");
|
||||
let update = view.inspector.once("fontinspector-updated");
|
||||
|
||||
info("Focusing the input field.");
|
||||
input.focus();
|
||||
|
|
|
@ -45,52 +45,29 @@ function selectAndHighlightNode(nodeOrSelector, inspector) {
|
|||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the inspector's sidebar corresponding to the given id already
|
||||
* exists
|
||||
* @param {InspectorPanel}
|
||||
* @param {String}
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function hasSideBarTab(inspector, id) {
|
||||
return !!inspector.sidebar.getWindowForTab(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the toolbox, with the inspector tool visible, and the layout-view
|
||||
* sidebar tab selected.
|
||||
* @return a promise that resolves when the inspector is ready and the layout
|
||||
* view is visible and ready
|
||||
*/
|
||||
var openLayoutView = Task.async(function*() {
|
||||
let {toolbox, inspector} = yield openInspector();
|
||||
function openLayoutView() {
|
||||
return openInspectorSidebarTab("layoutview").then(objects => {
|
||||
// The actual highligher show/hide methods are mocked in layoutview tests.
|
||||
// The highlighter is tested in devtools/inspector/test.
|
||||
function mockHighlighter({highlighter}) {
|
||||
highlighter.showBoxModel = function(nodeFront, options) {
|
||||
return promise.resolve();
|
||||
};
|
||||
highlighter.hideBoxModel = function() {
|
||||
return promise.resolve();
|
||||
};
|
||||
}
|
||||
mockHighlighter(objects.toolbox);
|
||||
|
||||
// The actual highligher show/hide methods are mocked in layoutview tests.
|
||||
// The highlighter is tested in devtools/inspector/test.
|
||||
function mockHighlighter({highlighter}) {
|
||||
highlighter.showBoxModel = function(nodeFront, options) {
|
||||
return promise.resolve();
|
||||
};
|
||||
highlighter.hideBoxModel = function() {
|
||||
return promise.resolve();
|
||||
};
|
||||
}
|
||||
mockHighlighter(toolbox);
|
||||
|
||||
if (!hasSideBarTab(inspector, "layoutview")) {
|
||||
info("Waiting for the layoutview sidebar to be ready");
|
||||
yield inspector.sidebar.once("layoutview-ready");
|
||||
}
|
||||
|
||||
info("Selecting the layoutview sidebar");
|
||||
inspector.sidebar.select("layoutview");
|
||||
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
inspector: inspector,
|
||||
view: inspector.sidebar.getWindowForTab("layoutview")["layoutview"]
|
||||
};
|
||||
});
|
||||
return objects;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the layoutview-updated event.
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
"use strict";
|
||||
|
||||
// Test native anonymous content in the markupview.
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_anonymous.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_anonymous.html";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
let pseudo = yield getNodeFront("#pseudo", inspector);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ requestLongerTimeout(2);
|
|||
const TEST_URL = "chrome://devtools/content/scratchpad/scratchpad.xul";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
let toolbarbutton = yield getNodeFront("toolbarbutton", inspector);
|
||||
let children = yield inspector.walker.children(toolbarbutton);
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
// Test shadow DOM content in the markupview.
|
||||
// Note that many features are not yet enabled, but basic listing
|
||||
// of elements should be working.
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_anonymous.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_anonymous.html";
|
||||
|
||||
add_task(function*() {
|
||||
Services.prefs.setBoolPref("dom.webcomponents.enabled", true);
|
||||
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
let shadow = yield getNodeFront("#shadow", inspector.markup);
|
||||
let children = yield inspector.walker.children(shadow);
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
|
||||
// Test native anonymous content in the markupview with devtools.inspector.showAllAnonymousContent
|
||||
// set to true
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_anonymous.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_anonymous.html";
|
||||
|
||||
add_task(function*() {
|
||||
Services.prefs.setBoolPref("devtools.inspector.showAllAnonymousContent", true);
|
||||
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
let native = yield getNodeFront("#native", inspector);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// The correctness and cycling of the suggestions is covered in the ruleview
|
||||
// tests.
|
||||
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_edit.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_edit.html";
|
||||
// test data format :
|
||||
// [
|
||||
// what key to press,
|
||||
|
@ -65,7 +65,7 @@ const TEST_DATA = [
|
|||
|
||||
add_task(function*() {
|
||||
info("Opening the inspector on the test URL");
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
yield inspector.markup.expandAll();
|
||||
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
// Test that dragging a node near the top or bottom edge of the markup-view
|
||||
// auto-scrolls the view.
|
||||
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_dragdrop_autoscroll.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_dragdrop_autoscroll.html";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
let markup = inspector.markup;
|
||||
let viewHeight = markup.doc.documentElement.clientHeight;
|
||||
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
// the minimum vertical distance defined in markup-view.js by
|
||||
// DRAG_DROP_MIN_INITIAL_DISTANCE.
|
||||
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_dragdrop.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_dragdrop.html";
|
||||
const TEST_NODE = "#test";
|
||||
|
||||
// Keep this in sync with DRAG_DROP_MIN_INITIAL_DISTANCE in markup-view.js
|
||||
const MIN_DISTANCE = 10;
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Drag the test node by half of the minimum distance");
|
||||
yield simulateNodeDrag(inspector, TEST_NODE, 0, MIN_DISTANCE / 2);
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
// Test that the root node isn't draggable (as well as head and body).
|
||||
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_dragdrop.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_dragdrop.html";
|
||||
const TEST_DATA = ["html", "head", "body"];
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
for (let selector of TEST_DATA) {
|
||||
info("Try to drag/drop node " + selector);
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
// Test whether ESCAPE keypress cancels dragging of an element.
|
||||
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_dragdrop.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_dragdrop.html";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
let {markup} = inspector;
|
||||
|
||||
info("Get a test container");
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
|
||||
// Check that pseudo-elements and anonymous nodes are not draggable.
|
||||
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_dragdrop.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_dragdrop.html";
|
||||
|
||||
add_task(function*() {
|
||||
Services.prefs.setBoolPref("devtools.inspector.showAllAnonymousContent", true);
|
||||
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Expanding nodes below #test");
|
||||
let parentFront = yield getNodeFront("#test", inspector);
|
||||
|
|
|
@ -8,10 +8,10 @@ requestLongerTimeout(2);
|
|||
|
||||
// Test different kinds of drag and drop node re-ordering.
|
||||
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_dragdrop.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_dragdrop.html";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
let ids;
|
||||
|
||||
info("Expand #test node");
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
const TEST_URL = "data:text/html;charset=utf8,<img src=\"about:logo\" /><div>";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
let {markup} = inspector;
|
||||
|
||||
info("Get the tooltip target element for the image's src attribute");
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events-overflow.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events-overflow.html";
|
||||
const TEST_DATA = [
|
||||
{
|
||||
desc: "editor overflows container",
|
||||
|
@ -29,7 +29,7 @@ const TEST_DATA = [
|
|||
];
|
||||
|
||||
add_task(function*() {
|
||||
let { inspector } = yield addTab(TEST_URL).then(openInspector);
|
||||
let { inspector } = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
let markupContainer = yield getContainerForSelector("#events", inspector);
|
||||
let evHolder = markupContainer.elt.querySelector(".markupview-events");
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
// Test that markup view event bubbles show the correct event info for DOM
|
||||
// events.
|
||||
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events.html";
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
|
|
@ -9,16 +9,16 @@
|
|||
// The test registers one backend actor providing custom form data
|
||||
// and checks that the value is properly sent to the client (NodeFront).
|
||||
|
||||
const TEST_PAGE_URL = TEST_URL_ROOT + "doc_markup_events_form.html";
|
||||
const TEST_ACTOR_URL = CHROME_BASE + "actor_events_form.js";
|
||||
const TEST_PAGE_URL = URL_ROOT + "doc_markup_events_form.html";
|
||||
const TEST_ACTOR_URL = CHROME_URL_ROOT + "actor_events_form.js";
|
||||
|
||||
var {ActorRegistryFront} = require("devtools/server/actors/actor-registry");
|
||||
var {EventsFormFront} = require(TEST_ACTOR_URL);
|
||||
|
||||
add_task(function*() {
|
||||
info("Opening the Toolbox");
|
||||
let {tab} = yield addTab(TEST_PAGE_URL);
|
||||
let {toolbox} = yield openToolbox("webconsole");
|
||||
let tab = yield addTab(TEST_PAGE_URL);
|
||||
let toolbox = yield openToolboxForTab(tab, "webconsole");
|
||||
|
||||
info("Registering test actor");
|
||||
let {registrar, front} = yield registerTestActor(toolbox);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// and jQuery Live events (jQuery version 1.0).
|
||||
|
||||
const TEST_LIB = "lib_jquery_1.0.js";
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
@ -18,7 +18,7 @@ const TEST_DATA = [
|
|||
expected: [
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB,
|
||||
filename: URL_ROOT + TEST_LIB,
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
|
@ -104,7 +104,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB,
|
||||
filename: URL_ROOT + TEST_LIB,
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM0"
|
||||
|
@ -159,7 +159,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":894",
|
||||
filename: URL_ROOT + TEST_LIB + ":894",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -199,7 +199,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":894",
|
||||
filename: URL_ROOT + TEST_LIB + ":894",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// and jQuery Live events (jQuery version 1.1).
|
||||
|
||||
const TEST_LIB = "lib_jquery_1.1.js";
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
@ -18,7 +18,7 @@ const TEST_DATA = [
|
|||
expected: [
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB,
|
||||
filename: URL_ROOT + TEST_LIB,
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
|
@ -108,7 +108,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB,
|
||||
filename: URL_ROOT + TEST_LIB,
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM0"
|
||||
|
@ -173,7 +173,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":1224",
|
||||
filename: URL_ROOT + TEST_LIB + ":1224",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -223,7 +223,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":1224",
|
||||
filename: URL_ROOT + TEST_LIB + ":1224",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// and jQuery Live events (jQuery version 1.11.1).
|
||||
|
||||
const TEST_LIB = "lib_jquery_1.11.1_min.js";
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
@ -105,7 +105,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
filename: URL_ROOT + TEST_LIB + ":3",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -126,7 +126,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
filename: URL_ROOT + TEST_LIB + ":3",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// and jQuery Live events (jQuery version 1.2).
|
||||
|
||||
const TEST_LIB = "lib_jquery_1.2_min.js";
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
@ -79,7 +79,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB,
|
||||
filename: URL_ROOT + TEST_LIB,
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM0"
|
||||
|
@ -144,7 +144,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":24",
|
||||
filename: URL_ROOT + TEST_LIB + ":24",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -168,7 +168,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":24",
|
||||
filename: URL_ROOT + TEST_LIB + ":24",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// and jQuery Live events (jQuery version 1.3).
|
||||
|
||||
const TEST_LIB = "lib_jquery_1.3_min.js";
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
@ -18,7 +18,7 @@ const TEST_DATA = [
|
|||
expected: [
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
filename: URL_ROOT + TEST_LIB + ":19",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
|
@ -98,7 +98,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
filename: URL_ROOT + TEST_LIB + ":19",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -109,7 +109,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "unload",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
filename: URL_ROOT + TEST_LIB + ":19",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
|
@ -120,7 +120,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "unload",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
filename: URL_ROOT + TEST_LIB + ":19",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -156,7 +156,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
filename: URL_ROOT + TEST_LIB + ":19",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -177,7 +177,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
filename: URL_ROOT + TEST_LIB + ":19",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// and jQuery Live events (jQuery version 1.4).
|
||||
|
||||
const TEST_LIB = "lib_jquery_1.4_min.js";
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
@ -79,7 +79,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":26",
|
||||
filename: URL_ROOT + TEST_LIB + ":26",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -123,7 +123,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":48",
|
||||
filename: URL_ROOT + TEST_LIB + ":48",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -144,7 +144,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":48",
|
||||
filename: URL_ROOT + TEST_LIB + ":48",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -171,7 +171,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "dblclick",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":17",
|
||||
filename: URL_ROOT + TEST_LIB + ":17",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
|
@ -230,7 +230,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "dragstart",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":17",
|
||||
filename: URL_ROOT + TEST_LIB + ":17",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
|
|
|
@ -10,7 +10,7 @@ requestLongerTimeout(2);
|
|||
// and jQuery Live events (jQuery version 1.6).
|
||||
|
||||
const TEST_LIB = "lib_jquery_1.6_min.js";
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
@ -81,7 +81,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
filename: URL_ROOT + TEST_LIB + ":16",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -122,7 +122,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
filename: URL_ROOT + TEST_LIB + ":16",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -143,7 +143,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
filename: URL_ROOT + TEST_LIB + ":16",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -170,7 +170,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "dblclick",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
filename: URL_ROOT + TEST_LIB + ":16",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
|
@ -225,7 +225,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "dragend",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
filename: URL_ROOT + TEST_LIB + ":16",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
|
@ -280,7 +280,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "dragleave",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
filename: URL_ROOT + TEST_LIB + ":16",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
|
@ -335,7 +335,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "dragstart",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
filename: URL_ROOT + TEST_LIB + ":16",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
|
|
|
@ -10,7 +10,7 @@ requestLongerTimeout(2);
|
|||
// and jQuery Live events (jQuery version 1.7).
|
||||
|
||||
const TEST_LIB = "lib_jquery_1.7_min.js";
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
@ -81,7 +81,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":2",
|
||||
filename: URL_ROOT + TEST_LIB + ":2",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -122,7 +122,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
filename: URL_ROOT + TEST_LIB + ":3",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -143,7 +143,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
filename: URL_ROOT + TEST_LIB + ":3",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
|
|
@ -10,7 +10,7 @@ requestLongerTimeout(2);
|
|||
// and jQuery Live events (jQuery version 2.1.1).
|
||||
|
||||
const TEST_LIB = "lib_jquery_2.1.1_min.js";
|
||||
const TEST_URL = TEST_URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events_jquery.html?" + TEST_LIB;
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
@ -106,7 +106,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
filename: URL_ROOT + TEST_LIB + ":3",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -127,7 +127,7 @@ const TEST_DATA = [
|
|||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
filename: URL_ROOT + TEST_LIB + ":3",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
|
|
@ -15,7 +15,7 @@ const TEST_DATA = [
|
|||
newHTML: '<div id="one">First Div</div>',
|
||||
validate: function*(pageNode, pageNodeFront, selectedNodeFront) {
|
||||
is(pageNode.textContent, "First Div", "New div has expected text content");
|
||||
ok(!getNode("#one em"), "No em remaining")
|
||||
ok(!getNode("#one em", {expectNoMatch: true}), "No em remaining")
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -71,7 +71,7 @@ const TEST_URL = "data:text/html," +
|
|||
"</html>";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
inspector.markup._frame.focus();
|
||||
yield runEditOuterHTMLTests(TEST_DATA, inspector);
|
||||
yield runEditOuterHTMLTests(TEST_DATA, inspector, testActor);
|
||||
});
|
||||
|
|
|
@ -74,7 +74,7 @@ const TEST_DATA = [
|
|||
is(pageNodeFront, selectedNodeFront, "Original element is selected");
|
||||
|
||||
let p = getNode("#badMarkup5");
|
||||
let nodiv = getNode("#badMarkup5 div");
|
||||
let nodiv = getNode("#badMarkup5 div", {expectNoMatch: true});
|
||||
let div = getNode("#badMarkup5 ~ div");
|
||||
|
||||
ok(!nodiv, "The invalid markup got created as a sibling");
|
||||
|
@ -95,7 +95,7 @@ const TEST_URL = "data:text/html," +
|
|||
"</html>";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
inspector.markup._frame.focus();
|
||||
yield runEditOuterHTMLTests(TEST_DATA, inspector);
|
||||
yield runEditOuterHTMLTests(TEST_DATA, inspector, testActor);
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ const NEW_HTML = '<div id="keyboard">Edited</div>';
|
|||
requestLongerTimeout(2);
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
inspector.markup._frame.focus();
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
const PAGE_CONTENT = [
|
||||
'<img class="local" src="chrome://branding/content/about-logo.png" />',
|
||||
'<img class="data" src="data:image/png;base64,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" />',
|
||||
'<img class="remote" src="' + TEST_URL_ROOT + 'doc_markup_tooltip.png" />',
|
||||
'<img class="remote" src="' + URL_ROOT + 'doc_markup_tooltip.png" />',
|
||||
'<canvas class="canvas" width="600" height="600"></canvas>'
|
||||
].join("\n");
|
||||
|
||||
|
|
|
@ -8,15 +8,14 @@
|
|||
// changes.
|
||||
|
||||
const INITIAL_SRC = "data:image/png;base64,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";
|
||||
const UPDATED_SRC = TEST_URL_ROOT + "doc_markup_tooltip.png";
|
||||
const UPDATED_SRC = URL_ROOT + "doc_markup_tooltip.png";
|
||||
|
||||
const INITIAL_SRC_SIZE = "64" + " \u00D7 " + "64";
|
||||
const UPDATED_SRC_SIZE = "22" + " \u00D7 " + "23";
|
||||
|
||||
add_task(function*() {
|
||||
yield addTab("data:text/html,<p>markup view tooltip test</p><img>");
|
||||
|
||||
let { inspector } = yield openInspector();
|
||||
let { inspector } = yield openInspectorForURL(
|
||||
"data:text/html,<p>markup view tooltip test</p><img>");
|
||||
|
||||
info("Retrieving NodeFront for the <img> element.");
|
||||
let img = yield getNodeFront("img", inspector);
|
||||
|
|
|
@ -11,7 +11,7 @@ requestLongerTimeout(2);
|
|||
const TEST_URL = "data:text/html;charset=utf8,<div id='test' a b c d e></div>";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Focusing the tag editor of the test element");
|
||||
let {editor} = yield getContainerForSelector("div", inspector);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
const TEST_URL = "data:text/html;charset=utf8,<div></div>";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector, toolbox} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector, toolbox} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Focusing the tag editor of the test element");
|
||||
let {editor} = yield getContainerForSelector("div", inspector);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
const TEST_URL = "data:text/html;charset=utf8,<div class='test-class'></div>Text node";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector, toolbox} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector, toolbox} = yield openInspectorForURL(TEST_URL);
|
||||
let {walker} = inspector;
|
||||
|
||||
info("Select the test node to have the 2 test containers visible");
|
||||
|
|
|
@ -14,7 +14,7 @@ requestLongerTimeout(2);
|
|||
const TEST_URL = "data:text/html;charset=utf8,<div>test element</div>";
|
||||
|
||||
add_task(function*() {
|
||||
let {toolbox, inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Select the test node with the browser ctx menu");
|
||||
yield selectWithBrowserMenu(inspector);
|
||||
|
@ -26,7 +26,7 @@ add_task(function*() {
|
|||
assertNodeSelected(inspector, "body");
|
||||
|
||||
info("Select the test node with the element picker");
|
||||
yield selectWithElementPicker(inspector);
|
||||
yield selectWithElementPicker(inspector, testActor);
|
||||
assertNodeSelected(inspector, "div");
|
||||
|
||||
info("Press arrowUp to focus <body> " +
|
||||
|
@ -71,16 +71,13 @@ function* selectWithBrowserMenu(inspector) {
|
|||
yield inspector.once("inspector-updated");
|
||||
}
|
||||
|
||||
function* selectWithElementPicker(inspector) {
|
||||
function* selectWithElementPicker(inspector, testActor) {
|
||||
yield inspector.toolbox.highlighterUtils.startPicker();
|
||||
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("div", {
|
||||
type: "mousemove",
|
||||
}, gBrowser.selectedBrowser);
|
||||
|
||||
executeInContent("Test:SynthesizeKey", {
|
||||
key: "VK_RETURN",
|
||||
options: {}
|
||||
}, {}, false);
|
||||
yield testActor.synthesizeKey({key: "VK_RETURN", options: {}});
|
||||
yield inspector.once("inspector-updated");
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче