Bug 1539462 - Remove WebIDE r=ochameau,jryans,janerik,fluent-reviewers,flod

Per deprecation roadmap on https://developer.mozilla.org/en-US/docs/Tools/Deprecated_tools#WebIDE_and_Connect_page

Differential Revision: https://phabricator.services.mozilla.com/D46703

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Julian Descottes 2019-09-25 17:24:58 +00:00
Родитель 3055031260
Коммит 5c1a679523
131 изменённых файлов: 15 добавлений и 9897 удалений

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

@ -1935,8 +1935,7 @@ pref("identity.fxaccounts.service.monitorLoginUrl", "https://monitor.firefox.com
pref("corroborator.enabled", true);
#endif
// Disable WebIDE and ConnectPage by default (Bug 1539451)
pref("devtools.webide.enabled", false);
// Disable ConnectPage by default (Bug 1539451)
pref("devtools.connectpage.enabled", false);
// Toolbox preferences
@ -2361,15 +2360,5 @@ pref("devtools.popup.disable_autohide", false);
// should be removed.
pref("devtools.toolbox.content-frame", true);
pref("devtools.webide.templatesURL", "https://code.cdn.mozilla.net/templates/list.json");
pref("devtools.webide.autoinstallADBExtension", true);
pref("devtools.webide.autoConnectRuntime", true);
pref("devtools.webide.restoreLastProject", true);
pref("devtools.webide.enableLocalRuntime", false);
pref("devtools.webide.lastConnectedRuntime", "");
pref("devtools.webide.lastSelectedProject", "");
pref("devtools.webide.zoom", "1");
pref("devtools.webide.busyTimeout", 10000);
// FirstStartup service time-out in ms
pref("first-startup.timeout", 30000);

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

@ -815,7 +815,6 @@ add_task(async function checkAllTheFiles() {
// Keep only chrome:// files, and filter out either the devtools paths or
// the non-devtools paths:
let devtoolsPrefixes = [
"chrome://webide/",
"chrome://devtools",
"resource://devtools/",
"resource://devtools-client-jsonview/",

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

@ -74,18 +74,6 @@ let whitelist = [
errorMessage: /Property contained reference to invalid variable.*color/i,
isFromDevTools: true,
},
{
sourceName: /webide\/skin\/logs\.css$/i,
intermittent: true,
errorMessage: /Property contained reference to invalid variable.*color/i,
isFromDevTools: true,
},
{
sourceName: /webide\/skin\/logs\.css$/i,
intermittent: true,
errorMessage: /Property contained reference to invalid variable.*background/i,
isFromDevTools: true,
},
];
if (
@ -429,7 +417,7 @@ add_task(async function checkAllTheCSS() {
// filter out either the devtools paths or the non-devtools paths:
let isDevtools = SimpleTest.harnessParameters.subsuite == "devtools";
let devtoolsPathBits = ["webide", "devtools"];
let devtoolsPathBits = ["devtools"];
uris = uris.filter(
uri => isDevtools == devtoolsPathBits.some(path => uri.spec.includes(path))
);

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

@ -122,7 +122,6 @@ if (typeof Mozilla == "undefined") {
* <li>searchPrefsLink
* <li>selectedTabIcon
* <li>urlbar
* <li>webide
* </ul>
*
* Generate using the following in the Browser Console:

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

@ -258,10 +258,6 @@
#endif
@RESPATH@/browser/features/*
; [Webide Files]
@RESPATH@/browser/chrome/webide@JAREXT@
@RESPATH@/browser/chrome/webide.manifest
; [DevTools Startup Files]
@RESPATH@/browser/chrome/devtools-startup@JAREXT@
@RESPATH@/browser/chrome/devtools-startup.manifest

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

@ -35,7 +35,6 @@ module.exports = {
"client/scratchpad/**",
"client/shared/*.jsm",
"client/shared/widgets/*.jsm",
"client/webide/**",
],
"rules": {
"consistent-return": "off",
@ -44,7 +43,6 @@ module.exports = {
"files": [
"client/framework/**",
"client/scratchpad/**",
"client/webide/**",
],
"rules": {
"max-nested-callbacks": "off",
@ -63,7 +61,6 @@ module.exports = {
"client/scratchpad/**",
"client/shared/*.jsm",
"client/shared/widgets/*.jsm",
"client/webide/**",
],
"rules": {
"mozilla/no-aArgs": "off",
@ -81,7 +78,6 @@ module.exports = {
"client/framework/**",
"client/scratchpad/**",
"client/shared/widgets/*.jsm",
"client/webide/**",
],
"rules": {
"no-shadow": "off",
@ -90,7 +86,6 @@ module.exports = {
"files": [
"client/framework/**",
"client/scratchpad/**",
"client/webide/**",
],
"rules": {
"strict": "off",

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

@ -1,7 +1,7 @@
# about:debugging-new
## What is about:debugging-new
The purpose of about:debugging is to be a debugging hub to start inspecting your addons, processes, tabs and workers. This new version of about:debugging will also allow you to debug remote devices (Firefox for Android on a smartphone). The user should be able to connect either via USB or WiFi. This solution is supposed to replace the various existing remote debugging solutions available in Firefox DevTools, WebIDE and the Connect page.
The purpose of about:debugging is to be a debugging hub to start inspecting your addons, processes, tabs and workers. This new version of about:debugging will also allow you to debug remote devices (Firefox for Android on a smartphone). The user should be able to connect either via USB or WiFi.
To try out about:debugging, type `about:debugging` in the Firefox URL bar.

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

@ -294,8 +294,8 @@ function switchPerformancePanel() {
// the perf actor yet. Also this function is not async, so we can't initialize
// the actor yet.
// We don't display the new performance panel for remote context in the
// toolbox, because this has an overhead. Instead we should use WebIDE (or
// the coming about:debugging).
// toolbox, because this has an overhead. Instead we should use
// about:debugging.
return target.isLocalTab;
};
} else {

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

@ -81,7 +81,7 @@ class ToolboxToolbar extends Component {
// |hostTypes| but this is not always the case (e.g. when it is "custom").
currentHostType: PropTypes.string,
// Are docking options enabled? They are not enabled in certain situations
// like when they are in the WebIDE.
// like when the toolbox is opened in a tab.
areDockOptionsEnabled: PropTypes.bool,
// Do we need to add UI for closing the toolbox? We don't when the
// toolbox is undocked, for example.
@ -352,8 +352,8 @@ class ToolboxToolbar extends Component {
* @param {string} props.currentHostType
* The current docking configuration.
* @param {boolean} props.areDockOptionsEnabled
* They are not enabled in certain situations like when they are in the
* WebIDE.
* They are not enabled in certain situations like when the toolbox is
* in a tab.
* @param {boolean} props.canCloseToolbox
* Do we need to add UI for closing the toolbox? We don't when the
* toolbox is undocked, for example.

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

@ -14,7 +14,6 @@
const { Cc, Ci } = require("chrome");
const Services = require("Services");
const defer = require("devtools/shared/defer");
const { gDevTools } = require("./devtools");
// Load target and toolbox lazily as they need gDevTools to be fully initialized
@ -139,10 +138,6 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
}
}
// Enable WebIDE?
const webIDEEnabled = Services.prefs.getBoolPref("devtools.webide.enabled");
toggleMenuItem("menu_webide", webIDEEnabled);
// Enable Browser Toolbox?
const chromeEnabled = Services.prefs.getBoolPref("devtools.chrome.enabled");
const devtoolsRemoteEnabled = Services.prefs.getBoolPref(
@ -359,9 +354,6 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
case "toggleToolboxF12":
await gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, startTime);
break;
case "webide":
gDevToolsBrowser.openWebIDE();
break;
case "browserToolbox":
BrowserToolboxProcess.init();
break;
@ -401,26 +393,6 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
);
},
/**
* Open WebIDE
*/
// Used by browser-sets.inc, command
// itself, webide widget
openWebIDE() {
const win = Services.wm.getMostRecentWindow("devtools:webide");
if (win) {
win.focus();
} else {
Services.ww.openWindow(
null,
"chrome://webide/content/",
"webide",
"chrome,centerscreen,resizable",
null
);
}
},
async _getContentProcessTarget(processId) {
// Create a DebuggerServer in order to connect locally to it
DebuggerServer.init();
@ -514,11 +486,6 @@ var gDevToolsBrowser = (exports.gDevToolsBrowser = {
return loadPromise;
},
/**
* The deferred promise will be resolved by WebIDE's UI.init()
*/
isWebIDEInitialized: defer(),
/**
* Add this DevTools's presence to a browser window's document
*

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

@ -28,9 +28,9 @@ requestLongerTimeout(2);
* client is destroyed when the toolbox is closed, which removes the client
* actor pools, and avoids this issue.
*
* In WebIDE, we do not destroy the DebuggerClient on toolbox close because it
* is still used for other purposes like managing apps, etc. that aren't part of
* a toolbox. Thus, the same client gets reused across multiple toolboxes,
* In remote debugging, we do not destroy the DebuggerClient on toolbox close
* because it can still used for other targets.
* Thus, the same client gets reused across multiple toolboxes,
* which leads to the tools failing if they don't destroy their fronts.
*/

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

@ -215,7 +215,7 @@ about-debugging-runtime-profile-button2 = Profile performance
about-debugging-runtime-service-workers-not-compatible = Your browser configuration is not compatible with Service Workers. <a>Learn more</a>
# This string is displayed in the runtime page if the remote browser version is too old.
# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/WebIDE/Troubleshooting
# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting
# { $runtimeVersion } is the version of the remote browser (for instance "67.0a1")
# { $minVersion } is the minimum version that is compatible with the current Firefox instance (same format)
about-debugging-browser-version-too-old = The connected browser has an old version ({ $runtimeVersion }). The minimum supported version is ({ $minVersion }). This is an unsupported setup and may cause DevTools to fail. Please update the connected browser. <a>Troubleshooting</a>
@ -229,7 +229,7 @@ about-debugging-browser-version-too-old = The connected browser has an old versi
about-debugging-browser-version-too-old-67-debugger = The Debugger panel may not work with the connected browser. Please use Firefox { $runtimeVersion } if you need to use the Debugger with this browser.
# This string is displayed in the runtime page if the remote browser version is too recent.
# "Troubleshooting" link points to https://developer.mozilla.org/en-US/docs/Tools/WebIDE/Troubleshooting
# "Troubleshooting" link points to https://developer.mozilla.org/docs/Tools/about:debugging#Troubleshooting
# { $runtimeID } is the build ID of the remote browser (for instance "20181231", format is yyyyMMdd)
# { $localID } is the build ID of the current Firefox instance (same format)
# { $runtimeVersion } is the version of the remote browser (for instance "67.0a1")

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

@ -1,29 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
validator.nonExistingFolder=The project folder doesnt exist
validator.expectProjectFolder=The project folder ends up being a file
validator.noManifestFile=A manifest file is required at project root folder, named either manifest.webapp for packaged apps or manifest.json for add-ons.
validator.invalidManifestURL=Invalid manifest URL %S
# LOCALIZATION NOTE (validator.invalidManifestJSON, validator.noAccessManifestURL):
# %1$S is the error message, %2$S is the URI of the manifest.
validator.invalidManifestJSON=The webapp manifest isnt a valid JSON file: %1$S at: %2$S
validator.noAccessManifestURL=Unable to read manifest file: %1$S at: %2$S
# LOCALIZATION NOTE (validator.invalidHostedManifestURL): %1$S is the URI of
# the manifest, %2$S is the error message.
validator.invalidHostedManifestURL=Invalid hosted manifest URL %1$S: %2$S
validator.invalidProjectType=Unknown project type %S
# LOCALIZATION NOTE (validator.missNameManifestProperty, validator.missIconsManifestProperty):
# don't translate 'icons' and 'name'.
validator.missNameManifestProperty=Missing mandatory name in Manifest.
validator.missIconsManifestProperty=Missing icons in Manifest.
validator.missIconMarketplace2=app submission to the Marketplace requires a 128px icon
validator.invalidAppType=Unknown app type: %S.
validator.invalidHostedPriviledges=Hosted App cant be type %S.
validator.noCertifiedSupport=certified apps are not fully supported on the App manager.
validator.nonAbsoluteLaunchPath=Launch path has to be an absolute path starting with /: %S
validator.accessFailedLaunchPath=Unable to access the app starting document %S
# LOCALIZATION NOTE (validator.accessFailedLaunchPathBadHttpCode): %1$S is the URI of
# the launch document, %2$S is the http error code.
validator.accessFailedLaunchPathBadHttpCode=Unable to access the app starting document %1$S, got HTTP code %2$S

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

@ -49,9 +49,6 @@ browserContentToolboxMenu.accesskey = x
toggleProfilerButtonMenu.label = Enable Profiler Toolbar Icon
toggleProfilerButtonMenu.accesskey = P
webide.label = WebIDE
webide.accesskey = W
devtoolsWebReplay.label = Web Replay
devtoolsRecordNewTab.label = Open New Recording Tab
devtoolsReloadAndRecordTab.label = Reload and Record Tab

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

@ -1,153 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!ENTITY windowTitle "Firefox WebIDE">
<!ENTITY projectMenu_label "Project">
<!ENTITY projectMenu_accesskey "P">
<!ENTITY projectMenu_newApp_label "New App…">
<!ENTITY projectMenu_newApp_accesskey "N">
<!ENTITY projectMenu_importPackagedApp_label "Open Packaged App…">
<!ENTITY projectMenu_importPackagedApp_accesskey "P">
<!ENTITY projectMenu_importHostedApp_label "Open Hosted App…">
<!ENTITY projectMenu_importHostedApp_accesskey "H">
<!ENTITY projectMenu_selectApp_label "Open App…">
<!ENTITY projectMenu_selectApp_accesskey "O">
<!ENTITY projectMenu_play_label "Install and Run">
<!ENTITY projectMenu_play_accesskey "I">
<!ENTITY projectMenu_stop_label "Stop App">
<!ENTITY projectMenu_stop_accesskey "S">
<!ENTITY projectMenu_debug_label "Debug App">
<!ENTITY projectMenu_debug_accesskey "D">
<!ENTITY projectMenu_remove_label "Remove Project">
<!ENTITY projectMenu_remove_accesskey "R">
<!ENTITY projectMenu_showPrefs_label "Preferences">
<!ENTITY projectMenu_showPrefs_accesskey "e">
<!ENTITY projectMenu_manageComponents_label "Manage Extra Components">
<!ENTITY projectMenu_manageComponents_accesskey "M">
<!ENTITY projectMenu_refreshTabs_label "Refresh Tabs">
<!ENTITY runtimeMenu_label "Runtime">
<!ENTITY runtimeMenu_accesskey "R">
<!ENTITY runtimeMenu_disconnect_label "Disconnect">
<!ENTITY runtimeMenu_disconnect_accesskey "D">
<!ENTITY runtimeMenu_takeScreenshot_label "Screenshot">
<!ENTITY runtimeMenu_takeScreenshot_accesskey "S">
<!ENTITY runtimeMenu_showDetails_label "Runtime Info">
<!ENTITY runtimeMenu_showDetails_accesskey "E">
<!ENTITY runtimeMenu_showDevicePrefs_label "Device Preferences">
<!ENTITY runtimeMenu_showDevicePrefs_accesskey "D">
<!ENTITY runtimeMenu_showSettings_label "Device Settings">
<!ENTITY runtimeMenu_showSettings_accesskey "s">
<!ENTITY runtimeMenu_showPerformancePanel_label "Performance">
<!ENTITY runtimeMenu_showPerformancePanel_accesskey "p">
<!ENTITY viewMenu_label "View">
<!ENTITY viewMenu_accesskey "V">
<!ENTITY viewMenu_zoomin_label "Zoom In">
<!ENTITY viewMenu_zoomin_accesskey "I">
<!ENTITY viewMenu_zoomout_label "Zoom Out">
<!ENTITY viewMenu_zoomout_accesskey "O">
<!ENTITY viewMenu_resetzoom_label "Reset Zoom">
<!ENTITY viewMenu_resetzoom_accesskey "R">
<!ENTITY runtimeButton_label "Select Runtime">
<!-- We try to repicate Firefox' bindings: -->
<!-- quit app -->
<!ENTITY key_quit "W">
<!-- open menu -->
<!ENTITY key_showProjectPanel "O">
<!-- reload app -->
<!ENTITY key_play "R">
<!-- show toolbox -->
<!ENTITY key_toggleToolbox "VK_F12">
<!-- zoom -->
<!ENTITY key_zoomin "+">
<!ENTITY key_zoomin2 "=">
<!ENTITY key_zoomout "-">
<!ENTITY key_resetzoom "0">
<!ENTITY projectPanel_myProjects "My Projects">
<!ENTITY projectPanel_runtimeApps "Runtime Apps">
<!ENTITY projectPanel_tabs "Tabs">
<!ENTITY runtimePanel_usb "USB Devices">
<!ENTITY runtimePanel_wifi "Wi-Fi Devices">
<!ENTITY runtimePanel_other "Other">
<!ENTITY runtimePanel_nousbdevice "Cant see your device?">
<!ENTITY runtimePanel_refreshDevices_label "Refresh Devices">
<!-- Lense -->
<!ENTITY details_valid_header "valid">
<!ENTITY details_warning_header "warnings">
<!ENTITY details_error_header "errors">
<!ENTITY details_description "Description">
<!ENTITY details_location "Location">
<!ENTITY details_manifestURL "App ID">
<!ENTITY details_removeProject_button "Remove Project">
<!-- New App -->
<!ENTITY newAppWindowTitle "New App">
<!ENTITY newAppHeader "Select template">
<!ENTITY newAppLoadingTemplate "Loading templates…">
<!ENTITY newAppProjectName "Project Name:">
<!-- Decks -->
<!ENTITY deck_close "Close">
<!-- Addons -->
<!ENTITY addons_title "Extra Components">
<!ENTITY addons_aboutaddons "Open Add-ons Manager">
<!-- Prefs -->
<!ENTITY prefs_title "Preferences">
<!ENTITY prefs_general_title "General">
<!ENTITY prefs_restore "Restore Defaults">
<!ENTITY prefs_manage_components "Manage Extra Components">
<!ENTITY prefs_options_autoconnectruntime "Reconnect to previous runtime">
<!ENTITY prefs_options_autoconnectruntime_tooltip "Reconnect to previous runtime when WebIDE starts">
<!ENTITY prefs_options_rememberlastproject "Remember last project">
<!ENTITY prefs_options_rememberlastproject_tooltip "Restore previous project when WebIDE starts">
<!ENTITY prefs_options_templatesurl "Templates URL">
<!ENTITY prefs_options_templatesurl_tooltip "Index of available templates">
<!-- Runtime Details -->
<!ENTITY runtimedetails_title "Runtime Info">
<!-- Device Preferences and Settings -->
<!ENTITY device_typeboolean "Boolean">
<!ENTITY device_typenumber "Integer">
<!ENTITY device_typestring "String">
<!ENTITY device_typenone "Select a type">
<!-- Device Preferences -->
<!ENTITY devicepreference_title "Device Preferences">
<!ENTITY devicepreference_search "Search preferences">
<!ENTITY devicepreference_newname "New preference name">
<!ENTITY devicepreference_newtext "Preference value">
<!ENTITY devicepreference_addnew "Add new preference">
<!-- WiFi Authentication -->
<!-- LOCALIZATION NOTE (wifi_auth_header): The header displayed on the dialog
that instructs the user to transfer an authentication token to the
server. -->
<!ENTITY wifi_auth_header "Client Identification">
<!-- LOCALIZATION NOTE (wifi_auth_scan_request): Instructions requesting the
user to transfer authentication info by scanning a QR code. -->
<!ENTITY wifi_auth_scan_request "The endpoint you are connecting to needs more information to authenticate this connection. Please scan the QR code below via the prompt on your other device.">
<!-- LOCALIZATION NOTE (wifi_auth_no_scanner): Link text to assist users with
devices that can't scan a QR code. -->
<!ENTITY wifi_auth_no_scanner "No QR scanner prompt?">
<!-- LOCALIZATION NOTE (wifi_auth_yes_scanner): Link text to assist users with
devices that can scan a QR code. -->
<!ENTITY wifi_auth_yes_scanner "Have a QR scanner prompt?">
<!-- LOCALIZATION NOTE (wifi_auth_token_request): Instructions requesting the
user to transfer authentication info by transferring a token. -->
<!ENTITY wifi_auth_token_request "If your other device asks for a token instead of scanning a QR code, please copy the value below to the other device:">
<!ENTITY wifi_auth_qr_size_note "If the QR code appears too small for the connection to be successfully established, try zooming or enlarging the window.">
<!-- Logs panel -->
<!ENTITY logs_title "Pre-packaging Command Logs">

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

@ -1,85 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
title_noApp=Firefox WebIDE
title_app=Firefox WebIDE: %S
runtimeButton_label=Select Runtime
mainProcess_label=Main Process
local_runtime=Local Runtime
remote_runtime=Remote Runtime
remote_runtime_promptTitle=Remote Runtime
remote_runtime_promptMessage=hostname:port
importPackagedApp_title=Select Directory
importHostedApp_title=Open Hosted App
importHostedApp_header=Enter Manifest URL
selectCustomBinary_title=Select custom B2G binary
selectCustomProfile_title=Select custom Gaia profile
notification_showTroubleShooting_label=Troubleshooting
notification_showTroubleShooting_accesskey=T
# LOCALIZATION NOTE (project_tab_loading): This is shown as a temporary tab
# title for browser tab projects when the tab is still loading.
project_tab_loading=Loading…
# These messages appear in a notification box when an error occur.
error_cantInstallNotFullyConnected=Cant install project. Not fully connected.
error_cantInstallValidationErrors=Cant install project. Validation errors.
# Variable: name of the operation (in english)
error_operationTimeout=Operation timed out: %1$S
error_operationFail=Operation failed: %1$S
# Variable: app name
error_cantConnectToApp=Cant connect to app: %1$S
error_appProjectsLoadFailed=Unable to load project list. This can occur if youve used this profile with a newer version of Firefox.
error_folderCreationFailed=Unable to create project folder in the selected directory.
# Variable: runtime app build ID (looks like this %Y%M%D format) and firefox build ID (same format)
error_runtimeVersionTooRecent=The connected runtime has a more recent build date (%1$S) than your desktop Firefox (%2$S) does. This is an unsupported setup and may cause DevTools to fail. Please update Firefox.
# Variable: runtime app version (looks like this 52.a3) and firefox version (same format)
error_runtimeVersionTooOld=The connected runtime has an old version (%1$S). The minimum supported version is (%2$S). This is an unsupported setup and may cause DevTools to fail. Please update the connected runtime.
# LOCALIZATION NOTE (error_runtimeVersionTooOld67Debugger): Dedicated message
# for a backward compatibility issue that occurs when connecting:
# - from Fx 67 to 66 or to 65
# - from Fx 68 to 66
# Those are normally in range for DevTools compatibility policy, but specific non
# backward compatible changes broke the debugger in those scenarios (Bug 1528219).
# Variable: runtime app version (looks like this 52.a3)
error_runtimeVersionTooOld67Debugger=The Debugger panel may not work with the connected runtime. Please use Firefox %S if you need to use the Debugger with this runtime.
# LOCALIZATION NOTE (error_webIDEDeprecated2): Text for the deprecation message displayed when starting WebIDE.
error_webIDEDeprecated2=WebIDE will be disabled in an upcoming release. Remote debugging is now available in about:debugging.
# LOCALIZATION NOTE (notification_openAboutDebugging): Text for a button displayed in the deprecation message for WebIDE.
# Clicking on the button will open a tab on about:debugging.
notification_openAboutDebugging.label=Open about:debugging
notification_openAboutDebugging.accesskey=O
addons_install_button=install
addons_uninstall_button=uninstall
addons_adb_warning=USB devices wont be detected without this add-on
addons_status_unknown=?
addons_status_installed=Installed
addons_status_uninstalled=Not Installed
addons_status_preparing=preparing
addons_status_downloading=downloading
addons_status_installing=installing
# LOCALIZATION NOTE (runtimePanel_noadbextension): Displayed in the WebIDE right sidebar
# when the ADB Extension is not installed, %S will be replaced with the name of extension
# ("ADB Extension").
runtimePanel_noadbextension=Install %S
# Device preferences and settings
device_reset_default=Reset to default

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

@ -96,14 +96,6 @@ exports.menuitems = [
gDevToolsBrowser.openAboutDebugging(window.gBrowser);
},
},
{
id: "menu_webide",
l10nKey: "webide",
oncommand() {
gDevToolsBrowser.openWebIDE();
},
keyId: "webide",
},
{
id: "menu_browserToolbox",
l10nKey: "browserToolboxMenu",

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

@ -28,7 +28,6 @@ DIRS += [
'styleeditor',
'themes',
'webconsole',
'webide',
'webreplay',
]

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

@ -753,7 +753,6 @@ function getChartsFromToolId(id) {
case "STYLEEDITOR":
case "TOOLBOX":
case "WEBCONSOLE":
case "WEBIDE":
timerHist = `DEVTOOLS_${id}_TIME_ACTIVE_SECONDS`;
countHist = `DEVTOOLS_${id}_OPENED_COUNT`;
break;

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

@ -1,122 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { loader, require } = ChromeUtils.import(
"resource://devtools/shared/Loader.jsm"
);
const Services = require("Services");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/webide.properties"
);
const { gDevTools } = require("devtools/client/framework/devtools");
loader.lazyRequireGetter(
this,
"adbAddon",
"devtools/shared/adb/adb-addon",
true
);
window.addEventListener(
"load",
function() {
document.querySelector("#aboutaddons").onclick = function() {
const browserWin = Services.wm.getMostRecentWindow(
gDevTools.chromeWindowType
);
if (browserWin && browserWin.BrowserOpenAddonsMgr) {
browserWin.BrowserOpenAddonsMgr("addons://list/extension");
}
};
document.querySelector("#close").onclick = CloseUI;
BuildUI();
},
{ capture: true, once: true }
);
function CloseUI() {
window.parent.UI.openProject();
}
function BuildUI() {
function onAddonUpdate(arg) {
progress.removeAttribute("value");
li.setAttribute("status", adbAddon.status);
status.textContent = Strings.GetStringFromName(
"addons_status_" + adbAddon.status
);
}
function onAddonFailure(arg) {
window.parent.UI.reportError("error_operationFail", arg);
}
function onAddonProgress(arg) {
if (arg == -1) {
progress.removeAttribute("value");
} else {
progress.value = arg;
}
}
adbAddon.on("update", onAddonUpdate);
adbAddon.on("failure", onAddonFailure);
adbAddon.on("progress", onAddonProgress);
window.addEventListener(
"unload",
function() {
adbAddon.off("update", onAddonUpdate);
adbAddon.off("failure", onAddonFailure);
adbAddon.off("progress", onAddonProgress);
},
{ once: true }
);
const li = document.createElement("li");
li.setAttribute("status", adbAddon.status);
const name = document.createElement("span");
name.className = "name";
li.setAttribute("addon", "adb");
name.textContent = "ADB Extension";
li.appendChild(name);
const status = document.createElement("span");
status.className = "status";
status.textContent = Strings.GetStringFromName(
"addons_status_" + adbAddon.status
);
li.appendChild(status);
const installButton = document.createElement("button");
installButton.className = "install-button";
installButton.onclick = () => adbAddon.install("webide");
installButton.textContent = Strings.GetStringFromName(
"addons_install_button"
);
li.appendChild(installButton);
const uninstallButton = document.createElement("button");
uninstallButton.className = "uninstall-button";
uninstallButton.onclick = () => adbAddon.uninstall();
uninstallButton.textContent = Strings.GetStringFromName(
"addons_uninstall_button"
);
li.appendChild(uninstallButton);
const progress = document.createElement("progress");
li.appendChild(progress);
const warning = document.createElement("p");
warning.textContent = Strings.GetStringFromName("addons_adb_warning");
warning.className = "warning";
li.appendChild(warning);
document.querySelector("ul").appendChild(li);
}

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

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf8"/>
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
<link rel="stylesheet" href="chrome://webide/skin/addons.css" type="text/css"/>
<script src="chrome://webide/content/addons.js"></script>
</head>
<body>
<div id="controls">
<a id="aboutaddons">&addons_aboutaddons;</a>
<a id="close">&deck_close;</a>
</div>
<h1>&addons_title;</h1>
<ul></ul>
</body>
</html>

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

@ -1,131 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const { AppManager } = require("devtools/client/webide/modules/app-manager");
window.addEventListener(
"load",
function() {
document.addEventListener("visibilitychange", updateUI, true);
AppManager.on("app-manager-update", onAppManagerUpdate);
updateUI();
},
{ capture: true, once: true }
);
window.addEventListener(
"unload",
function() {
AppManager.off("app-manager-update", onAppManagerUpdate);
},
{ capture: true, once: true }
);
function onAppManagerUpdate(what, details) {
if (what == "project" || what == "project-validated") {
updateUI();
}
}
function resetUI() {
document.querySelector("#toolbar").classList.add("hidden");
document.querySelector("#type").classList.add("hidden");
document.querySelector("#descriptionHeader").classList.add("hidden");
document.querySelector("#manifestURLHeader").classList.add("hidden");
document.querySelector("#locationHeader").classList.add("hidden");
document.body.className = "";
document.querySelector("#icon").src = "";
document.querySelector("h1").textContent = "";
document.querySelector("#description").textContent = "";
document.querySelector("#type").textContent = "";
document.querySelector("#manifestURL").textContent = "";
document.querySelector("#location").textContent = "";
document.querySelector("#errorslist").innerHTML = "";
document.querySelector("#warningslist").innerHTML = "";
}
function updateUI() {
resetUI();
const project = AppManager.selectedProject;
if (!project) {
return;
}
if (project.type != "runtimeApp" && project.type != "mainProcess") {
document.querySelector("#toolbar").classList.remove("hidden");
document.querySelector("#locationHeader").classList.remove("hidden");
document.querySelector("#location").textContent = project.location;
}
document.body.className = project.validationStatus;
document.querySelector("#icon").src = project.icon;
document.querySelector("h1").textContent = project.name;
let manifest;
if (project.type == "runtimeApp") {
manifest = project.app.manifest;
} else {
manifest = project.manifest;
}
if (manifest) {
if (manifest.description) {
document.querySelector("#descriptionHeader").classList.remove("hidden");
document.querySelector("#description").textContent = manifest.description;
}
document.querySelector("#type").classList.remove("hidden");
if (project.type == "runtimeApp") {
const manifestURL = AppManager.getProjectManifestURL(project);
document.querySelector("#type").textContent = manifest.type || "web";
document.querySelector("#manifestURLHeader").classList.remove("hidden");
document.querySelector("#manifestURL").textContent = manifestURL;
} else if (project.type == "mainProcess") {
document.querySelector("#type").textContent = project.name;
} else {
document.querySelector("#type").textContent =
project.type + " " + (manifest.type || "web");
}
if (project.type == "packaged") {
const manifestURL = AppManager.getProjectManifestURL(project);
if (manifestURL) {
document.querySelector("#manifestURLHeader").classList.remove("hidden");
document.querySelector("#manifestURL").textContent = manifestURL;
}
}
}
const errorsNode = document.querySelector("#errorslist");
const warningsNode = document.querySelector("#warningslist");
if (project.errors) {
for (const e of project.errors) {
const li = document.createElement("li");
li.textContent = e;
errorsNode.appendChild(li);
}
}
if (project.warnings) {
for (const w of project.warnings) {
const li = document.createElement("li");
li.textContent = w;
warningsNode.appendChild(li);
}
}
AppManager.update("details");
}
// Used in details.xhtml.
/* exported removeProject */
function removeProject() {
AppManager.removeSelectedProject();
}

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

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf8"/>
<link rel="stylesheet" href="chrome://webide/skin/details.css" type="text/css"/>
<script src="chrome://webide/content/details.js"></script>
</head>
<body>
<div id="toolbar">
<button onclick="removeProject()">&details_removeProject_button;</button>
<p id="validation_status">
<span class="valid">&details_valid_header;</span>
<span class="warning">&details_warning_header;</span>
<span class="error">&details_error_header;</span>
</p>
</div>
<header>
<img id="icon"></img>
<div>
<h1></h1>
<p id="type"></p>
</div>
</header>
<main>
<h3 id="descriptionHeader">&details_description;</h3>
<p id="description"></p>
<h3 id="locationHeader">&details_location;</h3>
<p id="location"></p>
<h3 id="manifestURLHeader">&details_manifestURL;</h3>
<p id="manifestURL"></p>
</main>
<ul class="validation_messages" id="errorslist"></ul>
<ul class="validation_messages" id="warningslist"></ul>
</body>
</html>

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

@ -1,93 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const { AppManager } = require("devtools/client/webide/modules/app-manager");
const { Connection } = require("devtools/shared/client/connection-manager");
const ConfigView = require("devtools/client/webide/modules/config-view");
var configView = new ConfigView(window);
window.addEventListener(
"load",
function() {
AppManager.on("app-manager-update", OnAppManagerUpdate);
document.getElementById("close").onclick = CloseUI;
document.getElementById("device-fields").onchange = UpdateField;
document.getElementById("device-fields").onclick = CheckReset;
document.getElementById("search-bar").onkeyup = document.getElementById(
"search-bar"
).onclick = SearchField;
document.getElementById("custom-value").onclick = UpdateNewField;
document.getElementById("custom-value-type").onchange = ClearNewFields;
document.getElementById("add-custom-field").onkeyup = CheckNewFieldSubmit;
BuildUI();
},
{ capture: true, once: true }
);
window.addEventListener(
"unload",
function() {
AppManager.off("app-manager-update", OnAppManagerUpdate);
},
{ once: true }
);
function CloseUI() {
window.parent.UI.openProject();
}
function OnAppManagerUpdate(what) {
if (what == "connection" || what == "runtime-global-actors") {
BuildUI();
}
}
function CheckNewFieldSubmit(event) {
configView.checkNewFieldSubmit(event);
}
function UpdateNewField() {
configView.updateNewField();
}
function ClearNewFields() {
configView.clearNewFields();
}
function CheckReset(event) {
configView.checkReset(event);
}
function UpdateField(event) {
configView.updateField(event);
}
function SearchField(event) {
configView.search(event);
}
// Used by tests
/* exported getAllPrefs */
var getAllPrefs;
function BuildUI() {
configView.resetTable();
if (
AppManager.connection &&
AppManager.connection.status == Connection.Status.CONNECTED &&
AppManager.preferenceFront
) {
configView.front = AppManager.preferenceFront;
configView.kind = "Pref";
configView.includeTypeName = true;
getAllPrefs = AppManager.preferenceFront
.getAllPrefs()
.then(json => configView.generateDisplay(json));
} else {
CloseUI();
}
}

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

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf8"/>
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
<link rel="stylesheet" href="chrome://webide/skin/config-view.css" type="text/css"/>
<script src="chrome://webide/content/devicepreferences.js"></script>
</head>
<body>
<header>
<div id="controls">
<a id="close">&deck_close;</a>
</div>
<h1>&devicepreference_title;</h1>
<div id="search">
<input type="text" id="search-bar" placeholder="&devicepreference_search;"/>
</div>
</header>
<table id="device-fields">
<tr id="add-custom-field">
<td>
<select id="custom-value-type">
<option value="" selected="selected">&device_typenone;</option>
<option value="boolean">&device_typeboolean;</option>
<option value="number">&device_typenumber;</option>
<option value="string">&device_typestring;</option>
</select>
<input type="text" id="custom-value-name" placeholder="&devicepreference_newname;"/>
</td>
<td class="custom-input">
<input type="text" id="custom-value-text" placeholder="&devicepreference_newtext;"/>
</td>
<td>
<button id="custom-value" class="new-editable">&devicepreference_addnew;</button>
</td>
</tr>
</table>
</body>
</html>

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

@ -1,28 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
webide.jar:
% content webide %content/
content/webide.xul (webide.xul)
content/webide.js (webide.js)
content/newapp.xul (newapp.xul)
content/newapp.js (newapp.js)
content/details.xhtml (details.xhtml)
content/details.js (details.js)
content/addons.js (addons.js)
content/addons.xhtml (addons.xhtml)
content/runtimedetails.js (runtimedetails.js)
content/runtimedetails.xhtml (runtimedetails.xhtml)
content/prefs.js (prefs.js)
content/prefs.xhtml (prefs.xhtml)
content/devicepreferences.js (devicepreferences.js)
content/devicepreferences.xhtml (devicepreferences.xhtml)
content/wifi-auth.js (wifi-auth.js)
content/wifi-auth.xhtml (wifi-auth.xhtml)
content/project-listing.xhtml (project-listing.xhtml)
content/project-listing.js (project-listing.js)
content/project-panel.js (project-panel.js)
content/runtime-panel.js (runtime-panel.js)
content/runtime-listing.xhtml (runtime-listing.xhtml)
content/runtime-listing.js (runtime-listing.js)

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

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf8"/>
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
<link rel="stylesheet" href="resource://devtools/client/themes/common.css" type="text/css"/>
<link rel="stylesheet" href="chrome://webide/skin/logs.css" type="text/css"/>
<script src="chrome://devtools/content/shared/theme-switching.js"></script>
<script src="logs.js"></script>
</head>
<body>
<div id="controls">
<a id="close">&deck_close;</a>
</div>
<h1>&logs_title;</h1>
<ul id="logs" class="devtools-monospace">
</ul>
</body>
</html>

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

@ -1,7 +0,0 @@
# -*- Mode: python; 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/.
JAR_MANIFESTS += ['jar.mn']

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

@ -1,192 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const Services = require("Services");
const { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
const { AppProjects } = require("devtools/client/webide/modules/app-projects");
const { AppManager } = require("devtools/client/webide/modules/app-manager");
const { getJSON } = require("devtools/client/shared/getjson");
ChromeUtils.defineModuleGetter(
this,
"ZipUtils",
"resource://gre/modules/ZipUtils.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"Downloads",
"resource://gre/modules/Downloads.jsm"
);
const TEMPLATES_URL = "devtools.webide.templatesURL";
var gTemplateList = null;
window.addEventListener(
"load",
function() {
const projectNameNode = document.querySelector("#project-name");
projectNameNode.addEventListener("input", canValidate, true);
getTemplatesJSON();
document.addEventListener("dialogaccept", doOK);
},
{ capture: true, once: true }
);
function getTemplatesJSON() {
getJSON(TEMPLATES_URL).then(
list => {
if (!Array.isArray(list)) {
throw new Error("JSON response not an array");
}
if (list.length == 0) {
throw new Error("JSON response is an empty array");
}
gTemplateList = list;
const templatelistNode = document.querySelector("#templatelist");
templatelistNode.innerHTML = "";
for (const template of list) {
const richlistitemNode = document.createXULElement("richlistitem");
const imageNode = document.createXULElement("image");
imageNode.setAttribute("src", template.icon);
const labelNode = document.createXULElement("label");
labelNode.setAttribute("value", template.name);
const descriptionNode = document.createXULElement("description");
descriptionNode.textContent = template.description;
const vboxNode = document.createXULElement("vbox");
vboxNode.setAttribute("flex", "1");
richlistitemNode.appendChild(imageNode);
vboxNode.appendChild(labelNode);
vboxNode.appendChild(descriptionNode);
richlistitemNode.appendChild(vboxNode);
templatelistNode.appendChild(richlistitemNode);
}
templatelistNode.selectedIndex = 0;
/* Chrome mochitest support */
const testOptions = window.arguments[0].testOptions;
if (testOptions) {
templatelistNode.selectedIndex = testOptions.index;
document.querySelector("#project-name").value = testOptions.name;
doOK();
}
},
e => {
failAndBail("Can't download app templates: " + e);
}
);
}
function failAndBail(msg) {
Services.prompt.alert(window, "error", msg);
window.close();
}
function canValidate() {
const projectNameNode = document.querySelector("#project-name");
const dialogNode = document.querySelector("dialog");
if (projectNameNode.value.length > 0) {
dialogNode.removeAttribute("buttondisabledaccept");
} else {
dialogNode.setAttribute("buttondisabledaccept", "true");
}
}
function doOK(event) {
const projectName = document.querySelector("#project-name").value;
if (!projectName) {
console.error("No project name");
event.preventDefault();
return;
}
if (!gTemplateList) {
console.error("No template index");
event.preventDefault();
return;
}
const templatelistNode = document.querySelector("#templatelist");
if (templatelistNode.selectedIndex < 0) {
console.error("No template selected");
event.preventDefault();
return;
}
/* Chrome mochitest support */
const promise = new Promise((resolve, reject) => {
const testOptions = window.arguments[0].testOptions;
if (testOptions) {
resolve(testOptions.folder);
} else {
const fp = Cc["@mozilla.org/filepicker;1"].createInstance(
Ci.nsIFilePicker
);
fp.init(
window,
"Select directory where to create app directory",
Ci.nsIFilePicker.modeGetFolder
);
fp.open(res => {
if (res == Ci.nsIFilePicker.returnCancel) {
console.error("No directory selected");
reject(null);
} else {
resolve(fp.file);
}
});
}
});
const bail = e => {
console.error(e);
window.close();
};
promise.then(folder => {
// Create subfolder with fs-friendly name of project
const subfolder = projectName.replace(/[\\/:*?"<>|]/g, "").toLowerCase();
const win = Services.wm.getMostRecentWindow("devtools:webide");
folder.append(subfolder);
try {
folder.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
} catch (e) {
win.UI.reportError("error_folderCreationFailed");
window.close();
return;
}
// Download boilerplate zip
const template = gTemplateList[templatelistNode.selectedIndex];
const source = template.file;
const target = folder.clone();
target.append(subfolder + ".zip");
Downloads.fetch(source, target).then(() => {
ZipUtils.extractFiles(target, folder);
target.remove(false);
AppProjects.addPackaged(folder).then(project => {
window.arguments[0].location = project.location;
AppManager.validateAndUpdateProject(project).then(() => {
if (project.manifest) {
project.manifest.name = projectName;
AppManager.writeManifest(project).then(() => {
AppManager.validateAndUpdateProject(project).then(() => {
window.close();
}, bail);
}, bail);
} else {
bail("Manifest not found");
}
}, bail);
}, bail);
}, bail);
}, bail);
event.preventDefault();
}

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

@ -1,32 +0,0 @@
<?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/. -->
<!DOCTYPE window [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://webide/skin/newapp.css"?>
<dialog id="webide:newapp" title="&newAppWindowTitle;"
width="600" height="400"
buttons="accept,cancel"
buttondisabledaccept="true"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="newapp.js"></script>
<label class="header-name" value="&newAppHeader;"/>
<richlistbox id="templatelist" flex="1">
<description>&newAppLoadingTemplate;</description>
</richlistbox>
<vbox>
<label class="header-name" control="project-name" value="&newAppProjectName;"/>
<textbox id="project-name"/>
</vbox>
</dialog>

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

@ -1,111 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
window.addEventListener(
"load",
function() {
// Listen to preference changes
const inputs = document.querySelectorAll("[data-pref]");
for (const i of inputs) {
const pref = i.dataset.pref;
Services.prefs.addObserver(pref, FillForm);
i.addEventListener("change", SaveForm);
}
// Buttons
document.querySelector("#close").onclick = CloseUI;
document.querySelector("#restore").onclick = RestoreDefaults;
document.querySelector("#manageComponents").onclick = ShowAddons;
// Initialize the controls
FillForm();
},
{ capture: true, once: true }
);
window.addEventListener(
"unload",
function() {
const inputs = document.querySelectorAll("[data-pref]");
for (const i of inputs) {
const pref = i.dataset.pref;
i.removeEventListener("change", SaveForm);
Services.prefs.removeObserver(pref, FillForm);
}
},
{ capture: true, once: true }
);
function CloseUI() {
window.parent.UI.openProject();
}
function ShowAddons() {
window.parent.Cmds.showAddons();
}
function FillForm() {
const inputs = document.querySelectorAll("[data-pref]");
for (const i of inputs) {
const pref = i.dataset.pref;
const val = GetPref(pref);
if (i.type == "checkbox") {
i.checked = val;
} else {
i.value = val;
}
}
}
function SaveForm(e) {
const inputs = document.querySelectorAll("[data-pref]");
for (const i of inputs) {
const pref = i.dataset.pref;
if (i.type == "checkbox") {
SetPref(pref, i.checked);
} else {
SetPref(pref, i.value);
}
}
}
function GetPref(name) {
const type = Services.prefs.getPrefType(name);
switch (type) {
case Services.prefs.PREF_STRING:
return Services.prefs.getCharPref(name);
case Services.prefs.PREF_INT:
return Services.prefs.getIntPref(name);
case Services.prefs.PREF_BOOL:
return Services.prefs.getBoolPref(name);
default:
throw new Error("Unknown type");
}
}
function SetPref(name, value) {
const type = Services.prefs.getPrefType(name);
switch (type) {
case Services.prefs.PREF_STRING:
return Services.prefs.setCharPref(name, value);
case Services.prefs.PREF_INT:
return Services.prefs.setIntPref(name, value);
case Services.prefs.PREF_BOOL:
return Services.prefs.setBoolPref(name, value);
default:
throw new Error("Unknown type");
}
}
function RestoreDefaults() {
const inputs = document.querySelectorAll("[data-pref]");
for (const i of inputs) {
const pref = i.dataset.pref;
Services.prefs.clearUserPref(pref);
}
}

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

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf8"/>
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
<script src="chrome://webide/content/prefs.js"></script>
</head>
<body>
<div id="controls">
<a id="restore">&prefs_restore;</a>
<a id="manageComponents">&prefs_manage_components;</a>
<a id="close">&deck_close;</a>
</div>
<h1>&prefs_title;</h1>
<h2>&prefs_general_title;</h2>
<ul>
<li>
<label title="&prefs_options_rememberlastproject_tooltip;">
<input type="checkbox" data-pref="devtools.webide.restoreLastProject"/>
<span>&prefs_options_rememberlastproject;</span>
</label>
</li>
<li>
<label title="&prefs_options_autoconnectruntime_tooltip;">
<input type="checkbox" data-pref="devtools.webide.autoConnectRuntime"/>
<span>&prefs_options_autoconnectruntime;</span>
</label>
</li>
<li>
<label class="text-input" title="&prefs_options_templatesurl_tooltip;">
<span>&prefs_options_templatesurl;</span>
<input data-pref="devtools.webide.templatesURL"/>
</label>
</li>
</ul>
</body>
</html>

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

@ -1,47 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env browser */
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const ProjectList = require("devtools/client/webide/modules/project-list");
var projectList = new ProjectList(window, window.parent);
window.addEventListener(
"load",
function() {
document.getElementById("new-app").onclick = CreateNewApp;
document.getElementById("hosted-app").onclick = ImportHostedApp;
document.getElementById("packaged-app").onclick = ImportPackagedApp;
document.getElementById("refresh-tabs").onclick = RefreshTabs;
projectList.update();
projectList.updateCommands();
},
{ capture: true, once: true }
);
window.addEventListener(
"unload",
function() {
projectList.destroy();
},
{ once: true }
);
function RefreshTabs() {
projectList.refreshTabs();
}
function CreateNewApp() {
projectList.newApp();
}
function ImportHostedApp() {
projectList.importHostedApp();
}
function ImportPackagedApp() {
projectList.importPackagedApp();
}

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

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf8"/>
<link rel="stylesheet" href="chrome://webide/skin/panel-listing.css" type="text/css"/>
<script src="chrome://webide/content/project-listing.js"></script>
</head>
<body>
<div id="project-panel">
<div id="project-panel-box">
<button class="panel-item project-panel-item-newapp" id="new-app">&projectMenu_newApp_label;</button>
<button class="panel-item project-panel-item-openpackaged" id="packaged-app">&projectMenu_importPackagedApp_label;</button>
<button class="panel-item project-panel-item-openhosted" id="hosted-app">&projectMenu_importHostedApp_label;</button>
<label class="panel-header">&projectPanel_myProjects;</label>
<div id="project-panel-projects"></div>
<label class="panel-header" id="panel-header-runtimeapps" hidden="true">&projectPanel_runtimeApps;</label>
<div id="project-panel-runtimeapps"/>
<label class="panel-header" id="panel-header-tabs" hidden="true">&projectPanel_tabs;
<button class="project-panel-item-refreshtabs refresh-icon" id="refresh-tabs" title="&projectMenu_refreshTabs_label;"></button>
</label>
<div id="project-panel-tabs"/>
</div>
</div>
</body>
</html>

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

@ -1,16 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* exported ProjectPanel */
var ProjectPanel = {
// TODO: Expand function to save toggle state.
toggleSidebar: function() {
document
.querySelector("#project-listing-panel")
.setAttribute("sidebar-displayed", true);
document
.querySelector("#project-listing-splitter")
.setAttribute("sidebar-displayed", true);
},
};

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

@ -1,78 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const RuntimeList = require("devtools/client/webide/modules/runtime-list");
var runtimeList = new RuntimeList(window, window.parent);
window.addEventListener(
"load",
function() {
document.getElementById("runtime-screenshot").onclick = TakeScreenshot;
document.getElementById("runtime-details").onclick = ShowRuntimeDetails;
document.getElementById("runtime-disconnect").onclick = DisconnectRuntime;
document.getElementById(
"runtime-preferences"
).onclick = ShowDevicePreferences;
document.getElementById("runtime-settings").onclick = ShowSettings;
document.getElementById(
"runtime-performance"
).onclick = ShowPerformancePanel;
document.getElementById(
"runtime-panel-noadbextension"
).onclick = ShowAddons;
document.getElementById(
"runtime-panel-nousbdevice"
).onclick = ShowTroubleShooting;
document.getElementById("refresh-devices").onclick = RefreshScanners;
runtimeList.update();
runtimeList.updateCommands();
},
{ capture: true, once: true }
);
window.addEventListener(
"unload",
function() {
runtimeList.destroy();
},
{ once: true }
);
function TakeScreenshot() {
runtimeList.takeScreenshot();
}
function ShowRuntimeDetails() {
runtimeList.showRuntimeDetails();
}
function ShowDevicePreferences() {
runtimeList.showDevicePreferences();
}
function ShowSettings() {
runtimeList.showSettings();
}
function ShowPerformancePanel() {
runtimeList.showPerformancePanel();
}
function RefreshScanners() {
runtimeList.refreshScanners();
}
function DisconnectRuntime() {
window.parent.Cmds.disconnectRuntime();
}
function ShowAddons() {
runtimeList.showAddons();
}
function ShowTroubleShooting() {
runtimeList.showTroubleShooting();
}

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

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf8"/>
<link rel="stylesheet" href="chrome://webide/skin/panel-listing.css" type="text/css"/>
<script src="chrome://webide/content/runtime-listing.js"></script>
</head>
<body>
<div id="runtime-panel">
<div id="runtime-panel-box">
<label class="panel-header">&runtimePanel_usb;
<button class="runtime-panel-item-refreshdevices refresh-icon" id="refresh-devices" title="&runtimePanel_refreshDevices_label;"></button>
</label>
<button class="panel-item" id="runtime-panel-nousbdevice">&runtimePanel_nousbdevice;</button>
<button class="panel-item" id="runtime-panel-noadbextension"></button>
<div id="runtime-panel-usb"></div>
<label class="panel-header" id="runtime-header-wifi">&runtimePanel_wifi;</label>
<div id="runtime-panel-wifi"></div>
<label class="panel-header">&runtimePanel_other;</label>
<div id="runtime-panel-other"></div>
<div id="runtime-actions">
<button class="panel-item" id="runtime-details">&runtimeMenu_showDetails_label;</button>
<button class="panel-item" id="runtime-preferences">&runtimeMenu_showDevicePrefs_label;</button>
<button class="panel-item" id="runtime-settings">&runtimeMenu_showSettings_label;</button>
<button class="panel-item" id="runtime-performance">&runtimeMenu_showPerformancePanel_label;</button>
<button class="panel-item" id="runtime-screenshot">&runtimeMenu_takeScreenshot_label;</button>
<button class="panel-item" id="runtime-disconnect">&runtimeMenu_disconnect_label;</button>
</div>
</div>
</div>
</body>
</html>

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

@ -1,16 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* exported RuntimePanel */
var RuntimePanel = {
// TODO: Expand function to save toggle state.
toggleSidebar: function() {
document
.querySelector("#runtime-listing-panel")
.setAttribute("sidebar-displayed", true);
document
.querySelector("#runtime-listing-splitter")
.setAttribute("sidebar-displayed", true);
},
};

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

@ -1,68 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const { AppManager } = require("devtools/client/webide/modules/app-manager");
const { Connection } = require("devtools/shared/client/connection-manager");
window.addEventListener(
"load",
function() {
document.querySelector("#close").onclick = CloseUI;
AppManager.on("app-manager-update", OnAppManagerUpdate);
BuildUI();
},
{ capture: true, once: true }
);
window.addEventListener(
"unload",
function() {
AppManager.off("app-manager-update", OnAppManagerUpdate);
},
{ once: true }
);
function CloseUI() {
window.parent.UI.openProject();
}
function OnAppManagerUpdate(what) {
if (what == "connection" || what == "runtime-global-actors") {
BuildUI();
}
}
function generateFields(json) {
const table = document.querySelector("table");
for (const name in json) {
const tr = document.createElement("tr");
let td = document.createElement("td");
td.textContent = name;
tr.appendChild(td);
td = document.createElement("td");
td.textContent = json[name];
tr.appendChild(td);
table.appendChild(tr);
}
}
// Used by tests
/* exported getDescriptionPromise */
var getDescriptionPromise;
function BuildUI() {
const table = document.querySelector("table");
table.innerHTML = "";
if (
AppManager.connection &&
AppManager.connection.status == Connection.Status.CONNECTED &&
AppManager.deviceFront
) {
getDescriptionPromise = AppManager.deviceFront
.getDescription()
.then(json => generateFields(json));
} else {
CloseUI();
}
}

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

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf8"/>
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
<link rel="stylesheet" href="chrome://webide/skin/runtimedetails.css" type="text/css"/>
<script src="chrome://webide/content/runtimedetails.js"></script>
</head>
<body>
<div id="controls">
<a id="close">&deck_close;</a>
</div>
<h1>&runtimedetails_title;</h1>
<table></table>
</body>
</html>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -1,168 +0,0 @@
<?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/. -->
<!DOCTYPE window [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="resource://devtools/client/themes/common.css"?>
<?xml-stylesheet href="chrome://webide/skin/webide.css"?>
<window id="webide"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
title="&windowTitle;"
windowtype="devtools:webide"
macanimationtype="document"
fullscreenbutton="true"
screenX="4" screenY="4"
width="800" height="600"
persist="screenX screenY width height sizemode">
<script src="chrome://global/content/globalOverlay.js"></script>
<script src="project-panel.js"></script>
<script src="runtime-panel.js"></script>
<script src="webide.js"></script>
<script src="chrome://global/content/editMenuOverlay.js"/>
<commandset id="mainCommandSet">
<commandset id="webideCommands">
<command id="cmd_quit" oncommand="Cmds.quit()"/>
<command id="cmd_newApp" oncommand="Cmds.newApp()" label="&projectMenu_newApp_label;"/>
<command id="cmd_importPackagedApp" oncommand="Cmds.importPackagedApp()" label="&projectMenu_importPackagedApp_label;"/>
<command id="cmd_importHostedApp" oncommand="Cmds.importHostedApp()" label="&projectMenu_importHostedApp_label;"/>
<command id="cmd_showDevicePrefs" label="&runtimeMenu_showDevicePrefs_label;" oncommand="Cmds.showDevicePrefs()"/>
<command id="cmd_showPerformancePanel" label="&runtimeMenu_showPerformancePanel_label;" oncommand="Cmds.showPerformancePanel()"/>
<command id="cmd_showSettings" label="&runtimeMenu_showSettings_label;" oncommand="Cmds.showSettings()"/>
<command id="cmd_removeProject" oncommand="Cmds.removeProject()" label="&projectMenu_remove_label;"/>
<command id="cmd_showProjectPanel" oncommand="Cmds.showProjectPanel()"/>
<command id="cmd_showRuntimePanel" oncommand="Cmds.showRuntimePanel()"/>
<command id="cmd_disconnectRuntime" oncommand="Cmds.disconnectRuntime()" label="&runtimeMenu_disconnect_label;"/>
<command id="cmd_showRuntimeDetails" oncommand="Cmds.showRuntimeDetails()" label="&runtimeMenu_showDetails_label;"/>
<command id="cmd_takeScreenshot" oncommand="Cmds.takeScreenshot()" label="&runtimeMenu_takeScreenshot_label;"/>
<command id="cmd_showAddons" oncommand="Cmds.showAddons()"/>
<command id="cmd_showPrefs" oncommand="Cmds.showPrefs()"/>
<command id="cmd_showTroubleShooting" oncommand="Cmds.showTroubleShooting()"/>
<command id="cmd_play" oncommand="Cmds.play()"/>
<command id="cmd_stop" oncommand="Cmds.stop()" label="&projectMenu_stop_label;"/>
<command id="cmd_toggleToolbox" oncommand="Cmds.toggleToolbox()"/>
<command id="cmd_zoomin" label="&viewMenu_zoomin_label;" oncommand="Cmds.zoomIn()"/>
<command id="cmd_zoomout" label="&viewMenu_zoomout_label;" oncommand="Cmds.zoomOut()"/>
<command id="cmd_resetzoom" label="&viewMenu_resetzoom_label;" oncommand="Cmds.resetZoom()"/>
</commandset>
</commandset>
<toolbar type="menubar">
<menubar id="main-menubar">
<menu id="menu-project" label="&projectMenu_label;" accesskey="&projectMenu_accesskey;">
<menupopup id="menu-project-popup">
<menuitem command="cmd_newApp" accesskey="&projectMenu_newApp_accesskey;"/>
<menuitem command="cmd_importPackagedApp" accesskey="&projectMenu_importPackagedApp_accesskey;"/>
<menuitem command="cmd_importHostedApp" accesskey="&projectMenu_importHostedApp_accesskey;"/>
<menuitem id="menuitem-show_projectPanel" command="cmd_showProjectPanel" key="key_showProjectPanel" label="&projectMenu_selectApp_label;" accesskey="&projectMenu_selectApp_accesskey;"/>
<menuseparator/>
<menuitem command="cmd_play" key="key_play" label="&projectMenu_play_label;" accesskey="&projectMenu_play_accesskey;"/>
<menuitem command="cmd_stop" accesskey="&projectMenu_stop_accesskey;"/>
<menuitem command="cmd_toggleToolbox" key="key_toggleToolbox" label="&projectMenu_debug_label;" accesskey="&projectMenu_debug_accesskey;"/>
<menuseparator/>
<menuitem command="cmd_removeProject" accesskey="&projectMenu_remove_accesskey;"/>
<menuseparator/>
<menuitem command="cmd_showPrefs" label="&projectMenu_showPrefs_label;" accesskey="&projectMenu_showPrefs_accesskey;"/>
<menuitem command="cmd_showAddons" label="&projectMenu_manageComponents_label;" accesskey="&projectMenu_manageComponents_accesskey;"/>
</menupopup>
</menu>
<menu id="menu-runtime" label="&runtimeMenu_label;" accesskey="&runtimeMenu_accesskey;">
<menupopup id="menu-runtime-popup">
<menuitem command="cmd_takeScreenshot" accesskey="&runtimeMenu_takeScreenshot_accesskey;"/>
<menuitem command="cmd_showRuntimeDetails" accesskey="&runtimeMenu_showDetails_accesskey;"/>
<menuitem command="cmd_showDevicePrefs" accesskey="&runtimeMenu_showDevicePrefs_accesskey;"/>
<menuitem command="cmd_showSettings" accesskey="&runtimeMenu_showSettings_accesskey;"/>
<menuitem command="cmd_showPerformancePanel" accesskey="&runtimeMenu_showPerformancePanel_accesskey;"/>
<menuseparator/>
<menuitem command="cmd_disconnectRuntime" accesskey="&runtimeMenu_disconnect_accesskey;"/>
</menupopup>
</menu>
<menu id="menu-view" label="&viewMenu_label;" accesskey="&viewMenu_accesskey;">
<menupopup id="menu-ViewPopup">
<menuseparator/>
<menuitem command="cmd_zoomin" key="key_zoomin" accesskey="&viewMenu_zoomin_accesskey;"/>
<menuitem command="cmd_zoomout" key="key_zoomout" accesskey="&viewMenu_zoomout_accesskey;"/>
<menuitem command="cmd_resetzoom" key="key_resetzoom" accesskey="&viewMenu_resetzoom_accesskey;"/>
</menupopup>
</menu>
</menubar>
</toolbar>
<keyset id="mainKeyset">
<key key="&key_quit;" id="key_quit" command="cmd_quit" modifiers="accel"/>
<key key="&key_showProjectPanel;" id="key_showProjectPanel" command="cmd_showProjectPanel" modifiers="accel"/>
<key key="&key_play;" id="key_play" command="cmd_play" modifiers="accel"/>
<key keycode="&key_toggleToolbox;" id="key_toggleToolbox" command="cmd_toggleToolbox"/>
<key key="&key_zoomin;" id="key_zoomin" command="cmd_zoomin" modifiers="accel"/>
<key key="&key_zoomin2;" id="key_zoomin2" command="cmd_zoomin" modifiers="accel"/>
<key key="&key_zoomout;" id="key_zoomout" command="cmd_zoomout" modifiers="accel"/>
<key key="&key_resetzoom;" id="key_resetzoom" command="cmd_resetzoom" modifiers="accel"/>
</keyset>
<tooltip id="aHTMLTooltip" page="true"/>
<toolbar id="main-toolbar">
<vbox flex="1">
<hbox id="action-buttons-container" class="busy">
<toolbarbutton id="action-button-play" class="action-button" command="cmd_play" tooltiptext="&projectMenu_play_label;"/>
<toolbarbutton id="action-button-stop" class="action-button" command="cmd_stop" tooltiptext="&projectMenu_stop_label;"/>
<toolbarbutton id="action-button-debug" class="action-button" command="cmd_toggleToolbox" tooltiptext="&projectMenu_debug_label;"/>
<hbox id="action-busy" align="center">
<html:img id="action-busy-undetermined" src="chrome://webide/skin/throbber.svg"/>
<html:progress id="action-busy-determined"/>
</hbox>
</hbox>
<hbox id="panel-buttons-container">
<spacer flex="1"/>
<toolbarbutton id="runtime-panel-button" class="panel-button">
<image class="panel-button-image"/>
<label class="panel-button-label" value="&runtimeButton_label;"/>
</toolbarbutton>
</hbox>
</vbox>
</toolbar>
<vbox flex="1" id="containerbox">
<div flex="1" id="deck-panels">
<vbox id="project-listing-panel" class="project-listing panel-list" flex="1">
<div id="project-listing-wrapper" class="panel-list-wrapper">
<iframe id="project-listing-panel-details" flex="1" src="project-listing.xhtml" tooltip="aHTMLTooltip"/>
</div>
</vbox>
<splitter class="devtools-side-splitter" id="project-listing-splitter"/>
<deck flex="1" id="deck" selectedIndex="-1">
<iframe id="deck-panel-details" flex="1" src="details.xhtml"/>
<iframe id="deck-panel-addons" flex="1" src="addons.xhtml"/>
<iframe id="deck-panel-prefs" flex="1" src="prefs.xhtml"/>
<iframe id="deck-panel-runtimedetails" flex="1" lazysrc="runtimedetails.xhtml"/>
<iframe id="deck-panel-devicepreferences" flex="1" lazysrc="devicepreferences.xhtml"/>
<iframe id="deck-panel-performance" flex="1" lazysrc="chrome://devtools/content/performance-new/index.xhtml"/>
</deck>
<splitter class="devtools-side-splitter" id="runtime-listing-splitter"/>
<vbox id="runtime-listing-panel" class="runtime-listing panel-list" flex="1">
<div id="runtime-listing-wrapper" class="panel-list-wrapper">
<iframe id="runtime-listing-panel-details" flex="1" src="runtime-listing.xhtml" tooltip="aHTMLTooltip"/>
</div>
</vbox>
</div>
<splitter hidden="true" class="devtools-horizontal-splitter" orient="vertical"/>
<!-- toolbox iframe will be inserted here -->
</vbox>
</window>

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

@ -1,44 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const QR = require("devtools/shared/qrcode/index");
window.addEventListener(
"load",
function() {
document.getElementById("close").onclick = () => window.close();
document.getElementById("no-scanner").onclick = showToken;
document.getElementById("yes-scanner").onclick = hideToken;
buildUI();
},
{ once: true }
);
function buildUI() {
const { oob } = window.arguments[0];
createQR(oob);
createToken(oob);
}
function createQR(oob) {
const oobData = JSON.stringify(oob);
const imgData = QR.encodeToDataURI(oobData, "L" /* low quality */);
document.querySelector("#qr-code img").src = imgData.src;
}
function createToken(oob) {
const token = oob.sha256.replace(/:/g, "").toLowerCase() + oob.k;
document.querySelector("#token pre").textContent = token;
}
function showToken() {
document.querySelector("body").setAttribute("token", "true");
}
function hideToken() {
document.querySelector("body").removeAttribute("token");
}

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

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html [
<!ENTITY % webideDTD SYSTEM "chrome://devtools/locale/webide.dtd" >
%webideDTD;
]>
<html id="devtools:wifi-auth" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf8"/>
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
<link rel="stylesheet" href="chrome://webide/skin/wifi-auth.css" type="text/css"/>
<script src="chrome://webide/content/wifi-auth.js"></script>
</head>
<body>
<div id="controls">
<a id="close">&deck_close;</a>
</div>
<h3 id="header">&wifi_auth_header;</h3>
<div id="scan-request">&wifi_auth_scan_request;</div>
<div id="qr-code">
<div id="qr-code-wrapper">
<img/>
</div>
<a id="no-scanner" class="toggle-scanner">&wifi_auth_no_scanner;</a>
<div id="qr-size-note">
<h5>&wifi_auth_qr_size_note;</h5>
</div>
</div>
<div id="token">
<div>&wifi_auth_token_request;</div>
<pre id="token-value"/>
<a id="yes-scanner" class="toggle-scanner">&wifi_auth_yes_scanner;</a>
</div>
</body>
</html>

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

@ -1,820 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const Services = require("Services");
const { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
const EventEmitter = require("devtools/shared/event-emitter");
const { OS } = require("resource://gre/modules/osfile.jsm");
const { AppProjects } = require("devtools/client/webide/modules/app-projects");
const TabStore = require("devtools/client/webide/modules/tab-store");
const {
AppValidator,
} = require("devtools/client/webide/modules/app-validator");
const {
ConnectionManager,
Connection,
} = require("devtools/shared/client/connection-manager");
const { RuntimeScanners } = require("devtools/client/webide/modules/runtimes");
const {
RuntimeTypes,
} = require("devtools/client/webide/modules/runtime-types");
const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
const Telemetry = require("devtools/client/shared/telemetry");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/webide.properties"
);
var AppManager = (exports.AppManager = {
DEFAULT_PROJECT_ICON: "chrome://webide/skin/default-app-icon.png",
DEFAULT_PROJECT_NAME: "--",
_initialized: false,
init: function() {
if (this._initialized) {
return;
}
this._initialized = true;
const port = Services.prefs.getIntPref("devtools.debugger.remote-port");
this.connection = ConnectionManager.createConnection("localhost", port);
this.onConnectionChanged = this.onConnectionChanged.bind(this);
this.connection.on(
Connection.Events.STATUS_CHANGED,
this.onConnectionChanged
);
this.tabStore = new TabStore(this.connection);
this.onTabList = this.onTabList.bind(this);
this.onTabNavigate = this.onTabNavigate.bind(this);
this.onTabClosed = this.onTabClosed.bind(this);
this.tabStore.on("tab-list", this.onTabList);
this.tabStore.on("navigate", this.onTabNavigate);
this.tabStore.on("closed", this.onTabClosed);
this._clearRuntimeList();
this._rebuildRuntimeList = this._rebuildRuntimeList.bind(this);
RuntimeScanners.on("runtime-list-updated", this._rebuildRuntimeList);
RuntimeScanners.enable();
this._rebuildRuntimeList();
this._telemetry = new Telemetry();
},
destroy: function() {
if (!this._initialized) {
return;
}
this._initialized = false;
this.selectedProject = null;
this.selectedRuntime = null;
RuntimeScanners.off("runtime-list-updated", this._rebuildRuntimeList);
RuntimeScanners.disable();
this.runtimeList = null;
this.tabStore.off("tab-list", this.onTabList);
this.tabStore.off("navigate", this.onTabNavigate);
this.tabStore.off("closed", this.onTabClosed);
this.tabStore.destroy();
this.tabStore = null;
this.connection.off(
Connection.Events.STATUS_CHANGED,
this.onConnectionChanged
);
this._rootForm = null;
this.connection.disconnect();
this.connection = null;
},
/**
* This module emits various events when state changes occur. The basic event
* naming scheme is that event "X" means "X has changed" or "X is available".
* Some names are more detailed to clarify their precise meaning.
*
* The events this module may emit include:
* before-project:
* The selected project is about to change. The event includes a special
* |cancel| callback that will abort the project change if desired.
* connection:
* The connection status has changed (connected, disconnected, etc.)
* project:
* The selected project has changed.
* project-started:
* The selected project started running on the connected runtime.
* project-stopped:
* The selected project stopped running on the connected runtime.
* project-removed:
* The selected project was removed from the project list.
* project-validated:
* The selected project just completed validation. As part of validation,
* many pieces of metadata about the project are refreshed, including its
* name, manifest details, etc.
* runtime:
* The selected runtime has changed.
* runtime-global-actors:
* The list of global actors for the entire runtime (but not actors for a
* specific tab or app) are now available, so we can test for features
* like preferences and settings.
* runtime-details:
* The selected runtime's details have changed, such as its user-visible
* name.
* runtime-list:
* The list of available runtimes has changed, or any of the user-visible
* details (like names) for the non-selected runtimes has changed.
* runtime-telemetry:
* Detailed runtime telemetry has been recorded. Used by tests.
* runtime-targets:
* The list of remote runtime targets available from the currently
* connected runtime (such as tabs or apps) has changed, or any of the
* user-visible details (like names) for the non-selected runtime targets
* has changed. This event includes |type| in the details, to distinguish
* "apps" and "tabs".
*/
update: function(what, details) {
// Anything we want to forward to the UI
this.emit("app-manager-update", what, details);
},
reportError: function(l10nProperty, ...l10nArgs) {
const win = Services.wm.getMostRecentWindow("devtools:webide");
if (win) {
win.UI.reportError(l10nProperty, ...l10nArgs);
} else {
let text;
if (l10nArgs.length > 0) {
text = Strings.formatStringFromName(l10nProperty, l10nArgs);
} else {
text = Strings.GetStringFromName(l10nProperty);
}
console.error(text);
}
},
onConnectionChanged: async function() {
console.log("Connection status changed: " + this.connection.status);
if (this.connection.status == Connection.Status.DISCONNECTED) {
this.selectedRuntime = null;
}
if (!this.connected) {
this._rootForm = null;
this.deviceFront = null;
this.preferenceFront = null;
this.perfFront = null;
} else {
const response = await this.connection.client.mainRoot.rootForm;
this._rootForm = response;
try {
this.deviceFront = await this.connection.client.mainRoot.getFront(
"device"
);
this.preferenceFront = await this.connection.client.mainRoot.getFront(
"preference"
);
this.perfFront = await this.connection.client.mainRoot.getFront("perf");
this._recordRuntimeInfo();
} catch (e) {
// This may fail on <FF55 (because of lack of bug 1352157) but we will want to
// emit runtime-global-actors in order to call checkRuntimeVersion and display
// the compatibility popup.
console.error(e);
}
this.update("runtime-global-actors");
}
this.update("connection");
},
get connected() {
return (
this.connection && this.connection.status == Connection.Status.CONNECTED
);
},
get apps() {
if (this._appsFront) {
return this._appsFront.apps;
}
return new Map();
},
isProjectRunning: function() {
if (
this.selectedProject.type == "mainProcess" ||
this.selectedProject.type == "tab"
) {
return true;
}
const app = this._getProjectFront(this.selectedProject);
return app && app.running;
},
checkIfProjectIsRunning: function() {
if (this.selectedProject) {
if (this.isProjectRunning()) {
this.update("project-started");
} else {
this.update("project-stopped");
}
}
},
listTabs: function() {
return this.tabStore.listTabs();
},
onTabList: function() {
this.update("runtime-targets", { type: "tabs" });
},
// TODO: Merge this into TabProject as part of project-agnostic work
onTabNavigate: function() {
this.update("runtime-targets", { type: "tabs" });
if (this.selectedProject.type !== "tab") {
return;
}
const tab = (this.selectedProject.app = this.tabStore.selectedTab);
const uri = NetUtil.newURI(tab.url);
// Wanted to use nsIFaviconService here, but it only works for visited
// tabs, so that's no help for any remote tabs. Maybe some favicon wizard
// knows how to get high-res favicons easily, or we could offer actor
// support for this (bug 1061654).
tab.favicon = uri.prePath + "/favicon.ico";
tab.name = tab.title || Strings.GetStringFromName("project_tab_loading");
if (uri.scheme.startsWith("http")) {
tab.name = uri.host + ": " + tab.name;
}
this.selectedProject.location = tab.url;
this.selectedProject.name = tab.name;
this.selectedProject.icon = tab.favicon;
this.update("project-validated");
},
onTabClosed: function() {
if (this.selectedProject.type !== "tab") {
return;
}
this.selectedProject = null;
},
reloadTab: function() {
if (this.selectedProject && this.selectedProject.type != "tab") {
return Promise.reject("tried to reload non-tab project");
}
return this.getTarget().then(target => {
target.reload();
}, console.error);
},
getTarget: function() {
if (this.selectedProject.type == "mainProcess") {
return this.connection.client.mainRoot.getMainProcess();
}
if (this.selectedProject.type == "tab") {
return this.tabStore.getTargetForTab();
}
const app = this._getProjectFront(this.selectedProject);
if (!app) {
return Promise.reject("Can't find app front for selected project");
}
return (async function() {
// Once we asked the app to launch, the app isn't necessary completely loaded.
// launch request only ask the app to launch and immediatly returns.
// We have to keep trying to get app target actors required to create its target.
for (let i = 0; i < 10; i++) {
try {
return await app.getTarget();
} catch (e) {}
return new Promise(resolve => {
setTimeout(resolve, 500);
});
}
AppManager.reportError(
"error_cantConnectToApp",
app.manifest.manifestURL
);
throw new Error("can't connect to app");
})();
},
getProjectManifestURL: function(project) {
let manifest = null;
if (project.type == "runtimeApp") {
manifest = project.app.manifestURL;
}
if (project.type == "hosted") {
manifest = project.location;
}
if (project.type == "packaged" && project.packagedAppOrigin) {
manifest = "app://" + project.packagedAppOrigin + "/manifest.webapp";
}
return manifest;
},
_getProjectFront: function(project) {
const manifest = this.getProjectManifestURL(project);
if (manifest && this._appsFront) {
return this._appsFront.apps.get(manifest);
}
return null;
},
_selectedProject: null,
set selectedProject(project) {
// A regular comparison doesn't work as we recreate a new object every time
const prev = this._selectedProject;
if (!prev && !project) {
return;
} else if (prev && project && prev.type === project.type) {
const type = project.type;
if (type === "runtimeApp") {
if (prev.app.manifestURL === project.app.manifestURL) {
return;
}
} else if (type === "tab") {
if (prev.app.actor === project.app.actor) {
return;
}
} else if (type === "packaged" || type === "hosted") {
if (prev.location === project.location) {
return;
}
} else if (type === "mainProcess") {
return;
} else {
throw new Error("Unsupported project type: " + type);
}
}
let cancelled = false;
this.update("before-project", {
cancel: () => {
cancelled = true;
},
});
if (cancelled) {
return;
}
this._selectedProject = project;
// Clear out tab store's selected state, if any
this.tabStore.selectedTab = null;
if (project) {
if (project.type == "packaged" || project.type == "hosted") {
this.validateAndUpdateProject(project);
}
if (project.type == "tab") {
this.tabStore.selectedTab = project.app;
}
}
this.update("project");
this.checkIfProjectIsRunning();
},
get selectedProject() {
return this._selectedProject;
},
async removeSelectedProject() {
const location = this.selectedProject.location;
AppManager.selectedProject = null;
// If the user cancels the removeProject operation, don't remove the project
if (AppManager.selectedProject != null) {
return;
}
await AppProjects.remove(location);
AppManager.update("project-removed");
},
_selectedRuntime: null,
set selectedRuntime(value) {
this._selectedRuntime = value;
if (
!value &&
this.selectedProject &&
(this.selectedProject.type == "mainProcess" ||
this.selectedProject.type == "runtimeApp" ||
this.selectedProject.type == "tab")
) {
this.selectedProject = null;
}
this.update("runtime");
},
get selectedRuntime() {
return this._selectedRuntime;
},
connectToRuntime: function(runtime) {
if (this.connected && this.selectedRuntime === runtime) {
// Already connected
return Promise.resolve();
}
const deferred = new Promise((resolve, reject) => {
this.disconnectRuntime().then(() => {
this.selectedRuntime = runtime;
const onConnectedOrDisconnected = () => {
this.connection.off(
Connection.Events.CONNECTED,
onConnectedOrDisconnected
);
this.connection.off(
Connection.Events.DISCONNECTED,
onConnectedOrDisconnected
);
if (this.connected) {
resolve();
} else {
reject();
}
};
this.connection.on(
Connection.Events.CONNECTED,
onConnectedOrDisconnected
);
this.connection.on(
Connection.Events.DISCONNECTED,
onConnectedOrDisconnected
);
try {
// Reset the connection's state to defaults
this.connection.resetOptions();
// Only watch for errors here. Final resolution occurs above, once
// we've reached the CONNECTED state.
this.selectedRuntime.connect(this.connection).catch(e => reject(e));
} catch (e) {
reject(e);
}
}, reject);
});
// Record connection result in telemetry
const logResult = result => {
this._telemetry
.getHistogramById("DEVTOOLS_WEBIDE_CONNECTION_RESULT")
.add(result);
if (runtime.type) {
this._telemetry
.getHistogramById(`DEVTOOLS_WEBIDE_${runtime.type}_CONNECTION_RESULT`)
.add(result);
}
};
deferred.then(() => logResult(true), () => logResult(false));
// If successful, record connection time in telemetry
deferred
.then(() => {
const timerId = "DEVTOOLS_WEBIDE_CONNECTION_TIME_SECONDS";
this._telemetry.start(timerId, this);
this.connection.once(Connection.Events.STATUS_CHANGED, () => {
this._telemetry.finish(timerId, this);
});
})
.catch(() => {
// Empty rejection handler to silence uncaught rejection warnings
// |connectToRuntime| caller should listen for rejections.
// Bug 1121100 may find a better way to silence these.
});
return deferred;
},
async _recordRuntimeInfo() {
if (!this.connected) {
return;
}
const runtime = this.selectedRuntime;
this._telemetry
.getKeyedHistogramById("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE")
.add(runtime.type || "UNKNOWN", true);
this._telemetry
.getKeyedHistogramById("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID")
.add(runtime.id || "unknown", true);
if (!this.deviceFront) {
this.update("runtime-telemetry");
return;
}
const d = await this.deviceFront.getDescription();
this._telemetry
.getKeyedHistogramById("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_PROCESSOR")
.add(d.processor, true);
this._telemetry
.getKeyedHistogramById("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_OS")
.add(d.os, true);
this._telemetry
.getKeyedHistogramById(
"DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_PLATFORM_VERSION"
)
.add(d.platformversion, true);
this._telemetry
.getKeyedHistogramById("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_APP_TYPE")
.add(d.apptype, true);
this._telemetry
.getKeyedHistogramById("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_VERSION")
.add(d.version, true);
this.update("runtime-telemetry");
},
isMainProcessDebuggable: function() {
// Fx <39 exposes chrome target actors on RootActor
// Fx >=39 exposes a dedicated actor via getProcess request
return (
(this.connection.client &&
this.connection.client.mainRoot &&
this.connection.client.mainRoot.traits.allowChromeProcess) ||
(this._rootForm && this._rootForm.consoleActor)
);
},
disconnectRuntime: function() {
if (!this.connected) {
return Promise.resolve();
}
return new Promise(resolve => {
this.connection.once(Connection.Events.DISCONNECTED, () => resolve());
this.connection.disconnect();
});
},
launchRuntimeApp: function() {
if (this.selectedProject && this.selectedProject.type != "runtimeApp") {
return Promise.reject("attempting to launch a non-runtime app");
}
const app = this._getProjectFront(this.selectedProject);
return app.launch();
},
launchOrReloadRuntimeApp: function() {
if (this.selectedProject && this.selectedProject.type != "runtimeApp") {
return Promise.reject("attempting to launch / reload a non-runtime app");
}
const app = this._getProjectFront(this.selectedProject);
if (!app.running) {
return app.launch();
}
return app.reload();
},
runtimeCanHandleApps: function() {
return !!this._appsFront;
},
installAndRunProject: function() {
const project = this.selectedProject;
if (!project || (project.type != "packaged" && project.type != "hosted")) {
console.error("Can't install project. Unknown type of project.");
return Promise.reject("Can't install");
}
if (!this._rootForm) {
this.reportError("error_cantInstallNotFullyConnected");
return Promise.reject("Can't install");
}
if (!this._appsFront) {
console.error("Runtime doesn't have a webappsActor");
return Promise.reject("Can't install");
}
return (async function() {
const self = AppManager;
// Validate project
await self.validateAndUpdateProject(project);
if (project.errorsCount > 0) {
self.reportError("error_cantInstallValidationErrors");
return;
}
if (project.type != "packaged" && project.type != "hosted") {
return Promise.reject("Don't know how to install project");
}
let response;
if (project.type == "packaged") {
const packageDir = project.location;
console.log("Installing app from " + packageDir);
response = await self._appsFront.installPackaged(
packageDir,
project.packagedAppOrigin
);
// If the packaged app specified a custom origin override,
// we need to update the local project origin
project.packagedAppOrigin = response.appId;
// And ensure the indexed db on disk is also updated
AppProjects.update(project);
}
if (project.type == "hosted") {
const manifestURLObject = Services.io.newURI(project.location);
const origin = Services.io.newURI(manifestURLObject.prePath);
const appId = origin.host;
const metadata = {
origin: origin.spec,
manifestURL: project.location,
};
response = await self._appsFront.installHosted(
appId,
metadata,
project.manifest
);
}
// Addons don't have any document to load (yet?)
// So that there is no need to run them, installing is enough
if (
project.manifest.manifest_version ||
project.manifest.role === "addon"
) {
return;
}
const { app } = response;
if (!app.running) {
const deferred = new Promise(resolve => {
self.on("app-manager-update", function onUpdate(what) {
if (what == "project-started") {
self.off("app-manager-update", onUpdate);
resolve();
}
});
});
await app.launch();
await deferred;
} else {
await app.reload();
}
})();
},
stopRunningApp: function() {
const app = this._getProjectFront(this.selectedProject);
return app.close();
},
/* PROJECT VALIDATION */
validateAndUpdateProject: function(project) {
if (!project) {
return Promise.reject();
}
return (async function() {
const packageDir = project.location;
const validation = new AppValidator({
type: project.type,
// Build process may place the manifest in a non-root directory
location: packageDir,
});
await validation.validate();
if (validation.manifest) {
const manifest = validation.manifest;
let iconPath;
if (manifest.icons) {
const size = Object.keys(manifest.icons).sort((a, b) => b - a)[0];
if (size) {
iconPath = manifest.icons[size];
}
}
if (!iconPath) {
project.icon = AppManager.DEFAULT_PROJECT_ICON;
} else if (project.type == "hosted") {
const manifestURL = Services.io.newURI(project.location);
const origin = Services.io.newURI(manifestURL.prePath);
project.icon = Services.io.newURI(iconPath, null, origin).spec;
} else if (project.type == "packaged") {
const projectFolder = FileUtils.File(packageDir);
const folderURI = Services.io.newFileURI(projectFolder).spec;
project.icon = folderURI + iconPath.replace(/^\/|\\/, "");
}
project.manifest = validation.manifest;
if ("name" in project.manifest) {
project.name = project.manifest.name;
} else {
project.name = AppManager.DEFAULT_PROJECT_NAME;
}
} else {
project.manifest = null;
project.icon = AppManager.DEFAULT_PROJECT_ICON;
project.name = AppManager.DEFAULT_PROJECT_NAME;
}
project.validationStatus = "valid";
if (validation.warnings.length > 0) {
project.warningsCount = validation.warnings.length;
project.warnings = validation.warnings;
project.validationStatus = "warning";
} else {
project.warnings = "";
project.warningsCount = 0;
}
if (validation.errors.length > 0) {
project.errorsCount = validation.errors.length;
project.errors = validation.errors;
project.validationStatus = "error";
} else {
project.errors = "";
project.errorsCount = 0;
}
if (project.warningsCount && project.errorsCount) {
project.validationStatus = "error warning";
}
if (
project.type === "hosted" &&
project.location !== validation.manifestURL
) {
await AppProjects.updateLocation(project, validation.manifestURL);
} else if (AppProjects.get(project.location)) {
await AppProjects.update(project);
}
if (AppManager.selectedProject === project) {
AppManager.update("project-validated");
}
})();
},
/* RUNTIME LIST */
_clearRuntimeList: function() {
this.runtimeList = {
usb: [],
wifi: [],
other: [],
};
},
_rebuildRuntimeList: function() {
const runtimes = RuntimeScanners.listRuntimes();
this._clearRuntimeList();
// Reorganize runtimes by type
for (const runtime of runtimes) {
switch (runtime.type) {
case RuntimeTypes.USB:
this.runtimeList.usb.push(runtime);
break;
case RuntimeTypes.WIFI:
this.runtimeList.wifi.push(runtime);
break;
default:
this.runtimeList.other.push(runtime);
}
}
this.update("runtime-details");
this.update("runtime-list");
},
/* MANIFEST UTILS */
writeManifest: function(project) {
if (project.type != "packaged") {
return Promise.reject("Not a packaged app");
}
if (!project.manifest) {
project.manifest = {};
}
const folder = project.location;
const manifestPath = OS.Path.join(folder, "manifest.webapp");
const text = JSON.stringify(project.manifest, null, 2);
const encoder = new TextEncoder();
const array = encoder.encode(text);
return OS.File.writeAtomic(manifestPath, array, {
tmpPath: manifestPath + ".tmp",
});
},
});
EventEmitter.decorate(AppManager);

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

@ -1,242 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { Cc, Ci, Cr } = require("chrome");
const EventEmitter = require("devtools/shared/event-emitter");
const { generateUUID } = Cc["@mozilla.org/uuid-generator;1"].getService(
Ci.nsIUUIDGenerator
);
const { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
/**
* IndexedDB wrapper that just save project objects
*
* The only constraint is that project objects have to have
* a unique `location` object.
*/
const IDB = {
_db: null,
databaseName: "AppProjects",
open: function() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(IDB.databaseName, 5);
request.onerror = function(event) {
reject(
"Unable to open AppProjects indexedDB: " +
this.error.name +
" - " +
this.error.message
);
};
request.onupgradeneeded = function(event) {
const db = event.target.result;
db.createObjectStore("projects", { keyPath: "location" });
};
request.onsuccess = function() {
const db = (IDB._db = request.result);
const objectStore = db.transaction("projects").objectStore("projects");
const projects = [];
const toRemove = [];
objectStore.openCursor().onsuccess = function(event) {
const cursor = event.target.result;
if (cursor) {
if (cursor.value.location) {
// We need to make sure this object has a `.location` property.
// The UI depends on this property.
// This should not be needed as we make sure to register valid
// projects, but in the past (before bug 924568), we might have
// registered invalid objects.
// We also want to make sure the location is valid.
// If the location doesn't exist, we remove the project.
try {
const file = FileUtils.File(cursor.value.location);
if (file.exists()) {
projects.push(cursor.value);
} else {
toRemove.push(cursor.value.location);
}
} catch (e) {
if (e.result == Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH) {
// A URL
projects.push(cursor.value);
}
}
}
cursor.continue();
} else {
const removePromises = [];
for (const location of toRemove) {
removePromises.push(IDB.remove(location));
}
Promise.all(removePromises).then(() => {
resolve(projects);
});
}
};
};
});
},
add: function(project) {
return new Promise((resolve, reject) => {
if (!project.location) {
// We need to make sure this object has a `.location` property.
reject("Missing location property on project object.");
} else {
const transaction = IDB._db.transaction(["projects"], "readwrite");
const objectStore = transaction.objectStore("projects");
const request = objectStore.add(project);
request.onerror = function(event) {
reject(
"Unable to add project to the AppProjects indexedDB: " +
this.error.name +
" - " +
this.error.message
);
};
request.onsuccess = function() {
resolve();
};
}
});
},
update: function(project) {
return new Promise((resolve, reject) => {
const transaction = IDB._db.transaction(["projects"], "readwrite");
const objectStore = transaction.objectStore("projects");
const request = objectStore.put(project);
request.onerror = function(event) {
reject(
"Unable to update project to the AppProjects indexedDB: " +
this.error.name +
" - " +
this.error.message
);
};
request.onsuccess = function() {
resolve();
};
});
},
remove: function(location) {
return new Promise((resolve, reject) => {
const request = IDB._db
.transaction(["projects"], "readwrite")
.objectStore("projects")
.delete(location);
request.onsuccess = function(event) {
resolve();
};
request.onerror = function() {
reject(
"Unable to delete project to the AppProjects indexedDB: " +
this.error.name +
" - " +
this.error.message
);
};
});
},
};
var loadDeferred = IDB.open().then(function(projects) {
AppProjects.projects = projects;
AppProjects.emit("ready", projects);
});
const AppProjects = {
load: function() {
return loadDeferred;
},
addPackaged: function(folder) {
const file = FileUtils.File(folder.path);
if (!file.exists()) {
return Promise.reject("path doesn't exist");
}
const existingProject = this.get(folder.path);
if (existingProject) {
return Promise.reject("Already added");
}
const project = {
type: "packaged",
location: folder.path,
// We need a unique id, that is the app origin,
// in order to identify the app when being installed on the device.
// The packaged app local path is a valid id, but only on the client.
// This origin will be used to generate the true id of an app:
// its manifest URL.
// If the app ends up specifying an explicit origin in its manifest,
// we will override this random UUID on app install.
packagedAppOrigin: generateUUID()
.toString()
.slice(1, -1),
};
return IDB.add(project).then(() => {
this.projects.push(project);
return project;
});
},
addHosted: function(manifestURL) {
const existingProject = this.get(manifestURL);
if (existingProject) {
return Promise.reject("Already added");
}
const project = {
type: "hosted",
location: manifestURL,
};
return IDB.add(project).then(() => {
this.projects.push(project);
return project;
});
},
update: function(project) {
return IDB.update(project);
},
updateLocation: function(project, newLocation) {
return IDB.remove(project.location).then(() => {
project.location = newLocation;
return IDB.add(project);
});
},
remove: function(location) {
return IDB.remove(location).then(() => {
for (let i = 0; i < this.projects.length; i++) {
if (this.projects[i].location == location) {
this.projects.splice(i, 1);
return;
}
}
throw new Error("Unable to find project in AppProjects store");
});
},
get: function(location) {
for (let i = 0; i < this.projects.length; i++) {
if (this.projects[i].location == location) {
return this.projects[i];
}
}
return null;
},
projects: [],
};
EventEmitter.decorate(AppProjects);
exports.AppProjects = AppProjects;

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

@ -1,345 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var { Ci } = require("chrome");
const { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
const Services = require("Services");
var strings = Services.strings.createBundle(
"chrome://devtools/locale/app-manager.properties"
);
function AppValidator({ type, location }) {
this.type = type;
this.location = location;
this.errors = [];
this.warnings = [];
}
AppValidator.prototype.error = function(message) {
this.errors.push(message);
};
AppValidator.prototype.warning = function(message) {
this.warnings.push(message);
};
AppValidator.prototype._getPackagedManifestFile = function() {
const manifestFile = FileUtils.File(this.location);
if (!manifestFile.exists()) {
this.error(strings.GetStringFromName("validator.nonExistingFolder"));
return null;
}
if (!manifestFile.isDirectory()) {
this.error(strings.GetStringFromName("validator.expectProjectFolder"));
return null;
}
const appManifestFile = manifestFile.clone();
appManifestFile.append("manifest.webapp");
const jsonManifestFile = manifestFile.clone();
jsonManifestFile.append("manifest.json");
const hasAppManifest = appManifestFile.exists() && appManifestFile.isFile();
const hasJsonManifest =
jsonManifestFile.exists() && jsonManifestFile.isFile();
if (!hasAppManifest && !hasJsonManifest) {
this.error(strings.GetStringFromName("validator.noManifestFile"));
return null;
}
return hasAppManifest ? appManifestFile : jsonManifestFile;
};
AppValidator.prototype._getPackagedManifestURL = function() {
const manifestFile = this._getPackagedManifestFile();
if (!manifestFile) {
return null;
}
return Services.io.newFileURI(manifestFile).spec;
};
AppValidator.checkManifest = function(manifestURL) {
return new Promise((resolve, reject) => {
let error;
const req = new XMLHttpRequest();
req.overrideMimeType("text/plain");
try {
req.open("GET", manifestURL, true);
req.channel.loadFlags |=
Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
} catch (e) {
error = strings.formatStringFromName("validator.invalidManifestURL", [
manifestURL,
]);
return reject(error);
}
req.onload = function() {
let manifest = null;
try {
manifest = JSON.parse(req.responseText);
} catch (e) {
error = strings.formatStringFromName("validator.invalidManifestJSON", [
e,
manifestURL,
]);
reject(error);
}
resolve({ manifest, manifestURL });
};
req.onerror = function() {
error = strings.formatStringFromName("validator.noAccessManifestURL", [
req.statusText,
manifestURL,
]);
reject(error);
};
try {
req.send(null);
} catch (e) {
error = strings.formatStringFromName("validator.noAccessManifestURL", [
e,
manifestURL,
]);
reject(error);
}
});
};
AppValidator.findManifestAtOrigin = function(manifestURL) {
const fixedManifest =
Services.io.newURI(manifestURL).prePath + "/manifest.webapp";
return AppValidator.checkManifest(fixedManifest);
};
AppValidator.findManifestPath = function(manifestURL) {
return new Promise((resolve, reject) => {
if (manifestURL.endsWith("manifest.webapp")) {
reject();
} else {
const fixedManifest = manifestURL + "/manifest.webapp";
resolve(AppValidator.checkManifest(fixedManifest));
}
});
};
AppValidator.checkAlternateManifest = function(manifestURL) {
return (async function() {
let result;
try {
result = await AppValidator.findManifestPath(manifestURL);
} catch (e) {
result = await AppValidator.findManifestAtOrigin(manifestURL);
}
return result;
})();
};
AppValidator.prototype._fetchManifest = function(manifestURL) {
return new Promise(resolve => {
this.manifestURL = manifestURL;
AppValidator.checkManifest(manifestURL).then(
({ manifest, manifestURL }) => {
resolve(manifest);
},
error => {
AppValidator.checkAlternateManifest(manifestURL).then(
({ manifest, manifestURL }) => {
this.manifestURL = manifestURL;
resolve(manifest);
},
() => {
this.error(error);
resolve(null);
}
);
}
);
});
};
AppValidator.prototype._getManifest = function() {
let manifestURL;
if (this.type == "packaged") {
manifestURL = this._getPackagedManifestURL();
if (!manifestURL) {
return Promise.resolve(null);
}
} else if (this.type == "hosted") {
manifestURL = this.location;
try {
Services.io.newURI(manifestURL);
} catch (e) {
this.error(
strings.formatStringFromName("validator.invalidHostedManifestURL", [
manifestURL,
e.message,
])
);
return Promise.resolve(null);
}
} else {
this.error(
strings.formatStringFromName("validator.invalidProjectType", [this.type])
);
return Promise.resolve(null);
}
return this._fetchManifest(manifestURL);
};
AppValidator.prototype.validateManifest = function(manifest) {
if (!manifest.name) {
this.error(strings.GetStringFromName("validator.missNameManifestProperty"));
}
if (!manifest.icons || Object.keys(manifest.icons).length === 0) {
this.warning(
strings.GetStringFromName("validator.missIconsManifestProperty")
);
} else if (!manifest.icons["128"]) {
this.warning(strings.GetStringFromName("validator.missIconMarketplace2"));
}
};
AppValidator.prototype._getOriginURL = function() {
if (this.type == "packaged") {
const manifestURL = Services.io.newURI(this.manifestURL);
return Services.io.newURI(".", null, manifestURL).spec;
} else if (this.type == "hosted") {
return Services.io.newURI(this.location).prePath;
}
};
AppValidator.prototype.validateLaunchPath = function(manifest) {
return new Promise(resolve => {
// The launch_path field has to start with a `/`
if (manifest.launch_path && manifest.launch_path[0] !== "/") {
this.error(
strings.formatStringFromName("validator.nonAbsoluteLaunchPath", [
manifest.launch_path,
])
);
resolve();
}
const origin = this._getOriginURL();
let path;
if (this.type == "packaged") {
path = "." + (manifest.launch_path || "/index.html");
} else if (this.type == "hosted") {
path = manifest.launch_path || "/";
}
let indexURL;
try {
indexURL = Services.io.newURI(path, null, Services.io.newURI(origin))
.spec;
} catch (e) {
this.error(
strings.formatStringFromName("validator.accessFailedLaunchPath", [
origin + path,
])
);
return resolve();
}
const req = new XMLHttpRequest();
req.overrideMimeType("text/plain");
try {
req.open("HEAD", indexURL, true);
req.channel.loadFlags |=
Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
} catch (e) {
this.error(
strings.formatStringFromName("validator.accessFailedLaunchPath", [
indexURL,
])
);
return resolve();
}
req.onload = () => {
if (req.status >= 400) {
this.error(
strings.formatStringFromName(
"validator.accessFailedLaunchPathBadHttpCode",
[indexURL, req.status]
)
);
}
resolve();
};
req.onerror = () => {
this.error(
strings.formatStringFromName("validator.accessFailedLaunchPath", [
indexURL,
])
);
resolve();
};
try {
req.send(null);
} catch (e) {
this.error(
strings.formatStringFromName("validator.accessFailedLaunchPath", [
indexURL,
])
);
resolve();
}
});
};
AppValidator.prototype.validateType = function(manifest) {
const appType = manifest.type || "web";
if (!["web", "privileged", "certified"].includes(appType)) {
this.error(
strings.formatStringFromName("validator.invalidAppType", [appType])
);
} else if (
this.type == "hosted" &&
["certified", "privileged"].includes(appType)
) {
this.error(
strings.formatStringFromName("validator.invalidHostedPriviledges", [
appType,
])
);
}
// certified app are not fully supported on the simulator
if (appType === "certified") {
this.warning(strings.GetStringFromName("validator.noCertifiedSupport"));
}
};
AppValidator.prototype.validate = function() {
this.errors = [];
this.warnings = [];
return this._getManifest().then(manifest => {
if (manifest) {
this.manifest = manifest;
// Skip validations for add-ons
if (manifest.role === "addon" || manifest.manifest_version) {
return Promise.resolve();
}
this.validateManifest(manifest);
this.validateType(manifest);
return this.validateLaunchPath(manifest);
}
});
};
exports.AppValidator = AppValidator;

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

@ -1,395 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const EventEmitter = require("devtools/shared/event-emitter");
const Services = require("Services");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/webide.properties"
);
var ConfigView;
module.exports = ConfigView = function(window) {
EventEmitter.decorate(this);
this._doc = window.document;
this._keys = [];
return this;
};
ConfigView.prototype = {
_renderByType: function(input, name, value, customType) {
value = customType || typeof value;
switch (value) {
case "boolean":
input.setAttribute("data-type", "boolean");
input.setAttribute("type", "checkbox");
break;
case "number":
input.setAttribute("data-type", "number");
input.setAttribute("type", "number");
break;
case "object":
input.setAttribute("data-type", "object");
input.setAttribute("type", "text");
break;
default:
input.setAttribute("data-type", "string");
input.setAttribute("type", "text");
break;
}
return input;
},
set front(front) {
this._front = front;
},
set keys(keys) {
this._keys = keys;
},
get keys() {
return this._keys;
},
set kind(kind) {
this._kind = kind;
},
set includeTypeName(include) {
this._includeTypeName = include;
},
search: function(event) {
if (event.target.value.length) {
const stringMatch = new RegExp(event.target.value, "i");
for (let i = 0; i < this._keys.length; i++) {
const key = this._keys[i];
const row = this._doc.getElementById("row-" + key);
if (key.match(stringMatch)) {
row.classList.remove("hide");
} else if (row) {
row.classList.add("hide");
}
}
} else {
const trs = this._doc
.getElementById("device-fields")
.querySelectorAll("tr");
for (let i = 0; i < trs.length; i++) {
trs[i].classList.remove("hide");
}
}
},
generateDisplay: function(json) {
const deviceItems = Object.keys(json);
deviceItems.sort();
this.keys = deviceItems;
for (let i = 0; i < this.keys.length; i++) {
const key = this.keys[i];
this.generateField(key, json[key].value, json[key].hasUserValue);
}
},
generateField: function(name, value, hasUserValue, customType, newRow) {
const table = this._doc.querySelector("table");
const sResetDefault = Strings.GetStringFromName("device_reset_default");
if (!this._keys.includes(name)) {
this._keys.push(name);
}
let input = this._doc.createElement("input");
const tr = this._doc.createElement("tr");
tr.setAttribute("id", "row-" + name);
tr.classList.add("edit-row");
let td = this._doc.createElement("td");
td.classList.add("field-name");
td.textContent = name;
tr.appendChild(td);
td = this._doc.createElement("td");
input.classList.add("editable");
input.setAttribute("id", name);
input = this._renderByType(input, name, value, customType);
if (customType === "boolean" || input.type === "checkbox") {
input.checked = value;
} else {
if (typeof value === "object") {
value = JSON.stringify(value);
}
input.value = value;
}
if (!(this._includeTypeName || isNaN(parseInt(value, 10)))) {
input.type = "number";
}
td.appendChild(input);
tr.appendChild(td);
td = this._doc.createElement("td");
td.setAttribute("id", "td-" + name);
const button = this._doc.createElement("button");
button.setAttribute("data-id", name);
button.setAttribute("id", "btn-" + name);
button.classList.add("reset");
button.textContent = sResetDefault;
td.appendChild(button);
if (!hasUserValue) {
button.classList.add("hide");
}
tr.appendChild(td);
// If this is a new field, add it to the top of the table.
if (newRow) {
const existing = table.querySelector("#" + name);
if (!existing) {
table.insertBefore(tr, newRow);
} else {
existing.value = value;
}
} else {
table.appendChild(tr);
}
},
resetTable: function() {
const table = this._doc.querySelector("table");
const trs = table.querySelectorAll("tr:not(#add-custom-field)");
for (let i = 0; i < trs.length; i++) {
table.removeChild(trs[i]);
}
return table;
},
_getCallType: function(type, name) {
let frontName = "get";
if (this._includeTypeName) {
frontName += type;
}
return this._front[frontName + this._kind](name);
},
_setCallType: function(type, name, value) {
let frontName = "set";
if (this._includeTypeName) {
frontName += type;
}
return this._front[frontName + this._kind](name, value);
},
_saveByType: function(options) {
const fieldName = options.id;
const inputType = options.type;
let value = options.value;
const input = this._doc.getElementById(fieldName);
switch (inputType) {
case "boolean":
this._setCallType("Bool", fieldName, input.checked);
break;
case "number":
this._setCallType("Int", fieldName, value);
break;
case "object":
try {
value = JSON.parse(value);
} catch (e) {}
this._setCallType("Object", fieldName, value);
break;
default:
this._setCallType("Char", fieldName, value);
break;
}
},
updateField: function(event) {
if (event.target) {
const inputType = event.target.getAttribute("data-type");
let inputValue = event.target.checked || event.target.value;
if (
event.target.nodeName == "input" &&
event.target.validity.valid &&
event.target.classList.contains("editable")
) {
const id = event.target.id;
if (inputType === "boolean") {
if (event.target.checked) {
inputValue = true;
} else {
inputValue = false;
}
}
this._saveByType({
id: id,
type: inputType,
value: inputValue,
});
this._doc.getElementById("btn-" + id).classList.remove("hide");
}
}
},
_resetToDefault: function(name, input, button) {
this._front["clearUser" + this._kind](name);
const dataType = input.getAttribute("data-type");
const tr = this._doc.getElementById("row-" + name);
switch (dataType) {
case "boolean":
this._defaultField = this._getCallType("Bool", name);
this._defaultField.then(
boolean => {
input.checked = boolean;
},
() => {
input.checked = false;
tr.remove();
}
);
break;
case "number":
this._defaultField = this._getCallType("Int", name);
this._defaultField.then(
number => {
input.value = number;
},
() => {
tr.remove();
}
);
break;
case "object":
this._defaultField = this._getCallType("Object", name);
this._defaultField.then(
object => {
input.value = JSON.stringify(object);
},
() => {
tr.remove();
}
);
break;
default:
this._defaultField = this._getCallType("Char", name);
this._defaultField.then(
string => {
input.value = string;
},
() => {
tr.remove();
}
);
break;
}
button.classList.add("hide");
},
checkReset: function(event) {
if (event.target.classList.contains("reset")) {
const btnId = event.target.getAttribute("data-id");
const input = this._doc.getElementById(btnId);
this._resetToDefault(btnId, input, event.target);
}
},
updateFieldType: function() {
const table = this._doc.querySelector("table");
const customValueType = table.querySelector("#custom-value-type").value;
const customTextEl = table.querySelector("#custom-value-text");
if (customValueType.length === 0) {
return false;
}
switch (customValueType) {
case "boolean":
customTextEl.type = "checkbox";
break;
case "number":
customTextEl.type = "number";
break;
default:
customTextEl.type = "text";
break;
}
return customValueType;
},
clearNewFields: function() {
const table = this._doc.querySelector("table");
const customTextEl = table.querySelector("#custom-value-text");
if (customTextEl.checked) {
customTextEl.checked = false;
} else {
customTextEl.value = "";
}
this.updateFieldType();
},
updateNewField: function() {
const table = this._doc.querySelector("table");
const customValueType = this.updateFieldType();
if (!customValueType) {
return;
}
const customRow = table.querySelector("tr:nth-of-type(2)");
const customTextEl = table.querySelector("#custom-value-text");
const customTextNameEl = table.querySelector("#custom-value-name");
if (customTextEl.validity.valid) {
let customText = customTextEl.value;
if (customValueType === "boolean") {
customText = customTextEl.checked;
}
const customTextName = customTextNameEl.value.replace(
/[^A-Za-z0-9\.\-_]/gi,
""
);
this.generateField(
customTextName,
customText,
true,
customValueType,
customRow
);
this._saveByType({
id: customTextName,
type: customValueType,
value: customText,
});
customTextNameEl.value = "";
this.clearNewFields();
}
},
checkNewFieldSubmit: function(event) {
if (event.keyCode === 13) {
this._doc.getElementById("custom-value").click();
}
},
};

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

@ -1,18 +0,0 @@
# -*- Mode: python; 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/.
DevToolsModules(
'app-manager.js',
'app-projects.js',
'app-validator.js',
'config-view.js',
'project-list.js',
'runtime-list.js',
'runtime-types.js',
'runtimes.js',
'tab-store.js',
'utils.js'
)

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

@ -1,417 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const Services = require("Services");
const { AppProjects } = require("devtools/client/webide/modules/app-projects");
const { AppManager } = require("devtools/client/webide/modules/app-manager");
const EventEmitter = require("devtools/shared/event-emitter");
const utils = require("devtools/client/webide/modules/utils");
const Telemetry = require("devtools/client/shared/telemetry");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/webide.properties"
);
const TELEMETRY_WEBIDE_NEW_PROJECT_COUNT = "DEVTOOLS_WEBIDE_NEW_PROJECT_COUNT";
var ProjectList;
module.exports = ProjectList = function(win, parentWindow) {
EventEmitter.decorate(this);
this._doc = win.document;
this._UI = parentWindow.UI;
this._parentWindow = parentWindow;
this._telemetry = new Telemetry();
this._panelNodeEl = "div";
this.onWebIDEUpdate = this.onWebIDEUpdate.bind(this);
this._UI.on("webide-update", this.onWebIDEUpdate);
AppManager.init();
this.appManagerUpdate = this.appManagerUpdate.bind(this);
AppManager.on("app-manager-update", this.appManagerUpdate);
};
ProjectList.prototype = {
get doc() {
return this._doc;
},
appManagerUpdate: function(what, details) {
// Got a message from app-manager.js
// See AppManager.update() for descriptions of what these events mean.
switch (what) {
case "project-removed":
case "runtime-targets":
case "connection":
this.update(details);
break;
case "project":
this.updateCommands();
this.update(details);
break;
}
},
onWebIDEUpdate: function(what, details) {
if (what == "busy" || what == "unbusy") {
this.updateCommands();
}
},
/**
* testOptions: { chrome mochitest support
* folder: nsIFile, where to store the app
* index: Number, index of the app in the template list
* name: String name of the app
* }
*/
newApp: function(testOptions) {
const parentWindow = this._parentWindow;
const self = this;
return this._UI.busyUntil(
(async function() {
// Open newapp.xul, which will feed ret.location
const ret = { location: null, testOptions: testOptions };
parentWindow.openDialog(
"chrome://webide/content/newapp.xul",
"newapp",
"chrome,modal",
ret
);
if (!ret.location) {
return;
}
// Retrieve added project
const project = AppProjects.get(ret.location);
// Select project
AppManager.selectedProject = project;
self._telemetry
.getHistogramById(TELEMETRY_WEBIDE_NEW_PROJECT_COUNT)
.add(true);
})(),
"creating new app"
);
},
importPackagedApp: function(location) {
const parentWindow = this._parentWindow;
const UI = this._UI;
return UI.busyUntil(
(async function() {
const directory = await utils.getPackagedDirectory(
parentWindow,
location
);
if (!directory) {
// User cancelled directory selection
return;
}
await UI.importAndSelectApp(directory);
})(),
"importing packaged app"
);
},
importHostedApp: function(location) {
const parentWindow = this._parentWindow;
const UI = this._UI;
return UI.busyUntil(
(async function() {
const url = utils.getHostedURL(parentWindow, location);
if (!url) {
return;
}
await UI.importAndSelectApp(url);
})(),
"importing hosted app"
);
},
/**
* opts: {
* panel: Object, currenl project panel node
* name: String, name of the project
* icon: String path of the project icon
* }
*/
_renderProjectItem: function(opts) {
const span =
opts.panel.querySelector("span") || this._doc.createElement("span");
span.textContent = opts.name;
const icon =
opts.panel.querySelector("img") || this._doc.createElement("img");
icon.className = "project-image";
icon.setAttribute("src", opts.icon);
opts.panel.appendChild(icon);
opts.panel.appendChild(span);
opts.panel.setAttribute("title", opts.name);
},
refreshTabs: function() {
if (AppManager.connected) {
return AppManager.listTabs()
.then(() => {
this.updateTabs();
})
.catch(console.error);
}
},
updateTabs: function() {
const tabsHeaderNode = this._doc.querySelector("#panel-header-tabs");
const tabsNode = this._doc.querySelector("#project-panel-tabs");
while (tabsNode.hasChildNodes()) {
tabsNode.firstChild.remove();
}
if (!AppManager.connected) {
tabsHeaderNode.setAttribute("hidden", "true");
return;
}
const tabs = AppManager.tabStore.tabs;
tabsHeaderNode.removeAttribute("hidden");
for (let i = 0; i < tabs.length; i++) {
const tab = tabs[i];
const URL = this._parentWindow.URL;
let url;
try {
url = new URL(tab.url);
} catch (e) {
// Don't try to handle invalid URLs
continue;
}
// Wanted to use nsIFaviconService here, but it only works for visited
// tabs, so that's no help for any remote tabs. Maybe some favicon wizard
// knows how to get high-res favicons easily, or we could offer actor
// support for this (bug 1061654).
if (url.origin) {
tab.favicon = url.origin + "/favicon.ico";
}
tab.name = tab.title || Strings.GetStringFromName("project_tab_loading");
if (url.protocol.startsWith("http")) {
tab.name = url.hostname + ": " + tab.name;
}
const panelItemNode = this._doc.createElement(this._panelNodeEl);
panelItemNode.className = "panel-item";
tabsNode.appendChild(panelItemNode);
this._renderProjectItem({
panel: panelItemNode,
name: tab.name,
icon: tab.favicon || AppManager.DEFAULT_PROJECT_ICON,
});
panelItemNode.addEventListener(
"click",
() => {
AppManager.selectedProject = {
type: "tab",
app: tab,
icon: tab.favicon || AppManager.DEFAULT_PROJECT_ICON,
location: tab.url,
name: tab.name,
};
},
true
);
}
return Promise.resolve();
},
updateApps: function() {
const doc = this._doc;
const runtimeappsHeaderNode = doc.querySelector(
"#panel-header-runtimeapps"
);
let sortedApps = [];
for (const [, /* manifestURL */ app] of AppManager.apps) {
sortedApps.push(app);
}
sortedApps = sortedApps.sort((a, b) => {
return a.manifest.name > b.manifest.name;
});
const mainProcess = AppManager.isMainProcessDebuggable();
if (AppManager.connected && (sortedApps.length > 0 || mainProcess)) {
runtimeappsHeaderNode.removeAttribute("hidden");
} else {
runtimeappsHeaderNode.setAttribute("hidden", "true");
}
const runtimeAppsNode = doc.querySelector("#project-panel-runtimeapps");
while (runtimeAppsNode.hasChildNodes()) {
runtimeAppsNode.firstChild.remove();
}
if (mainProcess) {
const panelItemNode = doc.createElement(this._panelNodeEl);
panelItemNode.className = "panel-item";
this._renderProjectItem({
panel: panelItemNode,
name: Strings.GetStringFromName("mainProcess_label"),
icon: AppManager.DEFAULT_PROJECT_ICON,
});
runtimeAppsNode.appendChild(panelItemNode);
panelItemNode.addEventListener(
"click",
() => {
AppManager.selectedProject = {
type: "mainProcess",
name: Strings.GetStringFromName("mainProcess_label"),
icon: AppManager.DEFAULT_PROJECT_ICON,
};
},
true
);
}
for (let i = 0; i < sortedApps.length; i++) {
const app = sortedApps[i];
const panelItemNode = doc.createElement(this._panelNodeEl);
panelItemNode.className = "panel-item";
this._renderProjectItem({
panel: panelItemNode,
name: app.manifest.name,
icon: app.iconURL || AppManager.DEFAULT_PROJECT_ICON,
});
runtimeAppsNode.appendChild(panelItemNode);
panelItemNode.addEventListener(
"click",
() => {
AppManager.selectedProject = {
type: "runtimeApp",
app: app.manifest,
icon: app.iconURL || AppManager.DEFAULT_PROJECT_ICON,
name: app.manifest.name,
};
},
true
);
}
return Promise.resolve();
},
updateCommands: function() {
const doc = this._doc;
const newAppCmd = doc.querySelector("#new-app");
const packagedAppCmd = doc.querySelector("#packaged-app");
const hostedAppCmd = doc.querySelector("#hosted-app");
if (!newAppCmd || !packagedAppCmd || !hostedAppCmd) {
return;
}
if (
this._parentWindow.document
.querySelector("window")
.classList.contains("busy")
) {
newAppCmd.setAttribute("disabled", "true");
packagedAppCmd.setAttribute("disabled", "true");
hostedAppCmd.setAttribute("disabled", "true");
return;
}
newAppCmd.removeAttribute("disabled");
packagedAppCmd.removeAttribute("disabled");
hostedAppCmd.removeAttribute("disabled");
},
/**
* Trigger an update of the project and remote runtime list.
* @param options object (optional)
* An |options| object containing a type of |apps| or |tabs| will limit
* what is updated to only those sections.
*/
update: function(options) {
if (options && options.type === "apps") {
return this.updateApps();
} else if (options && options.type === "tabs") {
return this.updateTabs();
}
return new Promise((resolve, reject) => {
const doc = this._doc;
const projectsNode = doc.querySelector("#project-panel-projects");
while (projectsNode.hasChildNodes()) {
projectsNode.firstChild.remove();
}
AppProjects.load().then(() => {
const projects = AppProjects.projects;
for (let i = 0; i < projects.length; i++) {
const project = projects[i];
const panelItemNode = doc.createElement(this._panelNodeEl);
panelItemNode.className = "panel-item";
projectsNode.appendChild(panelItemNode);
if (!project.validationStatus) {
// The result of the validation process (storing names, icons, …) is not stored in
// the IndexedDB database when App Manager v1 is used.
// We need to run the validation again and update the name and icon of the app.
AppManager.validateAndUpdateProject(project).then(() => {
this._renderProjectItem({
panel: panelItemNode,
name: project.name,
icon: project.icon,
});
});
} else {
this._renderProjectItem({
panel: panelItemNode,
name: project.name || AppManager.DEFAULT_PROJECT_NAME,
icon: project.icon || AppManager.DEFAULT_PROJECT_ICON,
});
}
panelItemNode.addEventListener(
"click",
() => {
AppManager.selectedProject = project;
},
true
);
}
resolve();
}, reject);
// List remote apps and the main process, if they exist
this.updateApps();
// Build the tab list right now, so it's fast...
this.updateTabs();
// But re-list them and rebuild, in case any tabs navigated since the last
// time they were listed.
if (AppManager.connected) {
AppManager.listTabs()
.then(() => {
this.updateTabs();
})
.catch(console.error);
}
});
},
destroy: function() {
this._doc = null;
AppManager.off("app-manager-update", this.appManagerUpdate);
this._UI.off("webide-update", this.onWebIDEUpdate);
this._UI = null;
this._parentWindow = null;
this._panelNodeEl = null;
},
};

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

@ -1,226 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Services = require("Services");
const { AppManager } = require("devtools/client/webide/modules/app-manager");
const EventEmitter = require("devtools/shared/event-emitter");
const {
RuntimeScanners,
WiFiScanner,
} = require("devtools/client/webide/modules/runtimes");
const { adbAddon, ADB_ADDON_STATES } = require("devtools/shared/adb/adb-addon");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/webide.properties"
);
var RuntimeList;
module.exports = RuntimeList = function(window, parentWindow) {
EventEmitter.decorate(this);
this._doc = window.document;
this._UI = parentWindow.UI;
this._Cmds = parentWindow.Cmds;
this._parentWindow = parentWindow;
this._panelNodeEl = "button";
this._panelBoxEl = "div";
this.onWebIDEUpdate = this.onWebIDEUpdate.bind(this);
this._UI.on("webide-update", this.onWebIDEUpdate);
AppManager.init();
this.appManagerUpdate = this.appManagerUpdate.bind(this);
AppManager.on("app-manager-update", this.appManagerUpdate);
};
RuntimeList.prototype = {
get doc() {
return this._doc;
},
appManagerUpdate: function(what, details) {
// Got a message from app-manager.js
// See AppManager.update() for descriptions of what these events mean.
switch (what) {
case "runtime-list":
this.update();
break;
case "connection":
case "runtime-global-actors":
this.updateCommands();
break;
}
},
onWebIDEUpdate: function(what, details) {
if (what == "busy" || what == "unbusy") {
this.updateCommands();
}
},
takeScreenshot: function() {
this._Cmds.takeScreenshot();
},
showRuntimeDetails: function() {
this._Cmds.showRuntimeDetails();
},
showDevicePreferences: function() {
this._Cmds.showDevicePrefs();
},
showSettings: function() {
this._Cmds.showSettings();
},
showPerformancePanel: function() {
this._Cmds.showPerformancePanel();
},
showTroubleShooting: function() {
this._Cmds.showTroubleShooting();
},
showAddons: function() {
this._Cmds.showAddons();
},
refreshScanners: function() {
RuntimeScanners.scan();
},
updateCommands: function() {
const doc = this._doc;
// Runtime commands
const screenshotCmd = doc.querySelector("#runtime-screenshot");
const detailsCmd = doc.querySelector("#runtime-details");
const disconnectCmd = doc.querySelector("#runtime-disconnect");
const devicePrefsCmd = doc.querySelector("#runtime-preferences");
const settingsCmd = doc.querySelector("#runtime-settings");
const performanceCmd = doc.querySelector("#runtime-performance");
// Display the performance button only if the pref is enabled
performanceCmd.hidden = !Services.prefs.getBoolPref(
"devtools.performance.new-panel-enabled",
false
);
if (AppManager.connected) {
if (AppManager.deviceFront) {
detailsCmd.removeAttribute("disabled");
screenshotCmd.removeAttribute("disabled");
}
if (AppManager.preferenceFront) {
devicePrefsCmd.removeAttribute("disabled");
}
disconnectCmd.removeAttribute("disabled");
if (AppManager.perfFront) {
performanceCmd.removeAttribute("disabled");
}
} else {
detailsCmd.setAttribute("disabled", "true");
screenshotCmd.setAttribute("disabled", "true");
disconnectCmd.setAttribute("disabled", "true");
devicePrefsCmd.setAttribute("disabled", "true");
settingsCmd.setAttribute("disabled", "true");
performanceCmd.setAttribute("disabled", "true");
}
},
update: function() {
const doc = this._doc;
const wifiHeaderNode = doc.querySelector("#runtime-header-wifi");
if (WiFiScanner.allowed) {
wifiHeaderNode.removeAttribute("hidden");
} else {
wifiHeaderNode.setAttribute("hidden", "true");
}
const usbListNode = doc.querySelector("#runtime-panel-usb");
const wifiListNode = doc.querySelector("#runtime-panel-wifi");
const otherListNode = doc.querySelector("#runtime-panel-other");
const noADBExtensionNode = doc.querySelector(
"#runtime-panel-noadbextension"
);
const noUSBNode = doc.querySelector("#runtime-panel-nousbdevice");
noADBExtensionNode.textContent = Strings.formatStringFromName(
"runtimePanel_noadbextension",
["ADB Extension"]
);
if (adbAddon.status === ADB_ADDON_STATES.INSTALLED) {
noADBExtensionNode.setAttribute("hidden", "true");
} else {
noADBExtensionNode.removeAttribute("hidden");
}
const runtimeList = AppManager.runtimeList;
if (!runtimeList) {
return;
}
if (
runtimeList.usb.length === 0 &&
adbAddon.status === ADB_ADDON_STATES.INSTALLED
) {
noUSBNode.removeAttribute("hidden");
} else {
noUSBNode.setAttribute("hidden", "true");
}
for (const [type, parent] of [
["usb", usbListNode],
["wifi", wifiListNode],
["other", otherListNode],
]) {
while (parent.hasChildNodes()) {
parent.firstChild.remove();
}
for (const runtime of runtimeList[type]) {
const r = runtime;
const panelItemNode = doc.createElement(this._panelBoxEl);
panelItemNode.className = "panel-item-complex";
const connectButton = doc.createElement(this._panelNodeEl);
connectButton.className = "panel-item runtime-panel-item-" + type;
connectButton.textContent = r.name;
connectButton.addEventListener(
"click",
() => {
this._UI.dismissErrorNotification();
this._UI.connectToRuntime(r);
},
true
);
panelItemNode.appendChild(connectButton);
if (r.configure) {
const configButton = doc.createElement(this._panelNodeEl);
configButton.className = "configure-button";
configButton.addEventListener("click", r.configure.bind(r), true);
panelItemNode.appendChild(configButton);
}
parent.appendChild(panelItemNode);
}
}
},
destroy: function() {
this._doc = null;
AppManager.off("app-manager-update", this.appManagerUpdate);
this._UI.off("webide-update", this.onWebIDEUpdate);
this._UI = null;
this._Cmds = null;
this._parentWindow = null;
this._panelNodeEl = null;
},
};

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

@ -1,17 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// These type strings are used for logging events to Telemetry.
// You must update Histograms.json if new types are added.
const RuntimeTypes = {
USB: "USB",
WIFI: "WIFI",
REMOTE: "REMOTE",
LOCAL: "LOCAL",
OTHER: "OTHER",
};
exports.RuntimeTypes = RuntimeTypes;

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

@ -1,491 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Services = require("Services");
const { DebuggerServer } = require("devtools/server/debugger-server");
const discovery = require("devtools/shared/discovery/discovery");
const EventEmitter = require("devtools/shared/event-emitter");
const {
RuntimeTypes,
} = require("devtools/client/webide/modules/runtime-types");
const promise = require("promise");
loader.lazyRequireGetter(this, "adb", "devtools/shared/adb/adb", true);
loader.lazyRequireGetter(
this,
"AuthenticationResult",
"devtools/shared/security/auth",
true
);
loader.lazyRequireGetter(
this,
"DevToolsUtils",
"devtools/shared/DevToolsUtils"
);
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/webide.properties"
);
/**
* Runtime and Scanner API
*
* |RuntimeScanners| maintains a set of |Scanner| objects that produce one or
* more |Runtime|s to connect to. Add-ons can extend the set of known runtimes
* by registering additional |Scanner|s that emit them.
*
* Each |Scanner| must support the following API:
*
* enable()
* Bind any event handlers and start any background work the scanner needs to
* maintain an updated set of |Runtime|s.
* Called when the first consumer (such as WebIDE) actively interested in
* maintaining the |Runtime| list enables the registry.
* disable()
* Unbind any event handlers and stop any background work the scanner needs to
* maintain an updated set of |Runtime|s.
* Called when the last consumer (such as WebIDE) actively interested in
* maintaining the |Runtime| list disables the registry.
* emits "runtime-list-updated"
* If the set of runtimes a |Scanner| manages has changed, it must emit this
* event to notify consumers of changes.
* scan()
* Actively refreshes the list of runtimes the scanner knows about. If your
* scanner uses an active scanning approach (as opposed to listening for
* events when changes occur), the bulk of the work would be done here.
* @return Promise
* Should be resolved when scanning is complete. If scanning has no
* well-defined end point, you can resolve immediately, as long as
* update event is emitted later when changes are noticed.
* listRuntimes()
* Return the current list of runtimes known to the |Scanner| instance.
* @return Iterable
*
* Each |Runtime| must support the following API:
*
* |type| field
* The |type| must be one of the values from the |RuntimeTypes| object. This
* is used for Telemetry and to support displaying sets of |Runtime|s
* categorized by type.
* |id| field
* An identifier that is unique in the set of all runtimes with the same
* |type|. WebIDE tries to save the last used runtime via type + id, and
* tries to locate it again in the next session, so this value should attempt
* to be stable across Firefox sessions.
* |name| field
* A user-visible label to identify the runtime that will be displayed in a
* runtime list.
* |prolongedConnection| field
* A boolean value which should be |true| if the connection process is
* expected to take a unknown or large amount of time. A UI may use this as a
* hint to skip timeouts or other time-based code paths.
* connect()
* Configure the passed |connection| object with any settings need to
* successfully connect to the runtime, and call the |connection|'s connect()
* method.
* @param Connection connection
* A |Connection| object from the DevTools |ConnectionManager|.
* @return Promise
* Resolved once you've called the |connection|'s connect() method.
* configure() OPTIONAL
* Show a configuration screen if the runtime is configurable.
*/
/* SCANNER REGISTRY */
var RuntimeScanners = {
_enabledCount: 0,
_scanners: new Set(),
get enabled() {
return !!this._enabledCount;
},
add(scanner) {
if (this.enabled) {
// Enable any scanner added while globally enabled
this._enableScanner(scanner);
}
this._scanners.add(scanner);
this._emitUpdated();
},
remove(scanner) {
this._scanners.delete(scanner);
if (this.enabled) {
// Disable any scanner removed while globally enabled
this._disableScanner(scanner);
}
this._emitUpdated();
},
has(scanner) {
return this._scanners.has(scanner);
},
scan() {
if (!this.enabled) {
return promise.resolve();
}
if (this._scanPromise) {
return this._scanPromise;
}
const promises = [];
for (const scanner of this._scanners) {
promises.push(scanner.scan());
}
this._scanPromise = promise.all(promises);
// Reset pending promise
this._scanPromise.then(
() => {
this._scanPromise = null;
},
() => {
this._scanPromise = null;
}
);
return this._scanPromise;
},
listRuntimes: function*() {
for (const scanner of this._scanners) {
for (const runtime of scanner.listRuntimes()) {
yield runtime;
}
}
},
_emitUpdated() {
this.emit("runtime-list-updated");
},
enable() {
if (this._enabledCount++ !== 0) {
// Already enabled scanners during a previous call
return;
}
this._emitUpdated = this._emitUpdated.bind(this);
for (const scanner of this._scanners) {
this._enableScanner(scanner);
}
},
_enableScanner(scanner) {
scanner.enable();
scanner.on("runtime-list-updated", this._emitUpdated);
},
disable() {
if (--this._enabledCount !== 0) {
// Already disabled scanners during a previous call
return;
}
for (const scanner of this._scanners) {
this._disableScanner(scanner);
}
},
_disableScanner(scanner) {
scanner.off("runtime-list-updated", this._emitUpdated);
scanner.disable();
},
};
EventEmitter.decorate(RuntimeScanners);
exports.RuntimeScanners = RuntimeScanners;
/* SCANNERS */
var UsbScanner = {
init() {
this._emitUpdated = this._emitUpdated.bind(this);
},
enable() {
adb.registerListener(this._emitUpdated);
},
disable() {
adb.unregisterListener(this._emitUpdated);
},
scan() {
return adb.updateRuntimes();
},
listRuntimes() {
return adb.getRuntimes();
},
_emitUpdated() {
this.emit("runtime-list-updated");
},
};
EventEmitter.decorate(UsbScanner);
UsbScanner.init();
RuntimeScanners.add(UsbScanner);
var WiFiScanner = {
_runtimes: [],
init() {
this.updateRegistration();
Services.prefs.addObserver(this.ALLOWED_PREF, this);
},
enable() {
this._updateRuntimes = this._updateRuntimes.bind(this);
discovery.on("devtools-device-added", this._updateRuntimes);
discovery.on("devtools-device-updated", this._updateRuntimes);
discovery.on("devtools-device-removed", this._updateRuntimes);
this._updateRuntimes();
},
disable() {
discovery.off("devtools-device-added", this._updateRuntimes);
discovery.off("devtools-device-updated", this._updateRuntimes);
discovery.off("devtools-device-removed", this._updateRuntimes);
},
_emitUpdated() {
this.emit("runtime-list-updated");
},
_updateRuntimes() {
this._runtimes = [];
for (const device of discovery.getRemoteDevicesWithService("devtools")) {
this._runtimes.push(new WiFiRuntime(device));
}
this._emitUpdated();
},
scan() {
discovery.scan();
return promise.resolve();
},
listRuntimes: function() {
return this._runtimes;
},
ALLOWED_PREF: "devtools.remote.wifi.scan",
get allowed() {
return Services.prefs.getBoolPref(this.ALLOWED_PREF);
},
updateRegistration() {
if (this.allowed) {
RuntimeScanners.add(WiFiScanner);
} else {
RuntimeScanners.remove(WiFiScanner);
}
this._emitUpdated();
},
observe(subject, topic, data) {
if (data !== WiFiScanner.ALLOWED_PREF) {
return;
}
WiFiScanner.updateRegistration();
},
};
EventEmitter.decorate(WiFiScanner);
WiFiScanner.init();
exports.WiFiScanner = WiFiScanner;
var StaticScanner = {
enable() {},
disable() {},
scan() {
return promise.resolve();
},
listRuntimes() {
const runtimes = [gRemoteRuntime];
if (Services.prefs.getBoolPref("devtools.webide.enableLocalRuntime")) {
runtimes.push(gLocalRuntime);
}
return runtimes;
},
};
EventEmitter.decorate(StaticScanner);
RuntimeScanners.add(StaticScanner);
exports.RuntimeTypes = RuntimeTypes;
function WiFiRuntime(deviceName) {
this.deviceName = deviceName;
}
WiFiRuntime.prototype = {
type: RuntimeTypes.WIFI,
// Mark runtime as taking a long time to connect
prolongedConnection: true,
connect: function(connection) {
const service = discovery.getRemoteService("devtools", this.deviceName);
if (!service) {
return promise.reject(new Error("Can't find device: " + this.name));
}
connection.advertisement = service;
connection.authenticator.sendOOB = this.sendOOB;
// Disable the default connection timeout, since QR scanning can take an
// unknown amount of time. This prevents spurious errors (even after
// eventual success) from being shown.
connection.timeoutDelay = 0;
connection.connect();
return promise.resolve();
},
get id() {
return this.deviceName;
},
get name() {
return this.deviceName;
},
/**
* During OOB_CERT authentication, a notification dialog like this is used to
* to display a token which the user must transfer through some mechanism to the
* server to authenticate the devices.
*
* This implementation presents the token as text for the user to transfer
* manually. For a mobile device, you should override this implementation with
* something more convenient, such as displaying a QR code.
*
* This method receives an object containing:
* @param host string
* The host name or IP address of the debugger server.
* @param port number
* The port number of the debugger server.
* @param cert object (optional)
* The server's cert details.
* @param authResult AuthenticationResult
* Authentication result sent from the server.
* @param oob object (optional)
* The token data to be transferred during OOB_CERT step 8:
* * sha256: hash(ClientCert)
* * k : K(random 128-bit number)
* @return object containing:
* * close: Function to hide the notification
*/
sendOOB(session) {
const WINDOW_ID = "devtools:wifi-auth";
const { authResult } = session;
// Only show in the PENDING state
if (authResult != AuthenticationResult.PENDING) {
throw new Error("Expected PENDING result, got " + authResult);
}
// Listen for the window our prompt opens, so we can close it programatically
let promptWindow;
const windowListener = {
onOpenWindow(xulWindow) {
const win = xulWindow.docShell.domWindow;
win.addEventListener(
"load",
function() {
if (win.document.documentElement.getAttribute("id") != WINDOW_ID) {
return;
}
// Found the window
promptWindow = win;
Services.wm.removeListener(windowListener);
},
{ once: true }
);
},
onCloseWindow() {},
};
Services.wm.addListener(windowListener);
// |openDialog| is typically a blocking API, so |executeSoon| to get around this
DevToolsUtils.executeSoon(() => {
// Height determines the size of the QR code. Force a minimum size to
// improve scanability.
const MIN_HEIGHT = 600;
const win = Services.wm.getMostRecentWindow("devtools:webide");
const width = win.outerWidth * 0.8;
const height = Math.max(win.outerHeight * 0.5, MIN_HEIGHT);
win.openDialog(
"chrome://webide/content/wifi-auth.xhtml",
WINDOW_ID,
"modal=yes,width=" + width + ",height=" + height,
session
);
});
return {
close() {
if (!promptWindow) {
return;
}
promptWindow.close();
promptWindow = null;
},
};
},
};
// For testing use only
exports._WiFiRuntime = WiFiRuntime;
var gLocalRuntime = {
type: RuntimeTypes.LOCAL,
connect: function(connection) {
DebuggerServer.init();
DebuggerServer.registerAllActors();
DebuggerServer.allowChromeProcess = true;
connection.host = null; // Force Pipe transport
connection.port = null;
connection.connect();
return promise.resolve();
},
get id() {
return "local";
},
get name() {
return Strings.GetStringFromName("local_runtime");
},
};
// For testing use only
exports._gLocalRuntime = gLocalRuntime;
var gRemoteRuntime = {
type: RuntimeTypes.REMOTE,
connect: function(connection) {
const win = Services.wm.getMostRecentWindow("devtools:webide");
if (!win) {
return promise.reject(new Error("No WebIDE window found"));
}
const ret = { value: connection.host + ":" + connection.port };
const title = Strings.GetStringFromName("remote_runtime_promptTitle");
const message = Strings.GetStringFromName("remote_runtime_promptMessage");
const ok = Services.prompt.prompt(win, title, message, ret, null, {});
const [host, port] = ret.value.split(":");
if (!ok) {
return promise.reject({ canceled: true });
}
if (!host || !port) {
return promise.reject(new Error("Invalid host or port"));
}
connection.host = host;
connection.port = port;
connection.connect();
return promise.resolve();
},
get name() {
return Strings.GetStringFromName("remote_runtime");
},
};
// For testing use only
exports._gRemoteRuntime = gRemoteRuntime;

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

@ -1,177 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const EventEmitter = require("devtools/shared/event-emitter");
const { Connection } = require("devtools/shared/client/connection-manager");
const _knownTabStores = new WeakMap();
var TabStore;
module.exports = TabStore = function(connection) {
// If we already know about this connection,
// let's re-use the existing store.
if (_knownTabStores.has(connection)) {
return _knownTabStores.get(connection);
}
_knownTabStores.set(connection, this);
EventEmitter.decorate(this);
this._resetStore();
this.destroy = this.destroy.bind(this);
this._onStatusChanged = this._onStatusChanged.bind(this);
this._connection = connection;
this._connection.once(Connection.Events.DESTROYED, this.destroy);
this._connection.on(Connection.Events.STATUS_CHANGED, this._onStatusChanged);
this._onTabListChanged = this._onTabListChanged.bind(this);
this._onTabNavigated = this._onTabNavigated.bind(this);
this._onStatusChanged();
return this;
};
TabStore.prototype = {
destroy: function() {
if (this._connection) {
// While this.destroy is bound using .once() above, that event may not
// have occurred when the TabStore client calls destroy, so we
// manually remove it here.
this._connection.off(Connection.Events.DESTROYED, this.destroy);
this._connection.off(
Connection.Events.STATUS_CHANGED,
this._onStatusChanged
);
_knownTabStores.delete(this._connection);
this._connection = null;
}
},
_resetStore: function() {
this.tabs = [];
this._selectedTab = null;
this._selectedTabTargetPromise = null;
},
_onStatusChanged: function() {
if (this._connection.status == Connection.Status.CONNECTED) {
// Watch for changes to remote browser tabs
this._connection.client.mainRoot.on(
"tabListChanged",
this._onTabListChanged
);
this.listTabs();
} else {
if (this._connection.client) {
this._connection.client.mainRoot.off(
"tabListChanged",
this._onTabListChanged
);
}
this._resetStore();
}
},
_onTabListChanged: function() {
this.listTabs()
.then(() => this.emit("tab-list"))
.catch(console.error);
},
_onTabNavigated: function(e, { from, title, url }) {
if (!this._selectedTab || from !== this._selectedTab.actor) {
return;
}
this._selectedTab.url = url;
this._selectedTab.title = title;
this.emit("navigate");
},
listTabs: function() {
if (!this._connection || !this._connection.client) {
return Promise.reject(new Error("Can't listTabs, not connected."));
}
return new Promise((resolve, reject) => {
this._connection.client.mainRoot.listTabs().then(
tabs => {
// To avoid refactoring WebIDE while switching from form to Target Front for
// listTabs. Convert front to form list here.
tabs = tabs.map(tab => tab.targetForm);
const tabsChanged =
JSON.stringify(this.tabs) !== JSON.stringify(tabs);
this.tabs = tabs;
this._checkSelectedTab();
if (tabsChanged) {
this.emit("tab-list");
}
resolve(tabs);
},
error => {
this._connection.disconnect();
reject(error);
}
);
});
},
// TODO: Tab "selection" should really take place by creating a TabProject
// which is the selected project. This should be done as part of the
// project-agnostic work.
_selectedTab: null,
_selectedTabTargetPromise: null,
get selectedTab() {
return this._selectedTab;
},
set selectedTab(tab) {
if (this._selectedTab === tab) {
return;
}
this._selectedTab = tab;
this._selectedTabTargetPromise = null;
// Attach to the tab to follow navigation events
if (this._selectedTab) {
this.getTargetForTab();
}
},
_checkSelectedTab: function() {
if (!this._selectedTab) {
return;
}
const alive = this.tabs.some(tab => {
return tab.actor === this._selectedTab.actor;
});
if (!alive) {
this._selectedTab = null;
this._selectedTabTargetPromise = null;
this.emit("closed");
}
},
getTargetForTab: function() {
if (this._selectedTabTargetPromise) {
return this._selectedTabTargetPromise;
}
const store = this;
this._selectedTabTargetPromise = (async function() {
// If you connect to a tab, then detach from it, the root actor may have
// de-listed the actors that belong to the tab. This breaks the toolbox
// if you try to connect to the same tab again. To work around this
// issue, we force a "listTabs" request before connecting to a tab.
await store.listTabs();
const { outerWindowID } = store._selectedTab;
return store._connection.client.mainRoot.getTab({ outerWindowID });
})();
this._selectedTabTargetPromise.then(target => {
target.once("close", () => {
this._selectedTabTargetPromise = null;
});
});
return this._selectedTabTargetPromise;
},
};

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

@ -1,95 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { Cc, Ci } = require("chrome");
const { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
const Services = require("Services");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/webide.properties"
);
function doesFileExist(location) {
const file = new FileUtils.File(location);
return file.exists();
}
exports.doesFileExist = doesFileExist;
function _getFile(location, ...pickerParams) {
if (location) {
return Promise.resolve(new FileUtils.File(location));
}
const fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(...pickerParams);
return new Promise(resolve => {
fp.open(res => {
if (res == Ci.nsIFilePicker.returnCancel) {
resolve(null);
} else {
resolve(fp.file);
}
});
});
}
function getCustomBinary(window, location) {
return _getFile(
location,
window,
Strings.GetStringFromName("selectCustomBinary_title"),
Ci.nsIFilePicker.modeOpen
);
}
exports.getCustomBinary = getCustomBinary;
function getCustomProfile(window, location) {
return _getFile(
location,
window,
Strings.GetStringFromName("selectCustomProfile_title"),
Ci.nsIFilePicker.modeGetFolder
);
}
exports.getCustomProfile = getCustomProfile;
function getPackagedDirectory(window, location) {
return _getFile(
location,
window,
Strings.GetStringFromName("importPackagedApp_title"),
Ci.nsIFilePicker.modeGetFolder
);
}
exports.getPackagedDirectory = getPackagedDirectory;
function getHostedURL(window, location) {
const ret = { value: null };
if (!location) {
Services.prompt.prompt(
window,
Strings.GetStringFromName("importHostedApp_title"),
Strings.GetStringFromName("importHostedApp_header"),
ret,
null,
{}
);
location = ret.value;
}
if (!location) {
return null;
}
// Clean location string and add "http://" if missing
location = location.trim();
try {
// Will fail if no scheme
Services.io.extractScheme(location);
} catch (e) {
location = "http://" + location;
}
return location;
}
exports.getHostedURL = getHostedURL;

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

@ -1,21 +0,0 @@
# -*- Mode: python; 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/.
DIRS += [
'content',
'modules',
'themes',
]
BROWSER_CHROME_MANIFESTS += [
'test/browser.ini'
]
MOCHITEST_CHROME_MANIFESTS += [
'test/chrome.ini'
]
with Files('**'):
BUG_COMPONENT = ('DevTools', 'WebIDE')

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

@ -1,6 +0,0 @@
"use strict";
module.exports = {
// Extend from the shared list of defined globals for mochitests.
"extends": "../../../.eslintrc.mochitests.js"
};

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

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

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

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

Двоичные данные
devtools/client/webide/test/app.zip

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

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

@ -1,6 +0,0 @@
<!doctype html>
<html>
<head><title></title></head>
<body>
</body>
</html>

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

@ -1,5 +0,0 @@
{
"name": "A name (in app directory)",
"description": "desc",
"launch_path": "/index.html"
}

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

@ -1,11 +0,0 @@
[DEFAULT]
tags = devtools
skip-if = asan || debug # bug 1078284 too many intermittents for these tests
subsuite = devtools
support-files =
doc_tabs.html
head.js
templates.json
[browser_tabs.js]
skip-if = e10s # Bug 1072167 - browser_tabs.js test fails under e10s

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

@ -1,83 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_URI =
"http://example.com/browser/devtools/client/webide/test/doc_tabs.html";
function test() {
waitForExplicitFinish();
SimpleTest.requestCompleteLog();
(async function() {
// Since we test the connections set below, destroy the server in case it
// was left open.
DebuggerServer.destroy();
DebuggerServer.init();
DebuggerServer.registerAllActors();
let tab = await addTab(TEST_URI);
const win = await openWebIDE();
const docProject = getProjectDocument(win);
const docRuntime = getRuntimeDocument(win);
await connectToLocal(win, docRuntime);
is(Object.keys(DebuggerServer._connections).length, 1, "Locally connected");
await selectTabProject(win, docProject);
ok(win.UI.toolboxPromise, "Toolbox promise exists");
await win.UI.toolboxPromise;
const project = win.AppManager.selectedProject;
is(project.location, TEST_URI, "Location is correct");
is(project.name, "example.com: Test Tab", "Name is correct");
// Ensure tab list changes are noticed
const tabsNode = docProject.querySelector("#project-panel-tabs");
is(tabsNode.querySelectorAll(".panel-item").length, 2, "2 tabs available");
await removeTab(tab);
await waitForUpdate(win, "project");
await waitForUpdate(win, "runtime-targets");
is(tabsNode.querySelectorAll(".panel-item").length, 1, "1 tab available");
tab = await addTab(TEST_URI);
is(tabsNode.querySelectorAll(".panel-item").length, 2, "2 tabs available");
await removeTab(tab);
is(tabsNode.querySelectorAll(".panel-item").length, 2, "2 tabs available");
docProject.querySelector("#refresh-tabs").click();
await waitForUpdate(win, "runtime-targets");
is(tabsNode.querySelectorAll(".panel-item").length, 1, "1 tab available");
await win.Cmds.disconnectRuntime();
await closeWebIDE(win);
DebuggerServer.destroy();
})().then(finish, handleError);
}
function connectToLocal(win, docRuntime) {
return new Promise(resolve => {
win.AppManager.connection.once(win.Connection.Events.CONNECTED, resolve);
docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
});
}
function selectTabProject(win, docProject) {
return (async function() {
await waitForUpdate(win, "runtime-targets");
const tabsNode = docProject.querySelector("#project-panel-tabs");
const tabNode = tabsNode.querySelectorAll(".panel-item")[1];
const project = waitForUpdate(win, "project");
tabNode.click();
await project;
})();
}

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

@ -1,5 +0,0 @@
{
"webide": {
"prepackage": "echo \"{\\\"name\\\":\\\"hello\\\"}\" > manifest.webapp"
}
}

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

@ -1 +0,0 @@
{}

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

@ -1,10 +0,0 @@
{
"webide": {
"prepackage": {
"command": "echo \"{\\\"name\\\":\\\"$NAME\\\"}\" > manifest.webapp",
"cwd": "./stage",
"env": ["NAME=world"]
},
"packageDir": "./stage"
}
}

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

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

@ -1,5 +0,0 @@
{
"webide": {
"prepackage": "echo {\"name\":\"hello\"} > manifest.webapp"
}
}

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

@ -1 +0,0 @@
{}

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

@ -1,10 +0,0 @@
{
"webide": {
"prepackage": {
"command": "echo {\"name\":\"%NAME%\"} > manifest.webapp",
"cwd": "./stage",
"env": ["NAME=world"]
},
"packageDir": "./stage"
}
}

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

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

@ -1,45 +0,0 @@
[DEFAULT]
tags = devtools
skip-if = asan || debug # bug 1078284 too many intermittents for these tests
support-files =
app/index.html
app/manifest.webapp
app.zip
addons/adb-extension-linux.xpi
addons/adb-extension-linux64.xpi
addons/adb-extension-win32.xpi
addons/adb-extension-mac64.xpi
build_app1/package.json
build_app2/manifest.webapp
build_app2/package.json
build_app2/stage/empty-directory
build_app_windows1/package.json
build_app_windows2/manifest.webapp
build_app_windows2/package.json
build_app_windows2/stage/empty-directory
device_front_shared.js
head.js
hosted_app.manifest
templates.json
../../shared/test/browser_devices.json
validator/*
[test_basic.html]
[test_newapp.html]
skip-if = (os == "win" && os_version == "10.0") # Bug 1197053
[test_import.html]
skip-if = (os == "linux") # Bug 1024734
[test_duplicate_import.html]
[test_runtime.html]
[test_manifestUpdate.html]
[test_addons.html]
[test_deprecation_message.html]
[test_device_runtime.html]
[test_autoconnect_runtime.html]
[test_autoselect_project.html]
[test_device_preferences.html]
[test_fullscreenToolbox.html]
[test_zoom.html]
[test_toolbox.html]
[test_app_validator.html]
[test_performance_panel.html]

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

@ -1,231 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint no-unused-vars: ["error", {"args": "none", "vars": "local"}] */
"use strict";
var customName;
var customValue;
var customValueType;
var customBtn;
var newField;
var change;
var doc;
var iframe;
var resetBtn;
var found = false;
function setDocument(frame) {
iframe = frame;
doc = iframe.contentWindow.document;
}
function fieldChange(fields, id) {
// Trigger existing field change
for (const field of fields) {
if (field.id == id) {
const button = doc.getElementById("btn-" + id);
found = true;
ok(button.classList.contains("hide"), "Default field detected");
field.value = "custom";
field.click();
ok(!button.classList.contains("hide"), "Custom field detected");
break;
}
}
ok(found, "Found " + id + " line");
}
function addNewField() {
found = false;
customName = doc.querySelector("#custom-value-name");
customValue = doc.querySelector("#custom-value-text");
customValueType = doc.querySelector("#custom-value-type");
customBtn = doc.querySelector("#custom-value");
change = doc.createEvent("HTMLEvents");
change.initEvent("change", false, true);
// Add a new custom string
customValueType.value = "string";
customValueType.dispatchEvent(change);
customName.value = "new-string-field!";
customValue.value = "test";
customBtn.click();
const newField = doc.querySelector("#new-string-field");
if (newField) {
found = true;
is(newField.type, "text", "Custom type is a string");
is(newField.value, "test", "Custom string new value is correct");
}
ok(found, "Found new string field line");
is(customName.value, "", "Custom string name reset");
is(customValue.value, "", "Custom string value reset");
}
function addNewFieldWithEnter() {
// Add a new custom value with the <enter> key
found = false;
customName.value = "new-string-field-two";
customValue.value = "test";
const newAddField = doc.querySelector("#add-custom-field");
const enter = doc.createEvent("KeyboardEvent");
enter.initKeyEvent(
"keyup",
true,
true,
null,
false,
false,
false,
false,
13,
0
);
newAddField.dispatchEvent(enter);
newField = doc.querySelector("#new-string-field-two");
if (newField) {
found = true;
is(newField.type, "text", "Custom type is a string");
is(newField.value, "test", "Custom string new value is correct");
}
ok(found, "Found new string field line");
is(customName.value, "", "Custom string name reset");
is(customValue.value, "", "Custom string value reset");
}
function editExistingField() {
// Edit existing custom string preference
newField.value = "test2";
newField.click();
is(newField.value, "test2", "Custom string existing value is correct");
}
function addNewFieldInteger() {
// Add a new custom integer preference with a valid integer
customValueType.value = "number";
customValueType.dispatchEvent(change);
customName.value = "new-integer-field";
customValue.value = 1;
found = false;
customBtn.click();
newField = doc.querySelector("#new-integer-field");
if (newField) {
found = true;
is(newField.type, "number", "Custom type is a number");
is(newField.value, "1", "Custom integer value is correct");
}
ok(found, "Found new integer field line");
is(customName.value, "", "Custom integer name reset");
is(customValue.value, "", "Custom integer value reset");
}
var editFieldInteger = async function() {
// Edit existing custom integer preference
newField.value = 3;
newField.click();
is(newField.value, "3", "Custom integer existing value is correct");
// Reset a custom field
const resetBtn = doc.querySelector("#btn-new-integer-field");
resetBtn.click();
try {
await iframe.contentWindow.configView._defaultField;
} catch (err) {
const fieldRow = doc.querySelector("#row-new-integer-field");
if (!fieldRow) {
found = false;
}
ok(!found, "Custom field removed");
}
};
var resetExistingField = async function(id) {
const existing = doc.getElementById(id);
existing.click();
is(existing.checked, true, "Existing boolean value is correct");
resetBtn = doc.getElementById("btn-" + id);
resetBtn.click();
await iframe.contentWindow.configView._defaultField;
ok(resetBtn.classList.contains("hide"), "Reset button hidden");
is(existing.checked, true, "Existing field reset");
};
var resetNewField = async function(id) {
const custom = doc.getElementById(id);
custom.click();
is(custom.value, "test", "New string value is correct");
resetBtn = doc.getElementById("btn-" + id);
resetBtn.click();
await iframe.contentWindow.configView._defaultField;
ok(resetBtn.classList.contains("hide"), true, "Reset button hidden");
};
function addNewFieldBoolean() {
customValueType.value = "boolean";
customValueType.dispatchEvent(change);
customName.value = "new-boolean-field";
customValue.checked = true;
found = false;
customBtn.click();
newField = doc.querySelector("#new-boolean-field");
if (newField) {
found = true;
is(newField.type, "checkbox", "Custom type is a checkbox");
is(newField.checked, true, "Custom boolean value is correctly true");
}
ok(found, "Found new boolean field line");
// Mouse event trigger
const mouseClick = new MouseEvent("click", {
canBubble: true,
cancelable: true,
view: doc.parent,
});
found = false;
customValueType.value = "boolean";
customValueType.dispatchEvent(change);
customName.value = "new-boolean-field2";
customValue.dispatchEvent(mouseClick);
customBtn.dispatchEvent(mouseClick);
newField = doc.querySelector("#new-boolean-field2");
if (newField) {
found = true;
is(newField.checked, true, "Custom boolean value is correctly false");
}
ok(found, "Found new second boolean field line");
is(customName.value, "", "Custom boolean name reset");
is(customValue.checked, false, "Custom boolean value reset");
newField.click();
is(newField.checked, false, "Custom boolean existing value is correct");
}
function searchFields(deck, keyword) {
// Search for a non-existent field
const searchField = doc.querySelector("#search-bar");
searchField.value = "![o_O]!";
searchField.click();
const fieldsTotal = doc.querySelectorAll("tr.edit-row").length;
let hiddenFields = doc.querySelectorAll("tr.hide");
is(hiddenFields.length, fieldsTotal, "Search keyword not found");
// Search for existing fields
searchField.value = keyword;
searchField.click();
hiddenFields = doc.querySelectorAll("tr.hide");
isnot(hiddenFields.length, fieldsTotal, "Search keyword found");
doc.querySelector("#close").click();
ok(!deck.selectedPanel, "No panel selected");
}

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

@ -1,15 +0,0 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Test Tab</title>
</head>
<body>
Test Tab
</body>
</html>

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

@ -1,276 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
var { AppConstants } = ChromeUtils.import(
"resource://gre/modules/AppConstants.jsm"
);
const { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
const { gDevTools } = require("devtools/client/framework/devtools");
var Services = require("Services");
const { AppProjects } = require("devtools/client/webide/modules/app-projects");
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const { DebuggerServer } = require("devtools/server/debugger-server");
var TEST_BASE;
if (window.location === AppConstants.BROWSER_CHROME_URL) {
TEST_BASE =
"chrome://mochitests/content/browser/devtools/client/webide/test/";
} else {
TEST_BASE = "chrome://mochitests/content/chrome/devtools/client/webide/test/";
}
Services.prefs.setBoolPref("devtools.webide.enabled", true);
Services.prefs.setBoolPref("devtools.webide.enableLocalRuntime", true);
Services.prefs.setCharPref(
"devtools.remote.adb.extensionURL",
TEST_BASE + "addons/adb-extension-#OS#.xpi"
);
Services.prefs.setCharPref(
"devtools.webide.templatesURL",
TEST_BASE + "templates.json"
);
Services.prefs.setCharPref(
"devtools.devices.url",
TEST_BASE + "browser_devices.json"
);
var registerCleanupFunction =
registerCleanupFunction || SimpleTest.registerCleanupFunction;
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.webide.enabled");
Services.prefs.clearUserPref("devtools.webide.enableLocalRuntime");
Services.prefs.clearUserPref("devtools.webide.autoinstallADBExtension");
Services.prefs.clearUserPref("devtools.webide.busyTimeout");
Services.prefs.clearUserPref("devtools.webide.lastSelectedProject");
Services.prefs.clearUserPref("devtools.webide.lastConnectedRuntime");
});
var openWebIDE = async function({ autoInstallAddons } = {}) {
info("opening WebIDE");
Services.prefs.setBoolPref(
"devtools.webide.autoinstallADBExtension",
!!autoInstallAddons
);
const win = Services.ww.openWindow(
null,
"chrome://webide/content/",
"webide",
"chrome,centerscreen,resizable",
null
);
await new Promise(resolve => {
win.addEventListener(
"load",
function() {
SimpleTest.requestCompleteLog();
SimpleTest.executeSoon(resolve);
},
{ once: true }
);
});
info("WebIDE open");
return win;
};
function closeWebIDE(win) {
info("Closing WebIDE");
return new Promise(resolve => {
win.addEventListener(
"unload",
function() {
info("WebIDE closed");
SimpleTest.executeSoon(resolve);
},
{ once: true }
);
win.close();
});
}
function removeAllProjects() {
return (async function() {
await AppProjects.load();
// use a new array so we're not iterating over the same
// underlying array that's being modified by AppProjects
const projects = AppProjects.projects.map(p => p.location);
for (let i = 0; i < projects.length; i++) {
await AppProjects.remove(projects[i]);
}
})();
}
function nextTick() {
return new Promise(resolve => {
SimpleTest.executeSoon(resolve);
});
}
function waitForUpdate(win, update) {
info("Wait: " + update);
return new Promise(resolve => {
win.AppManager.on("app-manager-update", function onUpdate(what) {
info("Got: " + what);
if (what !== update) {
return;
}
win.AppManager.off("app-manager-update", onUpdate);
resolve(win.UI._updatePromise);
});
});
}
function waitForTime(time) {
return new Promise(resolve => {
setTimeout(resolve, time);
});
}
function documentIsLoaded(doc) {
return new Promise(resolve => {
if (doc.readyState == "complete") {
resolve();
} else {
doc.addEventListener("readystatechange", function onChange() {
if (doc.readyState == "complete") {
doc.removeEventListener("readystatechange", onChange);
resolve();
}
});
}
});
}
function lazyIframeIsLoaded(iframe) {
return new Promise(resolve => {
iframe.addEventListener(
"load",
function() {
resolve(nextTick());
},
{ capture: true, once: true }
);
});
}
function addTab(aUrl, aWindow) {
info("Adding tab: " + aUrl);
return new Promise(resolve => {
const targetWindow = aWindow || window;
const targetBrowser = targetWindow.gBrowser;
targetWindow.focus();
const tab = (targetBrowser.selectedTab = targetBrowser.addTab(aUrl));
const linkedBrowser = tab.linkedBrowser;
BrowserTestUtils.browserLoaded(linkedBrowser).then(function() {
info("Tab added and finished loading: " + aUrl);
resolve(tab);
});
});
}
function removeTab(aTab, aWindow) {
info("Removing tab.");
return new Promise(resolve => {
const targetWindow = aWindow || window;
const targetBrowser = targetWindow.gBrowser;
const tabContainer = targetBrowser.tabContainer;
tabContainer.addEventListener(
"TabClose",
function(aEvent) {
info("Tab removed and finished closing.");
resolve();
},
{ once: true }
);
targetBrowser.removeTab(aTab);
});
}
function getRuntimeDocument(win) {
return win.document.querySelector("#runtime-listing-panel-details")
.contentDocument;
}
function getProjectDocument(win) {
return win.document.querySelector("#project-listing-panel-details")
.contentDocument;
}
function getRuntimeWindow(win) {
return win.document.querySelector("#runtime-listing-panel-details")
.contentWindow;
}
function getProjectWindow(win) {
return win.document.querySelector("#project-listing-panel-details")
.contentWindow;
}
function getAddonsDocument(win) {
return win.document.querySelector("#deck-panel-addons").contentDocument;
}
function connectToLocalRuntime(win) {
info("Loading local runtime.");
const runtimePanel = getRuntimeDocument(win);
const panelNode = runtimePanel.querySelector("#runtime-panel");
const items = panelNode.querySelectorAll(".runtime-panel-item-other");
is(items.length, 2, "Found 2 custom runtime buttons");
const updated = waitForUpdate(win, "runtime-global-actors");
items[1].click();
return updated;
}
function handleError(aError) {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
finish();
}
function waitForConnectionChange(expectedState, count = 1) {
return new Promise(resolve => {
const onConnectionChange = state => {
if (state != expectedState) {
return;
}
if (--count != 0) {
return;
}
DebuggerServer.off("connectionchange", onConnectionChange);
resolve();
};
DebuggerServer.on("connectionchange", onConnectionChange);
});
}
/**
* Copied from shared-head.js.
*/
function waitUntil(predicate, interval = 100) {
if (predicate()) {
return Promise.resolve(true);
}
return new Promise(resolve => {
setTimeout(function() {
waitUntil(predicate, interval).then(() => resolve(true));
}, interval);
});
}

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

@ -1,3 +0,0 @@
{
"name": "hosted manifest name property"
}

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

@ -1,14 +0,0 @@
[
{
"file": "chrome://mochitests/content/chrome/devtools/client/webide/test/app.zip?1",
"icon": "ximgx1",
"name": "app name 1",
"description": "app description 1"
},
{
"file": "chrome://mochitests/content/chrome/devtools/client/webide/test/app.zip?2",
"icon": "ximgx2",
"name": "app name 2",
"description": "app description 2"
}
]

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

@ -1,85 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
// XXX Bug 1072167 - When updating after migration, fix the no-undef issues.
/* eslint-disable no-undef */
window.onload = function() {
SimpleTest.waitForExplicitFinish();
const { adbAddon, ADB_ADDON_STATES } = require("devtools/shared/adb/adb-addon");
function isAdbAddonInstalled() {
return adbAddon.status === ADB_ADDON_STATES.INSTALLED;
}
function uninstallADBFromUI(doc) {
return new Promise((resolve, reject) => {
adbAddon.on("update", function onUpdate() {
nextTick().then(() => {
const li = doc.querySelector('[status="uninstalled"][addon="adb"]');
if (li) {
adbAddon.off("update", onUpdate);
resolve();
} else {
reject("Can't find item");
}
});
});
const li = doc.querySelector('[status="installed"][addon="adb"]');
li.querySelector(".uninstall-button").click();
});
}
(async function() {
ok(!isAdbAddonInstalled(), "ADB extension not installed");
const win = await openWebIDE({
autoInstallAddons: true,
});
// ADB is installed asynchronously after starting WebIDE.
while (!isAdbAddonInstalled()) {
await adbAddon.once("update");
}
ok(isAdbAddonInstalled(), "ADB extension has been auto-installed");
await nextTick();
const addonDoc = getAddonsDocument(win);
const w = addonDoc.querySelector(".warning");
let display = addonDoc.defaultView.getComputedStyle(w).display;
is(display, "none", "Warning about missing ADB hidden");
await uninstallADBFromUI(addonDoc, "adb");
const docRuntime = getRuntimeDocument(win);
const panelNode = docRuntime.querySelector("#runtime-panel");
items = panelNode.querySelectorAll(".runtime-panel-item-usb");
is(items.length, 0, "No usb runtime listed");
display = addonDoc.defaultView.getComputedStyle(w).display;
is(display, "block", "Warning about missing ADB present");
await closeWebIDE(win);
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -1,199 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const {AppValidator} = require("devtools/client/webide/modules/app-validator");
const nsFile = Components.Constructor("@mozilla.org/file/local;1",
"nsIFile", "initWithPath");
const strings = Services.strings.createBundle("chrome://devtools/locale/app-manager.properties");
let httpserver, fakeOrigin;
window.onload = function() {
SimpleTest.waitForExplicitFinish();
httpserver = new HttpServer();
httpserver.start(-1);
fakeOrigin = "http://localhost:" + httpserver.identity.primaryPort + "/";
next();
};
function createHosted(path, manifestFile = "/manifest.webapp") {
const dirPath = getTestFilePath("validator/" + path);
httpserver.registerDirectory("/", nsFile(dirPath));
return new AppValidator({
type: "hosted",
location: fakeOrigin + manifestFile,
});
}
function createPackaged(path) {
const dirPath = getTestFilePath("validator/" + path);
return new AppValidator({
type: "packaged",
location: dirPath,
});
}
function next() {
const test = tests.shift();
if (test) {
try {
test();
} catch (e) {
console.error("exception", String(e), e, e.stack);
}
} else {
httpserver.stop(function() {
SimpleTest.finish();
});
}
}
const tests = [
// Test a 100% valid example
function() {
const validator = createHosted("valid");
validator.validate().then(() => {
is(validator.errors.length, 0, "valid app got no error");
is(validator.warnings.length, 0, "valid app got no warning");
next();
});
},
function() {
const validator = createPackaged("valid");
validator.validate().then(() => {
is(validator.errors.length, 0, "valid packaged app got no error");
is(validator.warnings.length, 0, "valid packaged app got no warning");
next();
});
},
// Test a launch path that returns a 404
function() {
const validator = createHosted("wrong-launch-path");
validator.validate().then(() => {
is(validator.errors.length, 1, "app with non-existant launch path got an error");
is(validator.errors[0], strings.formatStringFromName("validator.accessFailedLaunchPathBadHttpCode", [fakeOrigin + "wrong-path.html", 404]),
"with the right error message");
is(validator.warnings.length, 0, "but no warning");
next();
});
},
function() {
const validator = createPackaged("wrong-launch-path");
validator.validate().then(() => {
is(validator.errors.length, 1, "app with wrong path got an error");
const file = nsFile(validator.location);
file.append("wrong-path.html");
const url = Services.io.newFileURI(file);
is(validator.errors[0], strings.formatStringFromName("validator.accessFailedLaunchPath", [url.spec]),
"with the expected message");
is(validator.warnings.length, 0, "but no warning");
next();
});
},
// Test when using a non-absolute path for launch_path
function() {
const validator = createHosted("non-absolute-path");
validator.validate().then(() => {
is(validator.errors.length, 1, "app with non absolute path got an error");
is(validator.errors[0], strings.formatStringFromName("validator.nonAbsoluteLaunchPath", ["non-absolute.html"]),
"with expected message");
is(validator.warnings.length, 0, "but no warning");
next();
});
},
function() {
const validator = createPackaged("non-absolute-path");
validator.validate().then(() => {
is(validator.errors.length, 1, "app with non absolute path got an error");
is(validator.errors[0], strings.formatStringFromName("validator.nonAbsoluteLaunchPath", ["non-absolute.html"]),
"with expected message");
is(validator.warnings.length, 0, "but no warning");
next();
});
},
// Test multiple failures (missing name [error] and icon [warning])
function() {
const validator = createHosted("no-name-or-icon");
validator.validate().then(() => {
checkNoNameOrIcon(validator);
});
},
function() {
const validator = createPackaged("no-name-or-icon");
validator.validate().then(() => {
checkNoNameOrIcon(validator);
});
},
// Test a regular URL instead of a direct link to the manifest
function() {
const validator = createHosted("valid", "/");
validator.validate().then(() => {
is(validator.warnings.length, 0, "manifest found got no warning");
is(validator.errors.length, 0, "manifest found got no error");
next();
});
},
// Test finding a manifest at origin's root
function() {
const validator = createHosted("valid", "/unexisting-dir");
validator.validate().then(() => {
is(validator.warnings.length, 0, "manifest found at origin root got no warning");
is(validator.errors.length, 0, "manifest found at origin root got no error");
next();
});
},
// Test priorization of manifest.webapp at provided location instead of a manifest located at origin's root
function() {
const validator = createHosted("valid", "/alsoValid");
validator.validate().then(() => {
is(validator.manifest.name, "valid at subfolder", "manifest at subfolder was used");
next();
});
},
];
function checkNoNameOrIcon(validator) {
is(validator.errors.length, 1, "app with no name has an error");
is(validator.errors[0],
strings.GetStringFromName("validator.missNameManifestProperty"),
"with expected message");
is(validator.warnings.length, 1, "app with no icon has a warning");
is(validator.warnings[0],
strings.GetStringFromName("validator.missIconsManifestProperty"),
"with expected message");
next();
}
</script>
</body>
</html>

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

@ -1,97 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
DebuggerServer.init();
DebuggerServer.registerAllActors();
let win = await openWebIDE();
const docRuntime = getRuntimeDocument(win);
const fakeRuntime = {
type: "USB",
connect: function(connection) {
is(connection, win.AppManager.connection, "connection is valid");
connection.host = null; // force connectPipe
connection.connect();
return Promise.resolve();
},
get id() {
return "fakeRuntime";
},
get name() {
return "fakeRuntime";
},
};
win.AppManager.runtimeList.usb.push(fakeRuntime);
win.AppManager.update("runtime-list");
const panelNode = docRuntime.querySelector("#runtime-panel");
const items = panelNode.querySelectorAll(".runtime-panel-item-usb");
is(items.length, 1, "Found one runtime button");
let connectionsChanged = waitForConnectionChange("opened");
items[0].click();
ok(win.document.querySelector("window").classList.contains("busy"),
"UI is busy");
await win.UI._busyPromise;
await connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 1, "Connected");
connectionsChanged = waitForConnectionChange("closed");
await nextTick();
await closeWebIDE(win);
await connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");
// The DebuggerServer is destroyed when closing WebIDE, so re-initialize it.
DebuggerServer.init();
DebuggerServer.registerAllActors();
connectionsChanged = waitForConnectionChange("opened");
win = await openWebIDE();
win.AppManager.runtimeList.usb.push(fakeRuntime);
win.AppManager.update("runtime-list");
await waitForUpdate(win, "runtime-targets");
await connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 1, "Automatically reconnected");
await win.Cmds.disconnectRuntime();
await closeWebIDE(win);
DebuggerServer.destroy();
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -1,112 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
DebuggerServer.init();
DebuggerServer.registerAllActors();
let win = await openWebIDE();
let docRuntime = getRuntimeDocument(win);
const docProject = getProjectDocument(win);
let panelNode = docRuntime.querySelector("#runtime-panel");
let items = panelNode.querySelectorAll(".runtime-panel-item-other");
is(items.length, 2, "Found 2 runtime buttons");
// Connect to local runtime
let connectionsChanged = waitForConnectionChange("opened");
items[1].click();
await waitForUpdate(win, "runtime-targets");
await connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 1, "Locally connected");
ok(win.AppManager.isMainProcessDebuggable(), "Main process available");
// Select main process
await win.Cmds.showProjectPanel();
await waitForUpdate(win, "runtime-targets");
SimpleTest.executeSoon(() => {
docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
});
await waitForUpdate(win, "project");
const lastProject = Services.prefs.getCharPref("devtools.webide.lastSelectedProject");
is(lastProject, "mainProcess:", "Last project is main process");
connectionsChanged = waitForConnectionChange("closed");
await nextTick();
await closeWebIDE(win);
await connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");
// The DebuggerServer is destroyed when closing WebIDE, so re-initialize it.
DebuggerServer.init();
DebuggerServer.registerAllActors();
connectionsChanged = waitForConnectionChange("opened");
// Re-open, should reselect main process after connection
win = await openWebIDE();
docRuntime = getRuntimeDocument(win);
panelNode = docRuntime.querySelector("#runtime-panel");
items = panelNode.querySelectorAll(".runtime-panel-item-other");
is(items.length, 2, "Found 2 runtime buttons");
// Connect to local runtime
items[1].click();
await waitForUpdate(win, "runtime-targets");
await connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 1, "Locally connected");
ok(win.AppManager.isMainProcessDebuggable(), "Main process available");
is(win.AppManager.selectedProject.type, "mainProcess", "Main process reselected");
// Wait for the toolbox to be fully loaded
await win.UI.toolboxPromise;
// If we happen to pass a project object targeting the same context,
// here, the main process, the `selectedProject` attribute shouldn't be updated
// so that no `project` event would fire.
const oldProject = win.AppManager.selectedProject;
win.AppManager.selectedProject = {
type: "mainProcess",
};
is(win.AppManager.selectedProject, oldProject, "AppManager.selectedProject shouldn't be updated if we selected the same project");
await win.Cmds.disconnectRuntime();
await closeWebIDE(win);
DebuggerServer.destroy();
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -1,56 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
const win = await openWebIDE();
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
await gDevToolsBrowser.isWebIDEInitialized.promise;
ok(true, "WebIDE was initialized");
ok(win, "Found a window");
ok(win.AppManager, "App Manager accessible");
const appmgr = win.AppManager;
ok(appmgr.connection, "App Manager connection ready");
ok(appmgr.runtimeList, "Runtime list ready");
// test error reporting
const nbox = win.UI.notificationBox;
let notification = nbox.getNotificationWithValue("webide:errornotification");
ok(!notification, "No notification yet");
const deferred = new Promise((resolve, reject) => {
nextTick().then(() => {
reject("BOOM!");
});
});
try {
await win.UI.busyUntil(deferred, "xx");
} catch (e) { /* This *will* fail */ }
notification = nbox.getNotificationWithValue("webide:errornotification");
ok(notification, "Error has been reported");
await closeWebIDE(win);
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -1,58 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
info("Open WebIDE");
const win = await openWebIDE();
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
await gDevToolsBrowser.isWebIDEInitialized.promise;
ok(true, "WebIDE was initialized");
info("Check if the deprecation message is displayed");
const nbox = win.UI.deprecationBox;
const deprecationMessage = nbox.getNotificationWithValue("webide:deprecationnotification");
ok(!!deprecationMessage, "The deprecation message is displayed");
info("Check if a button is displayed in the notification box");
// Note: `notification-button` is a hardcoded className added by the XUL
// notificationbox widget and we cannot set custom classnames.
const button = nbox.stack.querySelector(".notification-button");
ok(!!button, "The button to open about:debugging is displayed");
button.click();
info("Wait until the about:debugging tab is selected in the main window");
const mainWindow = Services.wm.getMostRecentWindow("navigator:browser");
await waitUntil(() => {
const contentWindow = mainWindow.gBrowser.selectedBrowser.contentWindow;
return contentWindow.location.href.startsWith("about:debugging");
});
info("Remove the about:debugging tab");
await removeTab(mainWindow.gBrowser.selectedTab, mainWindow);
await closeWebIDE(win);
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -1,85 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="device_front_shared.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
DebuggerServer.init();
DebuggerServer.registerAllActors();
const win = await openWebIDE();
const prefIframe = win.document.querySelector("#deck-panel-devicepreferences");
const docRuntime = getRuntimeDocument(win);
win.AppManager.update("runtime-list");
await connectToLocalRuntime(win);
const prefs = docRuntime.querySelector("#runtime-preferences");
ok(!prefs.hasAttribute("disabled"), "device prefs cmd enabled");
const deck = win.document.querySelector("#deck");
win.Cmds.showDevicePrefs();
is(deck.selectedPanel, prefIframe, "device preferences iframe selected");
await nextTick();
await lazyIframeIsLoaded(prefIframe);
await prefIframe.contentWindow.getAllPrefs;
setDocument(prefIframe);
const fields = doc.querySelectorAll(".editable");
addNewField();
const preference = "accessibility.accesskeycausesactivation";
fieldChange(fields, preference);
addNewFieldWithEnter();
editExistingField();
addNewFieldInteger();
await editFieldInteger();
await resetExistingField("accessibility.accesskeycausesactivation");
addNewFieldBoolean();
searchFields(deck, "debugger");
DebuggerServer.destroy();
await closeWebIDE(win);
SimpleTest.finish();
})().catch(e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
};
</script>
</body>
</html>

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

@ -1,79 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
DebuggerServer.init();
DebuggerServer.registerAllActors();
const win = await openWebIDE();
const detailsIframe = win.document.querySelector("#deck-panel-runtimedetails");
await connectToLocalRuntime(win);
const details = win.document.querySelector("#cmd_showRuntimeDetails");
ok(!details.hasAttribute("disabled"), "info cmd enabled");
const deck = win.document.querySelector("#deck");
win.Cmds.showRuntimeDetails();
is(deck.selectedPanel, detailsIframe, "info iframe selected");
await nextTick();
await lazyIframeIsLoaded(detailsIframe);
await detailsIframe.contentWindow.getDescriptionPromise;
// device info and permissions content is checked in other tests
// We just test one value to make sure we get something
const doc = detailsIframe.contentWindow.document;
const trs = doc.querySelectorAll("tr");
let found = false;
for (const tr of trs) {
const [name, val] = tr.querySelectorAll("td");
if (name.textContent == "appid") {
found = true;
is(val.textContent, Services.appinfo.ID, "appid has the right value");
break;
}
}
ok(found, "Found appid line");
doc.querySelector("#close").click();
ok(!deck.selectedPanel, "No panel selected");
DebuggerServer.destroy();
await closeWebIDE(win);
SimpleTest.finish();
})().catch(e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
};
</script>
</body>
</html>

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

@ -1,77 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
const win = await openWebIDE();
const docProject = getProjectDocument(win);
const winProject = getProjectWindow(win);
const packagedAppLocation = getTestFilePath("app");
const hostedAppManifest = TEST_BASE + "hosted_app.manifest";
await win.AppProjects.load();
is(win.AppProjects.projects.length, 0, "IDB is empty");
let onValidated = waitForUpdate(win, "project-validated");
let onDetails = waitForUpdate(win, "details");
await winProject.projectList.importPackagedApp(packagedAppLocation);
await onValidated;
await onDetails;
await winProject.projectList.importHostedApp(hostedAppManifest);
await waitForUpdate(win, "project-validated");
await nextTick();
onValidated = waitForUpdate(win, "project-validated");
onDetails = waitForUpdate(win, "details");
await winProject.projectList.importPackagedApp(packagedAppLocation);
await onValidated;
await onDetails;
let project = win.AppManager.selectedProject;
is(project.location, packagedAppLocation, "Correctly reselected existing packaged app.");
await nextTick();
info("to call importHostedApp(" + hostedAppManifest + ") again");
await winProject.projectList.importHostedApp(hostedAppManifest);
await waitForUpdate(win, "project-validated");
project = win.AppManager.selectedProject;
is(project.location, hostedAppManifest, "Correctly reselected existing hosted app.");
await nextTick();
const panelNode = docProject.querySelector("#project-panel");
const items = panelNode.querySelectorAll(".panel-item");
// 3 controls, + 2 projects
is(items.length, 5, "5 projects in panel");
is(items[3].querySelector("span").textContent, "A name (in app directory)", "Panel text is correct");
is(items[4].querySelector("span").textContent, "hosted manifest name property", "Panel text is correct");
await closeWebIDE(win);
await removeAllProjects();
SimpleTest.finish();
})().catch(e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
};
</script>
</body>
</html>

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

@ -1,70 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
function connectToLocal(win, docRuntime) {
return new Promise(resolve => {
win.AppManager.connection.once(
win.Connection.Events.CONNECTED,
resolve);
docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
});
}
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
const win = await openWebIDE();
const docProject = getProjectDocument(win);
const docRuntime = getRuntimeDocument(win);
win.AppManager.update("runtime-list");
const onGlobalActors = waitForUpdate(win, "runtime-global-actors");
const onRuntimeTargets = waitForUpdate(win, "runtime-targets");
connectToLocal(win, docRuntime);
await onGlobalActors;
await onRuntimeTargets;
// Select main process
SimpleTest.executeSoon(() => {
docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
});
await waitForUpdate(win, "project");
ok(win.UI.toolboxPromise, "Toolbox promise exists");
await win.UI.toolboxPromise;
const nbox = win.document.getElementById("containerbox");
ok(!nbox.hasAttribute("toolboxfullscreen"), "Toolbox is not fullscreen");
win.Cmds.showRuntimeDetails();
ok(!nbox.hasAttribute("toolboxfullscreen"), "Toolbox is not fullscreen");
await win.Cmds.disconnectRuntime();
await closeWebIDE(win);
DebuggerServer.destroy();
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -1,82 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
const win = await openWebIDE();
const docProject = getProjectDocument(win);
const winProject = getProjectWindow(win);
const packagedAppLocation = getTestFilePath("app");
await win.AppProjects.load();
is(win.AppProjects.projects.length, 0, "IDB is empty");
info("to call importPackagedApp(" + packagedAppLocation + ")");
ok(!win.UI._busyPromise, "UI is not busy");
const onValidated = waitForUpdate(win, "project-validated");
const onDetails = waitForUpdate(win, "details");
await winProject.projectList.importPackagedApp(packagedAppLocation);
await onValidated;
await onDetails;
let project = win.AppManager.selectedProject;
is(project.location, packagedAppLocation, "Location is valid");
is(project.name, "A name (in app directory)", "name field has been updated");
is(project.manifest.launch_path, "/index.html", "manifest found. launch_path valid.");
is(project.manifest.description, "desc", "manifest found. description valid");
await nextTick();
let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
await winProject.projectList.importHostedApp(hostedAppManifest);
await waitForUpdate(win, "project-validated");
project = win.AppManager.selectedProject;
is(project.location, hostedAppManifest, "Location is valid");
is(project.name, "hosted manifest name property", "name field has been updated");
await nextTick();
hostedAppManifest = TEST_BASE + "/app";
await winProject.projectList.importHostedApp(hostedAppManifest);
await waitForUpdate(win, "project-validated");
project = win.AppManager.selectedProject;
ok(project.location.endsWith("manifest.webapp"), "The manifest was found and the project was updated");
const panelNode = docProject.querySelector("#project-panel");
const items = panelNode.querySelectorAll(".panel-item");
// 4 controls, + 2 projects
is(items.length, 6, "6 projects in panel");
is(items[3].querySelector("span").textContent, "A name (in app directory)", "Panel text is correct");
is(items[4].querySelector("span").textContent, "hosted manifest name property", "Panel text is correct");
await closeWebIDE(win);
await removeAllProjects();
SimpleTest.finish();
})().catch(e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
};
</script>
</body>
</html>

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

@ -1,97 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
const {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm");
(async function() {
const win = await openWebIDE();
const winProject = getProjectWindow(win);
const AppManager = win.AppManager;
function isProjectMarkedAsValid() {
const details = win.frames[1];
return !details.document.body.classList.contains("error");
}
const packagedAppLocation = getTestFilePath("app");
const onValidated = waitForUpdate(win, "project-validated");
const onDetails = waitForUpdate(win, "details");
await winProject.projectList.importPackagedApp(packagedAppLocation);
await onValidated;
await onDetails;
const project = win.AppManager.selectedProject;
ok("name" in project.manifest, "manifest includes name");
is(project.name, project.manifest.name, "Display name uses manifest name");
ok(isProjectMarkedAsValid(), "project is marked as valid");
// Change the name
const originalName = project.manifest.name;
project.manifest.name = "xxx";
// Write to disk
await AppManager.writeManifest(project);
// Read file
const manifestPath = OS.Path.join(packagedAppLocation, "manifest.webapp");
let data = await OS.File.read(manifestPath);
data = new TextDecoder().decode(data);
const json = JSON.parse(data);
is(json.name, "xxx", "manifest written on disc");
// Make the manifest invalid on disk
delete json.name;
const Encoder = new TextEncoder();
data = Encoder.encode(JSON.stringify(json));
await OS.File.writeAtomic(manifestPath, data, {tmpPath: manifestPath + ".tmp"});
// Trigger validation
await AppManager.validateAndUpdateProject(AppManager.selectedProject);
await nextTick();
ok(!("name" in project.manifest), "manifest has been updated");
is(project.name, "--", "Placeholder is used for display name");
ok(!isProjectMarkedAsValid(), "project is marked as invalid");
// Make the manifest valid on disk
project.manifest.name = originalName;
await AppManager.writeManifest(project);
// Trigger validation
await AppManager.validateAndUpdateProject(AppManager.selectedProject);
await nextTick();
ok("name" in project.manifest, "manifest includes name");
is(project.name, originalName, "Display name uses original manifest name");
ok(isProjectMarkedAsValid(), "project is marked as valid");
await closeWebIDE(win);
await removeAllProjects();
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -1,46 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
const win = await openWebIDE();
const winProject = getProjectWindow(win);
let tmpDir = FileUtils.getDir("TmpD", []);
await winProject.projectList.newApp({
index: 0,
name: "webideTmpApp",
folder: tmpDir,
});
const project = win.AppManager.selectedProject;
tmpDir = FileUtils.getDir("TmpD", ["webidetmpapp"]);
ok(tmpDir.isDirectory(), "Directory created");
is(project.location, tmpDir.path, "Location is valid (and lowercase)");
is(project.name, "webideTmpApp", "name field has been updated");
// Clean up
tmpDir.remove(true);
await closeWebIDE(win);
await removeAllProjects();
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -1,60 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = async function() {
SimpleTest.waitForExplicitFinish();
try {
Services.prefs.setBoolPref("devtools.performance.new-panel-enabled", true);
DebuggerServer.init();
DebuggerServer.registerAllActors();
const win = await openWebIDE();
const perfIframe = win.document.querySelector("#deck-panel-performance");
const docRuntime = getRuntimeDocument(win);
win.AppManager.update("runtime-list");
await connectToLocalRuntime(win);
const prefs = docRuntime.querySelector("#runtime-performance");
ok(!prefs.hidden, "performance button is displayed");
ok(!prefs.hasAttribute("disabled"), "performance cmd enabled");
const deck = win.document.querySelector("#deck");
win.Cmds.showPerformancePanel();
is(deck.selectedPanel, perfIframe, "performance iframe selected");
await nextTick();
await lazyIframeIsLoaded(perfIframe);
await SimpleTest.promiseWaitForCondition(
() => perfIframe.contentDocument.querySelector(".perf"),
"Waited for the react rendering that never came."
);
ok(true, "The perf interface was correctly rendered.");
await closeWebIDE(win);
} catch (e) {
ok(false, "Exception: " + e + "\nStack: " + e.stack);
} finally {
Services.prefs.clearUserPref("devtools.performance.new-panel-enabled");
SimpleTest.finish();
}
};
</script>
</body>
</html>

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

@ -1,207 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
let win;
SimpleTest.registerCleanupFunction(() => {
(async function() {
if (win) {
await closeWebIDE(win);
}
DebuggerServer.destroy();
await removeAllProjects();
})();
});
(async function() {
function isPlayActive() {
return !win.document.querySelector("#cmd_play").hasAttribute("disabled");
}
function isStopActive() {
return !win.document.querySelector("#cmd_stop").hasAttribute("disabled");
}
DebuggerServer.init();
DebuggerServer.registerAllActors();
win = await openWebIDE();
const docRuntime = getRuntimeDocument(win);
const docProject = getProjectDocument(win);
const winProject = getProjectWindow(win);
const packagedAppLocation = getTestFilePath("app");
const onValidated = waitForUpdate(win, "project-validated");
const onDetails = waitForUpdate(win, "details");
await winProject.projectList.importPackagedApp(packagedAppLocation);
await onValidated;
await onDetails;
win.AppManager.runtimeList.usb.push({
connect: function(connection) {
is(connection, win.AppManager.connection, "connection is valid");
connection.host = null; // force connectPipe
connection.connect();
return Promise.resolve();
},
get name() {
return "fakeRuntime";
},
});
win.AppManager.runtimeList.usb.push({
connect: function(connection) {
return new Promise(() => {});
},
get name() {
return "infiniteRuntime";
},
});
win.AppManager.runtimeList.usb.push({
connect: function(connection) {
return new Promise(() => {});
},
prolongedConnection: true,
get name() {
return "prolongedRuntime";
},
});
win.AppManager.update("runtime-list");
const panelNode = docRuntime.querySelector("#runtime-panel");
const items = panelNode.querySelectorAll(".runtime-panel-item-usb");
is(items.length, 3, "Found 3 runtime buttons");
let onGlobalActors = waitForUpdate(win, "runtime-global-actors");
let connectionsChanged = waitForConnectionChange("opened");
items[0].click();
ok(win.document.querySelector("window").classList.contains("busy"),
"UI is busy");
await win.UI._busyPromise;
await connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 1, "Connected");
await onGlobalActors;
// Play button always disabled now, webapps actor removed
ok(!isPlayActive(), "play button is disabled");
ok(!isStopActive(), "stop button is disabled");
const oldProject = win.AppManager.selectedProject;
win.AppManager.selectedProject = null;
await nextTick();
ok(!isPlayActive(), "play button is disabled");
ok(!isStopActive(), "stop button is disabled");
win.AppManager._selectedProject = oldProject;
win.UI.updateCommands();
await nextTick();
ok(!isPlayActive(), "play button is enabled");
ok(!isStopActive(), "stop button is disabled");
connectionsChanged = waitForConnectionChange("closed");
await win.Cmds.disconnectRuntime();
await connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");
ok(win.AppManager.selectedProject, "A project is still selected");
ok(!isPlayActive(), "play button is disabled");
ok(!isStopActive(), "stop button is disabled");
connectionsChanged = waitForConnectionChange("opened");
onGlobalActors = waitForUpdate(win, "runtime-global-actors");
const onRuntimeTargets = waitForUpdate(win, "runtime-targets");
docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
await connectionsChanged;
await onGlobalActors;
await onRuntimeTargets;
is(Object.keys(DebuggerServer._connections).length, 1, "Locally connected");
ok(win.AppManager.isMainProcessDebuggable(), "Main process available");
// Select main process
SimpleTest.executeSoon(() => {
docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
});
await waitForUpdate(win, "project");
// Toolbox opens automatically for main process / runtime apps
ok(win.UI.toolboxPromise, "Toolbox promise exists");
await win.UI.toolboxPromise;
await win.Cmds.disconnectRuntime();
Services.prefs.setIntPref("devtools.webide.busyTimeout", 100);
// Click the infinite runtime
items[1].click();
ok(win.document.querySelector("window").classList.contains("busy"),
"UI is busy");
// Wait for error message since connection never completes
await new Promise(resolve => {
win.UI.reportError = errorName => {
if (errorName === "error_operationTimeout") {
resolve();
}
};
});
// Click the prolonged runtime
items[2].click();
ok(win.document.querySelector("window").classList.contains("busy"),
"UI is busy");
// Check for unexpected error message since this is prolonged
const noErrorDeferred = new Promise((resolve, reject) => {
win.UI.reportError = errorName => {
if (errorName === "error_operationTimeout") {
reject();
}
};
setTimeout(() => {
resolve();
}, 1000);
});
await noErrorDeferred;
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -1,95 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
let win;
SimpleTest.registerCleanupFunction(() => {
(async function() {
if (win) {
await closeWebIDE(win);
}
DebuggerServer.destroy();
await removeAllProjects();
})();
});
(async function() {
DebuggerServer.init();
DebuggerServer.registerAllActors();
win = await openWebIDE();
const docRuntime = getRuntimeDocument(win);
const docProject = getProjectDocument(win);
win.AppManager.update("runtime-list");
const deferred = new Promise(resolve => {
win.AppManager.connection.once(
win.Connection.Events.CONNECTED,
resolve);
});
docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
ok(win.document.querySelector("window").classList.contains("busy"),
"UI is busy");
await win.UI._busyPromise;
await deferred;
is(Object.keys(DebuggerServer._connections).length, 1, "Connected");
await waitForUpdate(win, "runtime-global-actors");
ok(win.AppManager.isMainProcessDebuggable(), "Main process available");
// Select main process
SimpleTest.executeSoon(() => {
docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
});
await waitForUpdate(win, "project");
// Toolbox opens automatically for main process / runtime apps
ok(win.UI.toolboxPromise, "Toolbox promise exists");
const toolbox = await win.UI.toolboxPromise;
await toolbox.destroy();
ok(!win.UI.toolboxPromise, "Toolbox promise should be unset once toolbox.destroy()'s promise resolves");
// Reopen the toolbox right after to check races and also
// opening a toolbox more than just once against the same target
await win.Cmds.toggleToolbox();
ok(win.UI.toolboxPromise, "Toolbox promise exists");
await win.UI.destroyToolbox();
ok(!win.UI.toolboxPromise, "Toolbox promise is also nullified the second times");
await win.Cmds.disconnectRuntime();
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -1,71 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
(async function() {
let win = await openWebIDE();
let viewer = win.docShell.contentViewer;
win.Cmds.zoomOut();
win.Cmds.zoomOut();
win.Cmds.zoomOut();
win.Cmds.zoomOut();
win.Cmds.zoomOut();
win.Cmds.zoomOut();
win.Cmds.zoomOut();
let roundZoom = Math.round(10 * viewer.fullZoom) / 10;
is(roundZoom, 0.6, "Reach min zoom");
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
roundZoom = Math.round(10 * viewer.fullZoom) / 10;
is(roundZoom, 1.4, "Reach max zoom");
await closeWebIDE(win);
win = await openWebIDE();
viewer = win.docShell.contentViewer;
roundZoom = Math.round(10 * viewer.fullZoom) / 10;
is(roundZoom, 1.4, "Zoom restored");
win.Cmds.resetZoom();
is(viewer.fullZoom, 1, "Zoom reset");
await closeWebIDE(win);
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

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

@ -1,3 +0,0 @@
{
"launch_path": "/home.html"
}

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

@ -1,7 +0,0 @@
{
"name": "non-absolute path",
"icons": {
"128": "/icon.png"
},
"launch_path": "non-absolute.html"
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше