function initNetMonitor(aUrl, aWindow, aEnableCache) { info("Initializing a network monitor pane."); return Task.spawn(function* () { let tab = yield addTab(aUrl); info("Net tab added successfully: " + aUrl); let target = TargetFactory.forTab(tab); yield target.makeRemote(); info("Target remoted."); if (!aEnableCache) { yield toggleCache(target, true); info("Cache disabled when the current and all future toolboxes are open."); // Remove any requests generated by the reload while toggling the cache to // avoid interfering with the test. isnot([...target.activeConsole.getNetworkEvents()].length, 0, "Request to reconfigure the tab was recorded."); target.activeConsole.clearNetworkRequests(); } let toolbox = yield gDevTools.showToolbox(target, "netmonitor"); info("Netork monitor pane shown successfully."); let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject; let monitor = toolbox.getCurrentPanel(); return [tab, debuggee, monitor]; }); }
disconnectRuntime: function () { let disconnecting = Task.spawn(function* () { yield UI.destroyToolbox(); yield AppManager.disconnectRuntime(); }); return UI.busyUntil(disconnecting, "disconnecting from runtime"); },
open: function () { this._validateOptions(); DebuggerServer._addListener(this); let flags = Ci.nsIServerSocket.KeepWhenOffline; // A preference setting can force binding on the loopback interface. if (Services.prefs.getBoolPref("devtools.debugger.force-local")) { flags |= Ci.nsIServerSocket.LoopbackOnly; } let self = this; return Task.spawn(function* () { let backlog = 4; self._socket = self._createSocketInstance(); if (self.isPortBased) { let port = Number(self.portOrPath); self._socket.initSpecialConnection(port, flags, backlog); } else { let file = nsFile(self.portOrPath); if (file.exists()) { file.remove(false); } self._socket.initWithFilename(file, parseInt("666", 8), backlog); } yield self._setAdditionalSocketOptions(); self._socket.asyncListen(self); dumpn("Socket listening on: " + (self.port || self.portOrPath)); }).then(() => { this._advertise(); }).catch(e => { dumpn("Could not start debugging listener on '" + this.portOrPath + "': " + e); this.close(); }); },
_getImported: function (doc, styleSheet) { return Task.spawn(function* () { let rules = yield styleSheet.getCSSRules(); let imported = []; for (let i = 0; i < rules.length; i++) { let rule = rules[i]; if (rule.type == Ci.nsIDOMCSSRule.IMPORT_RULE) { // With the Gecko style system, the associated styleSheet may be null // if it has already been seen because an import cycle for the same // URL. With Stylo, the styleSheet will exist (which is correct per // the latest CSSOM spec), so we also need to check ancestors for the // same URL to avoid cycles. let sheet = rule.styleSheet; if (!sheet || this._haveAncestorWithSameURL(sheet) || !this._shouldListSheet(doc, sheet)) { continue; } let actor = this.parentActor.createStyleSheetActor(rule.styleSheet); imported.push(actor); // recurse imports in this stylesheet as well let children = yield this._getImported(doc, actor); imported = imported.concat(children); } else if (rule.type != Ci.nsIDOMCSSRule.CHARSET_RULE) { // @import rules must precede all others except @charset break; } } return imported; }.bind(this)); },
_addStyleSheets: function (win) { return Task.spawn(function* () { let doc = win.document; // readyState can be uninitialized if an iframe has just been created but // it has not started to load yet. if (doc.readyState === "loading" || doc.readyState === "uninitialized") { // Wait for the document to load first. yield listenOnce(win, "DOMContentLoaded", true); // Make sure we have the actual document for this window. If the // readyState was initially uninitialized, the initial dummy document // was replaced with the actual document (bug 1171919). doc = win.document; } let isChrome = Services.scriptSecurityManager.isSystemPrincipal(doc.nodePrincipal); let styleSheets = isChrome ? DOMUtils.getAllStyleSheets(doc) : doc.styleSheets; let actors = []; for (let i = 0; i < styleSheets.length; i++) { let sheet = styleSheets[i]; if (!this._shouldListSheet(doc, sheet)) { continue; } let actor = this.parentActor.createStyleSheetActor(sheet); actors.push(actor); // Get all sheets, including imported ones let imports = yield this._getImported(doc, actor); actors = actors.concat(imports); } return actors; }.bind(this)); },
function test() { const options = { tabContent: 'test if view menu items "Larger Font" and "Smaller Font" are enabled/disabled.' }; openTabAndScratchpad(options) .then(Task.async(runTests)) .then(finish, console.error); }
let requireInspector = generator => { return Task.async(function* (...args) { if (!isInspectorInitialized) { yield toolbox.initInspector(); isInspectorInitialized = true; } return yield generator.apply(null, args); }); };
function removeAllProjects() { return Task.spawn(function* () { yield AppProjects.load(); // use a new array so we're not iterating over the same // underlying array that's being modified by AppProjects let projects = AppProjects.projects.map(p => p.location); for (let i = 0; i < projects.length; i++) { yield AppProjects.remove(projects[i]); } }); }
/** * Wait for a specific action type to be dispatch. * If an async action, will wait for it to be done. * * @memberof mochitest/waits * @param {Object} dbg * @param {String} type * @param {Number} eventRepeat * @return {Promise} * @static */ function waitForDispatch(dbg, type, eventRepeat = 1) { let count = 0; return Task.spawn(function*() { info(`Waiting for ${type} to dispatch ${eventRepeat} time(s)`); while (count < eventRepeat) { yield _afterDispatchDone(dbg.store, type); count++; info(`${type} dispatched ${count} time(s)`); } }); }
getTarget: function () { if (this.selectedProject.type == "mainProcess") { // Fx >=39 exposes a ChromeActor to debug the main process if (this.connection.client.mainRoot.traits.allowChromeProcess) { return this.connection.client.getProcess() .then(aResponse => { return TargetFactory.forRemoteTab({ form: aResponse.form, client: this.connection.client, chrome: true }); }); } else { // Fx <39 exposes tab actors on the root actor return TargetFactory.forRemoteTab({ form: this._listTabsResponse, client: this.connection.client, chrome: true, isTabActor: false }); } } if (this.selectedProject.type == "tab") { return this.tabStore.getTargetForTab(); } let app = this._getProjectFront(this.selectedProject); if (!app) { return promise.reject("Can't find app front for selected project"); } return Task.spawn(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 tab actors required to create its target. for (let i = 0; i < 10; i++) { try { return yield app.getTarget(); } catch (e) {} let deferred = promise.defer(); setTimeout(deferred.resolve, 500); yield deferred.promise; } AppManager.reportError("error_cantConnectToApp", app.manifest.manifestURL); throw new Error("can't connect to app"); }); },
this.actions.togglePrettyPrint(source); }, /** * Toggle the black boxed state of the selected source. */ toggleBlackBoxing: Task.async(function* () { const source = getSelectedSource(this.getState()); const shouldBlackBox = !source.isBlackBoxed; // Be optimistic that the (un-)black boxing will succeed, so // enable/disable the pretty print button and check/uncheck the // black box button immediately. if (shouldBlackBox) { this._prettyPrintButton.setAttribute("disabled", true); this._blackBoxButton.setAttribute("checked", true); } else { this._prettyPrintButton.removeAttribute("disabled"); this._blackBoxButton.removeAttribute("checked"); } this.actions.blackbox(source, shouldBlackBox); }), renderBlackBoxed: function (source) { const sourceItem = this.getItemByValue(source.actor); sourceItem.prebuiltNode.classList.toggle( "black-boxed", source.isBlackBoxed );
Services.prefs.clearUserPref("devtools.webide.busyTimeout"); Services.prefs.clearUserPref("devtools.webide.lastSelectedProject"); Services.prefs.clearUserPref("devtools.webide.lastConnectedRuntime"); }); var openWebIDE = Task.async(function* (autoInstallAddons) { info("opening WebIDE"); Services.prefs.setBoolPref("devtools.webide.autoinstallADBHelper", !!autoInstallAddons); Services.prefs.setBoolPref("devtools.webide.autoinstallFxdtAdapters", !!autoInstallAddons); let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher); let win = ww.openWindow(null, "chrome://webide/content/", "webide", "chrome,centerscreen,resizable", null); yield new Promise(resolve => { win.addEventListener("load", function onLoad() { win.removeEventListener("load", onLoad); SimpleTest.requestCompleteLog(); SimpleTest.executeSoon(resolve); }); }); info("WebIDE open"); return win; }); function closeWebIDE(win) { info("Closing WebIDE"); let deferred = promise.defer();
/** * Executed when the AnimationPlayerActor emits a "changed" event. Used to * update the local knowledge of the state. */ onChanged: preEvent("changed", function (partialState) { let {state} = this.reconstructState(partialState); this.state = state; }), /** * Refresh the current state of this animation on the client from information * found on the server. Doesn't return anything, just stores the new state. */ refreshState: Task.async(function* () { let data = yield this.getCurrentState(); if (this.currentStateHasChanged) { this.state = data; } }), /** * getCurrentState interceptor re-constructs incomplete states since the actor * only sends the values that have changed. */ getCurrentState: custom(function () { this.currentStateHasChanged = false; return this._getCurrentState().then(partialData => { let {state, hasChanged} = this.reconstructState(partialData); this.currentStateHasChanged = hasChanged; return state; }); }, {
let deferred = defer(); if ("@mozilla.org/settingsService;1" in Cc) { let settingsService; // settingsService fails in b2g child processes // TODO bug 1205797, make this work in child processes. try { settingsService = Cc["@mozilla.org/settingsService;1"] .getService(Ci.nsISettingsService); } catch (e) { return promise.reject(e); } settingsService.createLock().get(name, { handle: (_, value) => deferred.resolve(value), handleError: (error) => deferred.reject(error), }); } else { deferred.reject(new Error("No settings service")); } return deferred.promise; } exports.getSystemInfo = Task.async(getSystemInfo); exports.getAppIniString = getAppIniString; exports.getSetting = getSetting; exports.getScreenDimensions = getScreenDimensions; exports.getOSCPU = getOSCPU; exports.constants = AppConstants;
iframe.removeAttribute("src"); }, /** * Remove an existing tab. * @param {String} tabId The ID of the tab that was used to register it, or * the tab id attribute value if the tab existed before the sidebar * got created. * @param {String} tabPanelId Optional. If provided, this ID will be used * instead of the tabId to retrieve and remove the corresponding <tabpanel> */ removeTab: Task.async(function* (tabId, tabPanelId) { this._tabbar.removeTab(tabId); let win = this.getWindowForTab(tabId); if (win && ("destroy" in win)) { yield win.destroy(); } this.emit("tab-unregistered", tabId); }), /** * Show or hide a specific tab. * @param {Boolean} isVisible True to show the tab/tabpanel, False to hide it. * @param {String} id The ID of the tab to be hidden. */ toggleTab: function (isVisible, id) { this._tabbar.toggleTab(id, isVisible); }, /**
if (updateButton) { let nodeGeometry = this.doc.getElementById("old-layout-geometry-editor"); nodeGeometry.removeAttribute("checked"); } }, /** * Update the visibility and the state of the geometry editor button, * based on the selected node. */ updateGeometryButton: Task.async(function* () { let node = this.inspector.selection.nodeFront; let isEditable = false; if (node) { isEditable = yield this.inspector.pageStyle.isPositionEditable(node); } let nodeGeometry = this.doc.getElementById("old-layout-geometry-editor"); nodeGeometry.style.visibility = isEditable ? "visible" : "hidden"; }), manageOverflowingText: function (span) { let classList = span.parentNode.classList; if (classList.contains("old-boxmodel-left") || classList.contains("old-boxmodel-right")) { let force = span.textContent.length > LONG_TEXT_ROTATE_LIMIT; classList.toggle("old-boxmodel-rotate", force); } }
} }), /** * Forces the reflow and waits for the next repaint. */ reflow: protocol.method(function () { let deferred = promise.defer(); this.content.document.documentElement.offsetWidth; this.content.requestAnimationFrame(deferred.resolve); return deferred.promise; }), getNodeRect: protocol.method(Task.async(function* (selector) { let node = this._querySelector(selector); return getRect(this.content, node, this.content); }), { request: { selector: Arg(0, "string") }, response: { value: RetVal("json") } }), /** * Get information about a DOM element, identified by a selector. * @param {String} selector The CSS selector to get the node (can be an array * of selectors to get elements in an iframe). * @return {Object} data Null if selector didn't match any node, otherwise: * - {String} tagName.
validateAndUpdateProject: function (project) { if (!project) { return promise.reject(); } return Task.spawn(function* () { let packageDir = yield ProjectBuilding.getPackageDir(project); let validation = new AppValidator({ type: project.type, // Build process may place the manifest in a non-root directory location: packageDir }); yield validation.validate(); if (validation.manifest) { let manifest = validation.manifest; let iconPath; if (manifest.icons) { let 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") { let manifestURL = Services.io.newURI(project.location); let origin = Services.io.newURI(manifestURL.prePath); project.icon = Services.io.newURI(iconPath, null, origin).spec; } else if (project.type == "packaged") { let projectFolder = FileUtils.File(packageDir); let 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) { yield AppProjects.updateLocation(project, validation.manifestURL); } else if (AppProjects.get(project.location)) { yield AppProjects.update(project); } if (AppManager.selectedProject === project) { AppManager.update("project-validated"); } }); },
/** * @see MemoryFront.prototype.transferHeapSnapshot */ transferHeapSnapshot: method(Task.async(function* (snapshotId) { const snapshotFilePath = HeapSnapshotFileUtils.getHeapSnapshotTempFilePath(snapshotId); if (!snapshotFilePath) { throw new Error(`No heap snapshot with id: ${snapshotId}`); } const streamPromise = DevToolsUtils.openFileStream(snapshotFilePath); const { size } = yield OS.File.stat(snapshotFilePath); const bulkPromise = this.conn.startBulkSend({ actor: this.actorID, type: "heap-snapshot", length: size }); const [bulk, stream] = yield Promise.all([bulkPromise, streamPromise]); try { yield bulk.copyFrom(stream); } finally { stream.close(); } }), { request: { snapshotId: Arg(0, "string") } }),
* HighlighterLock is a helper used to lock the highlighter on DOM nodes in the * page. * It instantiates a new highlighter that is then shared amongst all instances * of DomNodePreview. This is useful because that means showing the highlighter * on one node will unhighlight the previously highlighted one, but will not * interfere with the default inspector highlighter. */ var HighlighterLock = { highlighter: null, isShown: false, highlight: Task.async(function* (animationTargetNode) { if (!this.highlighter) { let util = animationTargetNode.inspector.toolbox.highlighterUtils; this.highlighter = yield util.getHighlighterByType("BoxModelHighlighter"); } yield this.highlighter.show(animationTargetNode.nodeFront); this.isShown = true; this.emit("highlighted", animationTargetNode); }), unhighlight: Task.async(function* () { if (!this.highlighter || !this.isShown) { return; } yield this.highlighter.hide(); this.isShown = false; this.emit("unhighlighted"); }) };
* Initializes the grid inspector by fetching the LayoutFront from the walker, loading * the highlighter settings and initalizing the SwatchColorPicker instance. */ init: Task.async(function* () { if (!this.inspector) { return; } this.layoutInspector = yield this.inspector.walker.getLayoutInspector(); this.loadHighlighterSettings(); // Create a shared SwatchColorPicker instance to be reused by all GridItem components. this.swatchColorPickerTooltip = new SwatchColorPickerTooltip( this.inspector.toolbox.doc, this.inspector, { supportsCssColor4ColorFunction: () => false } ); this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange); this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange); this.inspector.on("markupmutation", this.onMarkupMutation); this.inspector.sidebar.on("select", this.onSidebarSelect); this.onSidebarSelect(); }), /** * Destruction function called when the inspector is destroyed. Removes event listeners
update: function () { let lastRequest = Task.spawn((function* () { if (!this.isViewVisibleAndNodeValid()) { this.wrapper.hidden = true; this.inspector.emit("boxmodel-view-updated"); return null; } let node = this.inspector.selection.nodeFront; let layout = yield this.inspector.pageStyle.getLayout(node, { autoMargins: this.isActive }); let styleEntries = yield this.inspector.pageStyle.getApplied(node, {}); yield this.updateGeometryButton(); // If a subsequent request has been made, wait for that one instead. if (this._lastRequest != lastRequest) { return this._lastRequest; } this._lastRequest = null; let width = layout.width; let height = layout.height; let newLabel = SHARED_L10N.getFormatStr("dimensions", width, height); if (this.sizeHeadingLabel.textContent != newLabel) { this.sizeHeadingLabel.textContent = newLabel; } for (let i in this.map) { let property = this.map[i].property; if (!(property in layout)) { // Depending on the actor version, some properties // might be missing. continue; } let parsedValue = parseFloat(layout[property]); if (Number.isNaN(parsedValue)) { // Not a number. We use the raw string. // Useful for "position" for example. this.map[i].value = layout[property]; } else { this.map[i].value = parsedValue; } } let margins = layout.autoMargins; if ("top" in margins) { this.map.marginTop.value = "auto"; } if ("right" in margins) { this.map.marginRight.value = "auto"; } if ("bottom" in margins) { this.map.marginBottom.value = "auto"; } if ("left" in margins) { this.map.marginLeft.value = "auto"; } for (let i in this.map) { let selector = this.map[i].selector; let span = this.doc.querySelector(selector); this.updateSourceRuleTooltip(span, this.map[i].property, styleEntries); if (span.textContent.length > 0 && span.textContent == this.map[i].value) { continue; } span.textContent = this.map[i].value; this.manageOverflowingText(span); } width -= this.map.borderLeft.value + this.map.borderRight.value + this.map.paddingLeft.value + this.map.paddingRight.value; width = parseFloat(width.toPrecision(6)); height -= this.map.borderTop.value + this.map.borderBottom.value + this.map.paddingTop.value + this.map.paddingBottom.value; height = parseFloat(height.toPrecision(6)); let newValue = width + "\u00D7" + height; if (this.sizeLabel.textContent != newValue) { this.sizeLabel.textContent = newValue; } this.elementRules = styleEntries.map(e => e.rule); this.wrapper.hidden = false; this.inspector.emit("boxmodel-view-updated"); return null; }).bind(this)).catch(console.error); this._lastRequest = lastRequest; return this._lastRequest; },
} } this.update("project"); this.checkIfProjectIsRunning(); }, get selectedProject() { return this._selectedProject; }, removeSelectedProject: Task.async(function* () { let location = this.selectedProject.location; AppManager.selectedProject = null; // If the user cancels the removeProject operation, don't remove the project if (AppManager.selectedProject != null) { return; } yield AppProjects.remove(location); AppManager.update("project-removed"); }), packageProject: Task.async(function* (project) { if (!project) { return; } if (project.type == "packaged" || project.type == "hosted") { yield ProjectBuilding.build({ project: project, logger: this.update.bind(this, "pre-package")
/** * Initializes a connection to the profiler and other miscellaneous actors. * If in the process of opening, or already open, nothing happens. * * @return object * A promise that is resolved once the connection is established. */ connect: Task.async(function* () { if (this._connecting) { return this._connecting.promise; } // Create a promise that gets resolved upon connecting, so that // other attempts to open the connection use the same resolution promise this._connecting = promise.defer(); // Sets `this._profiler`, `this._timeline`. // Only initialize the timeline fronts if the respective actors // are available. Older Gecko versions don't have existing implementations, // in which case all the methods we need can be easily mocked. yield this._connectActors(); yield this._registerListeners(); this._connecting.resolve(); }), /** * Destroys this connection. */ destroy: Task.async(function* () { if (this._connecting) { yield this._connecting.promise;
installAndRunProject: function () { let 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._listTabsResponse) { 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 Task.spawn(function* () { let self = AppManager; // Package and validate project yield self.packageProject(project); yield self.validateAndUpdateProject(project); if (project.errorsCount > 0) { self.reportError("error_cantInstallValidationErrors"); return; } let installPromise; if (project.type != "packaged" && project.type != "hosted") { return promise.reject("Don't know how to install project"); } let response; if (project.type == "packaged") { let packageDir = yield ProjectBuilding.getPackageDir(project); console.log("Installing app from " + packageDir); response = yield 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") { let manifestURLObject = Services.io.newURI(project.location); let origin = Services.io.newURI(manifestURLObject.prePath); let appId = origin.host; let metadata = { origin: origin.spec, manifestURL: project.location }; response = yield 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; } let {app} = response; if (!app.running) { let deferred = promise.defer(); self.on("app-manager-update", function onUpdate(event, what) { if (what == "project-started") { self.off("app-manager-update", onUpdate); deferred.resolve(); } }); yield app.launch(); yield deferred.promise; } else { yield app.reload(); } }); },
search: custom(Task.async(function* (query, options = { }) { let nodeList; let searchType; let searchData = this.searchData = this.searchData || { }; let selectorOnly = !!options.selectorOnly; // Backwards compat. Use selector only search if the new // search functionality isn't implemented, or if the caller (tests) // want it. if (selectorOnly || !this.traits.textSearch) { searchType = "selector"; if (this.traits.multiFrameQuerySelectorAll) { nodeList = yield this.multiFrameQuerySelectorAll(query); } else { nodeList = yield this.querySelectorAll(this.rootNode, query); } } else { searchType = "search"; let result = yield this._search(query, options); nodeList = result.list; } // If this is a new search, start at the beginning. if (searchData.query !== query || searchData.selectorOnly !== selectorOnly) { searchData.selectorOnly = selectorOnly; searchData.query = query; searchData.index = -1; } if (!nodeList.length) { return null; } // Move search result cursor and cycle if necessary. searchData.index = options.reverse ? searchData.index - 1 : searchData.index + 1; if (searchData.index >= nodeList.length) { searchData.index = 0; } if (searchData.index < 0) { searchData.index = nodeList.length - 1; } // Send back the single node, along with any relevant search data let node = yield nodeList.item(searchData.index); return { type: searchType, node: node, resultsLength: nodeList.length, resultsIndex: searchData.index, }; }), {
this._target.on("will-navigate", this._onBeforeNavigate); EventEmitter.decorate(this); } exports.InspectorPanel = InspectorPanel; InspectorPanel.prototype = { /** * open is effectively an asynchronous constructor */ open: Task.async(function* () { this._cssPropertiesLoaded = initCssProperties(this.toolbox); yield this._cssPropertiesLoaded; yield this.target.makeRemote(); yield this._getPageStyle(); let defaultSelection = yield this._getDefaultNodeForSelection(); return yield this._deferredOpen(defaultSelection); }), get toolbox() { return this._toolbox; }, get inspector() { return this._toolbox.inspector; }, get walker() { return this._toolbox.walker; },
copyPostData: Task.async(function* () { let selected = this.selectedItem.attachment; // Try to extract any form data parameters. let formDataSections = yield getFormDataSections( selected.requestHeaders, selected.requestHeadersFromUploadStream, selected.requestPostData, gNetwork.getString.bind(gNetwork)); let params = []; formDataSections.forEach(section => { let paramsArray = NetworkHelper.parseQueryString(section); if (paramsArray) { params = [...params, ...paramsArray]; } }); let string = params .map(param => param.name + (param.value ? "=" + param.value : "")) .join(Services.appinfo.OS === "WINNT" ? "\r\n" : "\n"); // Fall back to raw payload. if (!string) { let postData = selected.requestPostData.postData.text; string = yield gNetwork.getString(postData); if (Services.appinfo.OS !== "WINNT") { string = string.replace(/\r/g, ""); } } clipboardHelper.copyString(string); }),
}, getMatchedSelectors: custom(function (node, property, options) { return this._getMatchedSelectors(node, property, options).then(ret => { return ret.matched; }); }, { impl: "_getMatchedSelectors" }), getApplied: custom(Task.async(function* (node, options = {}) { // If the getApplied method doesn't recreate the style cache itself, this // means a call to cssLogic.highlight is required before trying to access // the applied rules. Issue a request to getLayout if this is the case. // See https://bugzilla.mozilla.org/show_bug.cgi?id=1103993#c16. if (!this._form.traits || !this._form.traits.getAppliedCreatesStyleCache) { yield this.getLayout(node); } let ret = yield this._getApplied(node, options); return ret.entries; }), { impl: "_getApplied" }), addNewRule: custom(function (node, pseudoClasses) { let addPromise; if (this.supportsAuthoredStyles) { addPromise = this._addNewRule(node, pseudoClasses, true); } else { addPromise = this._addNewRule(node, pseudoClasses); }
} const MAXIMUM_FONT_SIZE = 96; const MINIMUM_FONT_SIZE = 6; const NORMAL_FONT_SIZE = 12; var testMaximumFontSize = Task.async(function* (win, sp) { let doc = win.document; Services.prefs.clearUserPref("devtools.scratchpad.editorFontSize"); let menu = doc.getElementById("sp-menu-larger-font"); for (let i = NORMAL_FONT_SIZE; i <= MAXIMUM_FONT_SIZE; i++) { menu.doCommand(); } let cmd = doc.getElementById("sp-cmd-larger-font"); ok(cmd.getAttribute("disabled") === "true", 'Command "sp-cmd-larger-font" is disabled.'); menu = doc.getElementById("sp-menu-smaller-font"); menu.doCommand(); ok(cmd.hasAttribute("disabled") === false, 'Command "sp-cmd-larger-font" is enabled.'); }); var testMinimumFontSize = Task.async(function* (win, sp) { let doc = win.document; let menu = doc.getElementById("sp-menu-smaller-font");