зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to m-c. a=merge
This commit is contained in:
Коммит
ae8c4ff6e3
|
@ -414,6 +414,8 @@ DevTools.prototype = {
|
|||
// No toolbox for target, create one
|
||||
toolbox = new devtools.Toolbox(target, toolId, hostType, hostOptions);
|
||||
|
||||
this.emit("toolbox-created", toolbox);
|
||||
|
||||
this._toolboxes.set(target, toolbox);
|
||||
|
||||
toolbox.once("destroy", () => {
|
||||
|
|
|
@ -43,6 +43,7 @@ skip-if = e10s # Bug 1069044 - destroyInspector may hang during shutdown
|
|||
[browser_toolbox_tabsswitch_shortcuts.js]
|
||||
[browser_toolbox_tool_ready.js]
|
||||
[browser_toolbox_tool_remote_reopen.js]
|
||||
[browser_toolbox_transport_events.js]
|
||||
[browser_toolbox_window_reload_target.js]
|
||||
[browser_toolbox_window_shortcuts.js]
|
||||
skip-if = os == "mac" && os_version == "10.8" || os == "win" && os_version == "5.1" # Bug 851129 - Re-enable browser_toolbox_window_shortcuts.js test after leaks are fixed
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const { on, off } = devtools.require("sdk/event/core");
|
||||
const { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
|
||||
|
||||
function test() {
|
||||
gDevTools.on("toolbox-created", onToolboxCreated);
|
||||
on(DebuggerClient, "connect", onDebuggerClientConnect);
|
||||
|
||||
addTab("about:blank").then(function() {
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target, "webconsole").then(testResults);
|
||||
});
|
||||
}
|
||||
|
||||
function testResults(toolbox) {
|
||||
testPackets(sent1, received1);
|
||||
testPackets(sent2, received2);
|
||||
|
||||
cleanUp(toolbox);
|
||||
}
|
||||
|
||||
function cleanUp(toolbox) {
|
||||
gDevTools.off("toolbox-created", onToolboxCreated);
|
||||
off(DebuggerClient, "connect", onDebuggerClientConnect);
|
||||
|
||||
toolbox.destroy().then(function() {
|
||||
gBrowser.removeCurrentTab();
|
||||
executeSoon(function() {
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testPackets(sent, received) {
|
||||
ok(sent.length > 0, "There must be at least one sent packet");
|
||||
ok(received.length > 0, "There must be at leaset one received packet");
|
||||
|
||||
if (!sent.length || received.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
let sentPacket = sent[0];
|
||||
let receivedPacket = received[0];
|
||||
|
||||
is(receivedPacket.from, "root",
|
||||
"The first received packet is from the root");
|
||||
is(receivedPacket.applicationType, "browser",
|
||||
"The first received packet has browser type");
|
||||
is(sentPacket.type, "listTabs",
|
||||
"The first sent packet is for list of tabs");
|
||||
}
|
||||
|
||||
// Listen to the transport object that is associated with the
|
||||
// default Toolbox debugger client
|
||||
let sent1 = [];
|
||||
let received1 = [];
|
||||
|
||||
function send1(eventId, packet) {
|
||||
sent1.push(packet);
|
||||
}
|
||||
|
||||
function onPacket1(eventId, packet) {
|
||||
received1.push(packet);
|
||||
}
|
||||
|
||||
function onToolboxCreated(eventId, toolbox) {
|
||||
toolbox.target.makeRemote();
|
||||
let client = toolbox.target.client;
|
||||
let transport = client._transport;
|
||||
|
||||
transport.on("send", send1);
|
||||
transport.on("onPacket", onPacket1);
|
||||
|
||||
client.addOneTimeListener("closed", event => {
|
||||
transport.off("send", send1);
|
||||
transport.off("onPacket", onPacket1);
|
||||
});
|
||||
}
|
||||
|
||||
// Listen to all debugger client object protocols.
|
||||
let sent2 = [];
|
||||
let received2 = [];
|
||||
|
||||
function send2(eventId, packet) {
|
||||
sent2.push(packet);
|
||||
}
|
||||
|
||||
function onPacket2(eventId, packet) {
|
||||
received2.push(packet);
|
||||
}
|
||||
|
||||
function onDebuggerClientConnect(client) {
|
||||
let transport = client._transport;
|
||||
|
||||
transport.on("send", send2);
|
||||
transport.on("onPacket", onPacket2);
|
||||
|
||||
client.addOneTimeListener("closed", event => {
|
||||
transport.off("send", send2);
|
||||
transport.off("onPacket", onPacket2);
|
||||
});
|
||||
}
|
|
@ -20,6 +20,11 @@ function consoleOpened(hud) {
|
|||
return waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "undefined",
|
||||
category: CATEGORY_OUTPUT,
|
||||
severity: SEVERITY_LOG,
|
||||
},
|
||||
{
|
||||
text: "start",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
}
|
||||
|
||||
function testXhrWarn(aCallback) {
|
||||
makeXhr('get', 'http://example.com', null, aCallback);
|
||||
makeXhr('get', 'http://example.com/browser/browser/devtools/netmonitor/test/sjs_cors-test-server.sjs', null, aCallback);
|
||||
}
|
||||
|
||||
function testXhrPost(aCallback) {
|
||||
|
|
|
@ -9,6 +9,7 @@ const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).de
|
|||
const {AppProjects} = require("devtools/app-manager/app-projects");
|
||||
const {AppValidator} = require("devtools/app-manager/app-validator");
|
||||
const {AppManager} = require("devtools/webide/app-manager");
|
||||
const {ProjectBuilding} = require("devtools/webide/build");
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
|
@ -44,6 +45,8 @@ function resetUI() {
|
|||
document.querySelector("#manifestURL").textContent = "";
|
||||
document.querySelector("#location").textContent = "";
|
||||
|
||||
document.querySelector("#prePackageLog").hidden = true;
|
||||
|
||||
document.querySelector("#errorslist").innerHTML = "";
|
||||
document.querySelector("#warningslist").innerHTML = "";
|
||||
|
||||
|
@ -102,6 +105,12 @@ function updateUI() {
|
|||
}
|
||||
}
|
||||
|
||||
if (project.type != "runtimeApp" && project.type != "mainProcess") {
|
||||
ProjectBuilding.hasPrepackage(project).then(hasPrepackage => {
|
||||
document.querySelector("#prePackageLog").hidden = !hasPrepackage;
|
||||
});
|
||||
}
|
||||
|
||||
let errorsNode = document.querySelector("#errorslist");
|
||||
let warningsNode = document.querySelector("#warningslist");
|
||||
|
||||
|
@ -122,6 +131,10 @@ function updateUI() {
|
|||
}
|
||||
}
|
||||
|
||||
function showPrepackageLog() {
|
||||
window.top.UI.selectDeckPanel("logs");
|
||||
}
|
||||
|
||||
function removeProject() {
|
||||
AppManager.removeSelectedProject();
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
|
||||
<h3 id="manifestURLHeader">&details_manifestURL;</h3>
|
||||
<p id="manifestURL"></p>
|
||||
|
||||
<button id="prePackageLog" onclick="showPrepackageLog()" hidden="true">&details_showPrepackageLog_button;</button>
|
||||
</main>
|
||||
|
||||
<ul class="validation_messages" id="errorslist"></ul>
|
||||
|
|
|
@ -26,3 +26,5 @@ webide.jar:
|
|||
content/devicesettings.xhtml (devicesettings.xhtml)
|
||||
content/wifi-auth.js (wifi-auth.js)
|
||||
content/wifi-auth.xhtml (wifi-auth.xhtml)
|
||||
content/logs.xhtml (logs.xhtml)
|
||||
content/logs.js (logs.js)
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/* 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 Cu = Components.utils;
|
||||
Cu.import("resource:///modules/devtools/gDevTools.jsm");
|
||||
const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
const {AppManager} = require("devtools/webide/app-manager");
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
|
||||
Logs.init();
|
||||
});
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
|
||||
Logs.uninit();
|
||||
});
|
||||
|
||||
const Logs = {
|
||||
init: function () {
|
||||
this.list = document.getElementById("logs");
|
||||
|
||||
Logs.onAppManagerUpdate = Logs.onAppManagerUpdate.bind(this);
|
||||
AppManager.on("app-manager-update", Logs.onAppManagerUpdate);
|
||||
|
||||
document.getElementById("close").onclick = Logs.close.bind(this);
|
||||
},
|
||||
|
||||
uninit: function () {
|
||||
AppManager.off("app-manager-update", Logs.onAppManagerUpdate);
|
||||
},
|
||||
|
||||
onAppManagerUpdate: function(event, what, details) {
|
||||
switch (what) {
|
||||
case "pre-package":
|
||||
this.prePackageLog(details);
|
||||
break;
|
||||
};
|
||||
},
|
||||
|
||||
close: function () {
|
||||
window.parent.UI.openProject();
|
||||
},
|
||||
|
||||
prePackageLog: function (msg, details) {
|
||||
if (msg == "start") {
|
||||
this.clear();
|
||||
} else if (msg == "succeed") {
|
||||
setTimeout(function () {
|
||||
Logs.close();
|
||||
}, 1000);
|
||||
} else if (msg == "failed") {
|
||||
this.log(details);
|
||||
} else {
|
||||
this.log(msg);
|
||||
}
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
this.list.innerHTML = "";
|
||||
},
|
||||
|
||||
log: function (msg) {
|
||||
let line = document.createElement("li");
|
||||
line.textContent = msg;
|
||||
this.list.appendChild(line);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
<?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://browser/locale/devtools/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://browser/skin/devtools/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/logs.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://browser/content/devtools/theme-switching.js"></script>
|
||||
<script type="application/javascript;version=1.8" 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>
|
|
@ -195,6 +195,9 @@ let UI = {
|
|||
case "runtime-apps-found":
|
||||
this.autoSelectProject();
|
||||
break;
|
||||
case "pre-package":
|
||||
this.prePackageLog(details);
|
||||
break;
|
||||
};
|
||||
this._updatePromise = promise.resolve();
|
||||
},
|
||||
|
@ -768,9 +771,13 @@ let UI = {
|
|||
},
|
||||
|
||||
selectDeckPanel: function(id) {
|
||||
let deck = document.querySelector("#deck");
|
||||
if (deck.selectedPanel && deck.selectedPanel.id === "deck-panel-" + id) {
|
||||
// This panel is already displayed.
|
||||
return;
|
||||
}
|
||||
this.hidePanels();
|
||||
this.resetFocus();
|
||||
let deck = document.querySelector("#deck");
|
||||
let panel = deck.querySelector("#deck-panel-" + id);
|
||||
let lazysrc = panel.getAttribute("lazysrc");
|
||||
if (lazysrc) {
|
||||
|
@ -1004,6 +1011,12 @@ let UI = {
|
|||
document.querySelector("#action-button-debug").removeAttribute("active");
|
||||
this.updateToolboxFullscreenState();
|
||||
},
|
||||
|
||||
prePackageLog: function (msg) {
|
||||
if (msg == "start") {
|
||||
UI.selectDeckPanel("logs");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let Cmds = {
|
||||
|
|
|
@ -201,6 +201,7 @@
|
|||
<iframe id="deck-panel-monitor" flex="1" lazysrc="monitor.xhtml"/>
|
||||
<iframe id="deck-panel-devicepreferences" flex="1" lazysrc="devicepreferences.xhtml"/>
|
||||
<iframe id="deck-panel-devicesettings" flex="1" lazysrc="devicesettings.xhtml"/>
|
||||
<iframe id="deck-panel-logs" flex="1" src="logs.xhtml"/>
|
||||
</deck>
|
||||
<splitter hidden="true" class="devtools-horizontal-splitter" orient="vertical"/>
|
||||
<!-- toolbox iframe will be inserted here -->
|
||||
|
|
|
@ -481,7 +481,10 @@ let AppManager = exports.AppManager = {
|
|||
return Task.spawn(function* () {
|
||||
let self = AppManager;
|
||||
|
||||
let packageDir = yield ProjectBuilding.build(project);
|
||||
let packageDir = yield ProjectBuilding.build({
|
||||
project: project,
|
||||
logger: self.update.bind(self, "pre-package")
|
||||
});
|
||||
|
||||
yield self.validateProject(project);
|
||||
|
||||
|
|
|
@ -30,13 +30,32 @@ const ProjectBuilding = exports.ProjectBuilding = {
|
|||
return manifest;
|
||||
}),
|
||||
|
||||
// If the app depends on some build step, run it before pushing the app
|
||||
build: Task.async(function* (project) {
|
||||
hasPrepackage: Task.async(function* (project) {
|
||||
let manifest = yield ProjectBuilding.fetchPackageManifest(project);
|
||||
if (!manifest || !manifest.webide || !manifest.webide.prepackage) {
|
||||
return manifest && manifest.webide && "prepackage" in manifest.webide;
|
||||
}),
|
||||
|
||||
// If the app depends on some build step, run it before pushing the app
|
||||
build: Task.async(function* ({ project, logger }) {
|
||||
if (!this.hasPrepackage(project)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let manifest = yield ProjectBuilding.fetchPackageManifest(project);
|
||||
|
||||
logger("start");
|
||||
let packageDir;
|
||||
try {
|
||||
packageDir = yield this._build(project, manifest, logger);
|
||||
logger("succeed");
|
||||
} catch(e) {
|
||||
logger("failed", e);
|
||||
}
|
||||
|
||||
return packageDir;
|
||||
}),
|
||||
|
||||
_build: Task.async(function* (project, manifest, logger) {
|
||||
// Look for `webide` property
|
||||
manifest = manifest.webide;
|
||||
|
||||
|
@ -80,10 +99,10 @@ const ProjectBuilding = exports.ProjectBuilding = {
|
|||
cwd = project.location;
|
||||
}
|
||||
|
||||
console.log("Running pre-package hook '" + command + "' " +
|
||||
args.join(" ") +
|
||||
" with ENV=[" + env.join(", ") + "]" +
|
||||
" at " + cwd);
|
||||
logger("Running pre-package hook '" + command + "' " +
|
||||
args.join(" ") +
|
||||
" with ENV=[" + env.join(", ") + "]" +
|
||||
" at " + cwd);
|
||||
|
||||
// Run the command through a shell command in order to support non absolute
|
||||
// paths.
|
||||
|
@ -115,12 +134,12 @@ const ProjectBuilding = exports.ProjectBuilding = {
|
|||
workdir: cwd,
|
||||
|
||||
stdout: data =>
|
||||
console.log("pre-package: " + data),
|
||||
logger(data),
|
||||
stderr: data =>
|
||||
console.error("pre-package: " + data),
|
||||
logger(data),
|
||||
|
||||
done: result => {
|
||||
console.log("pre-package: Terminated with error code: " + result.exitCode);
|
||||
logger("Terminated with error code: " + result.exitCode);
|
||||
if (result.exitCode == 0) {
|
||||
defer.resolve();
|
||||
} else {
|
||||
|
|
|
@ -50,8 +50,20 @@
|
|||
ok(!project.manifest, "manifest includes name");
|
||||
is(project.name, "--", "Display name uses manifest name");
|
||||
|
||||
let packageDir = yield ProjectBuilding.build(project);
|
||||
let loggedMessages = [];
|
||||
let logger = function (msg) {
|
||||
loggedMessages.push(msg);
|
||||
}
|
||||
|
||||
let packageDir = yield ProjectBuilding.build({
|
||||
project,
|
||||
logger
|
||||
});
|
||||
ok(!packageDir, "no custom packagedir");
|
||||
is(loggedMessages[0], "start", "log messages are correct");
|
||||
ok(loggedMessages[1].indexOf("Running pre-package hook") != -1, "log messages are correct");
|
||||
is(loggedMessages[2], "Terminated with error code: 0", "log messages are correct");
|
||||
is(loggedMessages[3], "succeed", "log messages are correct");
|
||||
|
||||
// Trigger validation
|
||||
yield AppManager.validateProject(AppManager.selectedProject);
|
||||
|
@ -70,9 +82,17 @@
|
|||
|
||||
project = win.AppManager.selectedProject;
|
||||
|
||||
packageDir = yield ProjectBuilding.build(project);
|
||||
loggedMessages = [];
|
||||
packageDir = yield ProjectBuilding.build({
|
||||
project,
|
||||
logger
|
||||
});
|
||||
is(OS.Path.normalize(packageDir),
|
||||
OS.Path.join(packagedAppLocation, "stage"), "custom packagedir");
|
||||
is(loggedMessages[0], "start", "log messages are correct");
|
||||
ok(loggedMessages[1].indexOf("Running pre-package hook") != -1, "log messages are correct");
|
||||
is(loggedMessages[2], "Terminated with error code: 0", "log messages are correct");
|
||||
is(loggedMessages[3], "succeed", "log messages are correct");
|
||||
|
||||
// Switch to the package dir in order to verify the generated webapp.manifest
|
||||
yield win.Cmds.importPackagedApp(packageDir);
|
||||
|
|
|
@ -17,3 +17,4 @@ webide.jar:
|
|||
skin/monitor.css (monitor.css)
|
||||
skin/config-view.css (config-view.css)
|
||||
skin/wifi-auth.css (wifi-auth.css)
|
||||
skin/logs.css (logs.css)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
html, body {
|
||||
background: var(--theme-body-background);
|
||||
color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
|
@ -94,6 +94,7 @@
|
|||
<!ENTITY details_location "Location">
|
||||
<!ENTITY details_manifestURL "App ID">
|
||||
<!ENTITY details_removeProject_button "Remove Project">
|
||||
<!ENTITY details_showPrepackageLog_button "Show Pre-package Log">
|
||||
|
||||
<!-- New App -->
|
||||
<!ENTITY newAppWindowTitle "New App">
|
||||
|
@ -191,3 +192,6 @@
|
|||
<!-- 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:">
|
||||
|
||||
<!-- Logs panel -->
|
||||
<!ENTITY logs_title "Pre-packaging Command Logs">
|
||||
|
|
|
@ -29,6 +29,12 @@
|
|||
|
||||
<include layout="@layout/shared_ui_components"/>
|
||||
|
||||
<ViewStub android:id="@+id/zoomed_view_stub"
|
||||
android:inflatedId="@+id/zoomed_view"
|
||||
android:layout="@layout/zoomed_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<FrameLayout android:id="@+id/home_pager_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
|
|
@ -26,12 +26,6 @@
|
|||
|
||||
<include layout="@layout/text_selection_handles"/>
|
||||
|
||||
<ViewStub android:id="@+id/zoomed_view_stub"
|
||||
android:inflatedId="@+id/zoomed_view"
|
||||
android:layout="@layout/zoomed_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<FrameLayout android:id="@+id/camera_layout"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -7,6 +7,7 @@ this.EXPORTED_SYMBOLS = ["RemoteAddonsParent"];
|
|||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
|
@ -512,22 +513,33 @@ let EventTargetParent = {
|
|||
|
||||
for (let [handler, target] of handlers) {
|
||||
let EventProxy = {
|
||||
get: function(actualEvent, name) {
|
||||
if (name == "currentTarget") {
|
||||
return target;
|
||||
} else {
|
||||
return actualEvent[name];
|
||||
}
|
||||
get: function(knownProps, name) {
|
||||
if (knownProps.hasOwnProperty(name))
|
||||
return knownProps[name];
|
||||
return event[name];
|
||||
}
|
||||
};
|
||||
let proxyEvent = new Proxy(event, EventProxy);
|
||||
}
|
||||
let proxyEvent = new Proxy({
|
||||
currentTarget: target,
|
||||
target: eventTarget,
|
||||
type: type,
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsIDOMEventTarget))
|
||||
return proxyEvent;
|
||||
// If event deson't support the interface this will throw. If it
|
||||
// does we want to return the proxy
|
||||
event.QueryInterface(iid);
|
||||
return proxyEvent;
|
||||
}
|
||||
}, EventProxy);
|
||||
|
||||
try {
|
||||
Prefetcher.withPrefetching(prefetched, cpows, () => {
|
||||
if ("handleEvent" in handler) {
|
||||
handler.handleEvent(proxyEvent);
|
||||
} else {
|
||||
handler.call(event.target, proxyEvent);
|
||||
handler.call(eventTarget, proxyEvent);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
|
|
|
@ -250,7 +250,7 @@ var LoginManagerContent = {
|
|||
let doc = form.ownerDocument;
|
||||
let autofillForm = gAutofillForms && !PrivateBrowsingUtils.isContentWindowPrivate(doc.defaultView);
|
||||
|
||||
this._fillForm(form, autofillForm, false, false, false, loginsFound);
|
||||
this._fillForm(form, autofillForm, false, false, loginsFound);
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -293,7 +293,7 @@ var LoginManagerContent = {
|
|||
if (usernameField == acInputField && passwordField) {
|
||||
this._asyncFindLogins(acForm, { showMasterPassword: false })
|
||||
.then(({ form, loginsFound }) => {
|
||||
this._fillForm(form, true, true, true, true, loginsFound);
|
||||
this._fillForm(form, true, true, true, loginsFound);
|
||||
})
|
||||
.then(null, Cu.reportError);
|
||||
} else {
|
||||
|
@ -564,14 +564,13 @@ var LoginManagerContent = {
|
|||
* [success, foundLogins].
|
||||
*
|
||||
* - autofillForm denotes if we should fill the form in automatically
|
||||
* - ignoreAutocomplete denotes if we should ignore autocomplete=off
|
||||
* attributes
|
||||
* - userTriggered is an indication of whether this filling was triggered by
|
||||
* the user
|
||||
* - foundLogins is an array of nsILoginInfo for optimization
|
||||
*/
|
||||
_fillForm : function (form, autofillForm, ignoreAutocomplete,
|
||||
clobberPassword, userTriggered, foundLogins) {
|
||||
_fillForm : function (form, autofillForm, clobberPassword,
|
||||
userTriggered, foundLogins) {
|
||||
let ignoreAutocomplete = true;
|
||||
// Heuristically determine what the user/pass fields are
|
||||
// We do this before checking to see if logins are stored,
|
||||
// so that the user isn't prompted for a master password
|
||||
|
|
|
@ -587,8 +587,7 @@ LoginManager.prototype = {
|
|||
log("fillForm processing form[ id:", form.id, "]");
|
||||
return LoginManagerContent._asyncFindLogins(form, { showMasterPassword: true })
|
||||
.then(function({ form, loginsFound }) {
|
||||
return LoginManagerContent._fillForm(form, true, true,
|
||||
false, false, loginsFound)[0];
|
||||
return LoginManagerContent._fillForm(form, true, false, false, loginsFound)[0];
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ skip-if = toolkit == 'android'
|
|||
[test_case_differences.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_basic_form_html5.html]
|
||||
[test_basic_form_observer_autocomplete.html]
|
||||
[test_basic_form_observer_autofillForms.html]
|
||||
[test_basic_form_observer_foundLogins.html]
|
||||
[test_basic_form_pwevent.html]
|
||||
|
@ -49,7 +48,6 @@ skip-if = toolkit == 'android'
|
|||
# This test doesn't pass because we can't ensure a cross-platform event that
|
||||
# occurs between DOMContentLoaded and Pageload
|
||||
skip-if = true
|
||||
[test_bug_227640.html]
|
||||
[test_bug_242956.html]
|
||||
[test_bug_360493_1.html]
|
||||
[test_bug_360493_2.html]
|
||||
|
|
|
@ -558,13 +558,13 @@ function* runTest() {
|
|||
yield runNextTest();
|
||||
|
||||
|
||||
/* Tests for single-user forms with autocomplete=off */
|
||||
/* Tests for single-user forms for ignoring autocomplete=off */
|
||||
|
||||
/* test 100 */
|
||||
// Turn our attention to form2
|
||||
uname = $_(2, "uname");
|
||||
pword = $_(2, "pword");
|
||||
checkACForm("", "");
|
||||
checkACForm("singleuser5", "singlepass5");
|
||||
|
||||
// Trigger autocomplete popup
|
||||
restoreForm();
|
||||
|
@ -585,8 +585,8 @@ function* runTest() {
|
|||
// Turn our attention to form3
|
||||
uname = $_(3, "uname");
|
||||
pword = $_(3, "pword");
|
||||
checkACForm("", "");
|
||||
|
||||
checkACForm("singleuser5", "singlepass5");
|
||||
|
||||
// Trigger autocomplete popup
|
||||
restoreForm();
|
||||
doKey("down");
|
||||
|
@ -605,7 +605,7 @@ function* runTest() {
|
|||
// Turn our attention to form4
|
||||
uname = $_(4, "uname");
|
||||
pword = $_(4, "pword");
|
||||
checkACForm("", "");
|
||||
checkACForm("singleuser5", "singlepass5");
|
||||
|
||||
// Trigger autocomplete popup
|
||||
restoreForm();
|
||||
|
@ -625,7 +625,7 @@ function* runTest() {
|
|||
// Turn our attention to form5
|
||||
uname = $_(5, "uname");
|
||||
pword = $_(5, "pword");
|
||||
checkACForm("", "");
|
||||
checkACForm("singleuser5", "singlepass5");
|
||||
|
||||
// Trigger autocomplete popup
|
||||
restoreForm();
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Login Manager test: simple form with autocomplete off and notifying observers & normal form
|
||||
<script>
|
||||
const Cc = SpecialPowers.Cc;
|
||||
const Ci = SpecialPowers.Ci;
|
||||
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: block">
|
||||
|
||||
<form id="form1" action="formtest.js" autocomplete="off">
|
||||
<p>This is form 1.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form2" action="formtest.js">
|
||||
<p>This is form 2.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Login Manager: simple form with autocomplete off and notifying observers & normal form **/
|
||||
var TestObserver = {
|
||||
receivedNotification1 : false,
|
||||
receivedNotification2 : false,
|
||||
data1 : "",
|
||||
data2 : "",
|
||||
observe : function (subject, topic, data) {
|
||||
var pwmgr = Cc["@mozilla.org/login-manager;1"].
|
||||
getService(Ci.nsILoginManager);
|
||||
if (topic == "passwordmgr-found-form") {
|
||||
if (subject.id == "form1") {
|
||||
this.receivedNotification1 = true;
|
||||
this.data1 = data;
|
||||
} else if (subject.id == "form2") {
|
||||
this.receivedNotification2 = true;
|
||||
this.data2 = data;
|
||||
}
|
||||
|
||||
// Now fill the form
|
||||
pwmgr.fillForm(subject)
|
||||
.then(startTest);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add the observer
|
||||
SpecialPowers.addObserver(TestObserver, "passwordmgr-found-form", false);
|
||||
|
||||
function startTest(){
|
||||
// Test that observer is notified & got correct data
|
||||
is(TestObserver.receivedNotification1, true, "Checking observer was notified");
|
||||
is(TestObserver.data1, "autocompleteOff", "Checking observer got correct data");
|
||||
|
||||
// Check that form1 was filled
|
||||
is($_(1, "uname").value, "testuser", "Checking for filled username 1");
|
||||
is($_(1, "pword").value, "testpass", "Checking for filled password 1");
|
||||
|
||||
// Test that observer wasn't notified & didn't get data
|
||||
is(TestObserver.receivedNotification2, false, "Checking observer was not notified");
|
||||
is(TestObserver.data2, "", "Checking observer didn't get data");
|
||||
|
||||
// Check that form2 was filled
|
||||
is($_(2, "uname").value, "testuser", "Checking for filled username 2");
|
||||
is($_(2, "pword").value, "testpass", "Checking for filled password 2");
|
||||
|
||||
// Remove the observer
|
||||
try {
|
||||
SpecialPowers.removeObserver(TestObserver, "passwordmgr-found-form");
|
||||
} catch (e) {
|
||||
ok(false, SpecialPowers.wrap(e));
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -44,7 +44,7 @@ var TestObserver = {
|
|||
};
|
||||
|
||||
// Initialize the object that stores the results of notifications.
|
||||
for (var formID of ["form1", "form2", "form3", "form4", "form5"])
|
||||
for (var formID of ["form1", "form2", "form3", "form5"])
|
||||
TestObserver.results[formID] = { receivedNotification: false, data: null };
|
||||
|
||||
// Add the observer
|
||||
|
@ -82,15 +82,6 @@ SpecialPowers.addObserver(TestObserver, "passwordmgr-found-logins", false);
|
|||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form4" action="formtest.js" autocomplete="off">
|
||||
<p>This is form 4.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form5" action="http://www.example.com">
|
||||
<p>This is form 5.</p>
|
||||
<input type="text" name="uname">
|
||||
|
@ -139,17 +130,6 @@ function startTest(){
|
|||
is(TestObserver.results["form3"].data.get("foundLogins").length, 1, "Checking foundLogins contains one login");
|
||||
is(TestObserver.results["form3"].data.get("selectedLogin"), null, "Checking selectedLogin is null");
|
||||
|
||||
// Test notification of a form that wasn't filled because autocomplete is off.
|
||||
is(TestObserver.results["form4"].receivedNotification, true, "Checking observer was notified");
|
||||
is(TestObserver.results["form4"].data.get("didntFillReason"), "autocompleteOff", "Checking didntFillReason is autocompleteOff");
|
||||
is(SpecialPowers.unwrap(TestObserver.results["form4"].data.get("usernameField")), $_(4, "uname"), "Checking username field is correct");
|
||||
is(SpecialPowers.unwrap(TestObserver.results["form4"].data.get("passwordField")), $_(4, "pword"), "Checking password field is correct");
|
||||
is(TestObserver.results["form4"].data.get("foundLogins").constructor.name, "Array", "Checking foundLogins is array");
|
||||
is(TestObserver.results["form4"].data.get("foundLogins").length, 1, "Checking foundLogins contains one login");
|
||||
ok(TestObserver.results["form4"].data.get("selectedLogin").QueryInterface(Ci.nsILoginInfo), "Checking selectedLogin is nsILoginInfo");
|
||||
ok(TestObserver.results["form4"].data.get("selectedLogin").equals(TestObserver.results["form4"].data.get("foundLogins")[0]),
|
||||
"Checking selectedLogin is found login");
|
||||
|
||||
// Test notification of a form that wasn't filled because multiple logins
|
||||
// are available for the form.
|
||||
is(TestObserver.results["form5"].receivedNotification, true, "Checking observer was notified");
|
||||
|
|
|
@ -1,243 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Login Manager test: 227640
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
|
||||
.getService(SpecialPowers.Ci.nsILoginManager);
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
<!-- no autocomplete for password field -->
|
||||
<form id="form1" onsubmit="return checkSubmit(1)" method="get">
|
||||
<input type="text" name="uname" value="">
|
||||
<input type="password" name="pword" value="" autocomplete=off>
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for username field -->
|
||||
<form id="form2" onsubmit="return checkSubmit(2);" method="get">
|
||||
<input type="text" name="uname" value="" autocomplete=off>
|
||||
<input type="password" name="pword" value="">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for username or password fields -->
|
||||
<form id="form3" onsubmit="return checkSubmit(3);" method="get">
|
||||
<input type="text" name="uname" value="" autocomplete=off>
|
||||
<input type="password" name="pword" value="" autocomplete=off>
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for entire form -->
|
||||
<form id="form4" onsubmit="return checkSubmit(4);" method="get" autocomplete=off>
|
||||
<input type="text" name="uname" value="">
|
||||
<input type="password" name="pword" value="">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for entire form and password field -->
|
||||
<form id="form5" onsubmit="return checkSubmit(5);" method="get">
|
||||
<input type="text" name="uname" value="">
|
||||
<input type="password" name="pword" value="" autocomplete=off>
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for entire form and username field -->
|
||||
<form id="form6" onsubmit="return checkSubmit(6);" method="get">
|
||||
<input type="text" name="uname" value="" autocomplete=off>
|
||||
<input type="password" name="pword" value="">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for entire form, userfield, and password field -->
|
||||
<form id="form7" onsubmit="return checkSubmit(7);" method="get" autocomplete=off>
|
||||
<input type="text" name="uname" value="" autocomplete=off>
|
||||
<input type="password" name="pword" value="" autocomplete=off>
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
|
||||
<!-- ===== repeat, but with logins not previously stored ===== -->
|
||||
|
||||
|
||||
<!-- no autocomplete for password field -->
|
||||
<form id="form8" onsubmit="return checkSubmit(8);" method="get">
|
||||
<input type="text" name="xxxuname" value="newuser">
|
||||
<input type="password" name="xxxpword" value="newpass" autocomplete=off>
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for username field -->
|
||||
<form id="form9" onsubmit="return checkSubmit(9);" method="get">
|
||||
<input type="text" name="xxxuname" value="newuser" autocomplete=off>
|
||||
<input type="password" name="xxxpword" value="newpass">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for username or password fields -->
|
||||
<form id="form10" onsubmit="return checkSubmit(10);" method="get">
|
||||
<input type="text" name="xxxuname" value="newuser" autocomplete=off>
|
||||
<input type="password" name="xxxpword" value="newpass" autocomplete=off>
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for entire form -->
|
||||
<form id="form11" onsubmit="return checkSubmit(11);" method="get" autocomplete=off>
|
||||
<input type="text" name="xxxuname" value="newuser">
|
||||
<input type="password" name="xxxpword" value="newpass">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for entire form and password field -->
|
||||
<form id="form12" onsubmit="return checkSubmit(12);" method="get">
|
||||
<input type="text" name="xxxuname" value="newuser">
|
||||
<input type="password" name="xxxpword" value="newpass" autocomplete=off>
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for entire form and username field -->
|
||||
<form id="form13" onsubmit="return checkSubmit(13);" method="get">
|
||||
<input type="text" name="xxxuname" value="newuser" autocomplete=off>
|
||||
<input type="password" name="xxxpword" value="newpass">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<!-- no autocomplete for entire form, userfield, and password field -->
|
||||
<form id="form14" onsubmit="return checkSubmit(14);" method="get" autocomplete=off>
|
||||
<input type="text" name="xxxuname" value="newuser" autocomplete=off>
|
||||
<input type="password" name="xxxpword" value="newpass" autocomplete=off>
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Login Manager: 227640 (password is saved even when the
|
||||
password field has autocomplete="off") **/
|
||||
|
||||
// This test ensures that pwmgr does not save a username or password when
|
||||
// autocomplete=off is present.
|
||||
|
||||
var numStartingLogins = 0;
|
||||
var numSubmittedForms = 0;
|
||||
|
||||
function startTest() {
|
||||
// Get current number of logins, so we can know if some accidently get
|
||||
// added during the test.
|
||||
numStartingLogins = countLogins();
|
||||
ok(numStartingLogins > 0, "counting logins at start");
|
||||
|
||||
// Check first set of forms, which should not be filled by pwmgr.
|
||||
for (var i = 1; i <= 7; i++) {
|
||||
is($_(i, "uname").value, "", "Checking for unfilled username " + i);
|
||||
is($_(i, "pword").value, "", "Checking for unfilled password " + i);
|
||||
// Set the field values to that of an existing login
|
||||
$_(i, "uname").value = "testuser";
|
||||
$_(i, "pword").value = "testpass";
|
||||
}
|
||||
|
||||
// Check second set of forms, which should have preset values (and are unknown to pwmgr).
|
||||
for (var i = 8; i <= 14; i++) {
|
||||
is($_(i, "xxxuname").value, "newuser", "Checking unmodified username " + i);
|
||||
is($_(i, "xxxpword").value, "newpass", "Checking unmodified password " + i);
|
||||
}
|
||||
|
||||
var button = getFormSubmitButton(1);
|
||||
|
||||
// submit the first form.
|
||||
button.click();
|
||||
}
|
||||
|
||||
|
||||
// Called by each form's onsubmit handler.
|
||||
function checkSubmit(formNum) {
|
||||
numSubmittedForms++;
|
||||
|
||||
// End the test at the last form.
|
||||
if (formNum == 14) {
|
||||
is(numSubmittedForms, 14, "Ensuring all forms were submitted.");;
|
||||
|
||||
var numEndingLogins = countLogins();
|
||||
ok(numEndingLogins > 0, "counting logins at end");
|
||||
|
||||
is(numStartingLogins, numEndingLogins, "counting logins at end");
|
||||
|
||||
SimpleTest.finish();
|
||||
return false; // return false to cancel current form submission
|
||||
}
|
||||
|
||||
var button = getFormSubmitButton(formNum + 1);
|
||||
|
||||
// submit the next form.
|
||||
button.click();
|
||||
|
||||
return false; // return false to cancel current form submission
|
||||
}
|
||||
|
||||
|
||||
function getFormSubmitButton(formNum) {
|
||||
var form = $("form" + formNum); // by id, not name
|
||||
ok(form != null, "getting form " + formNum);
|
||||
|
||||
// we can't just call form.submit(), because that doesn't seem to
|
||||
// invoke the form onsubmit handler.
|
||||
var button = form.firstChild;
|
||||
while (button && button.type != "submit") { button = button.nextSibling; }
|
||||
ok(button != null, "getting form submit button");
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
// Counts the number of logins currently stored by password manager.
|
||||
function countLogins() {
|
||||
var logins = pwmgr.getAllLogins();
|
||||
|
||||
return logins.length;
|
||||
}
|
||||
window.addEventListener("runTests", startTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -41,6 +41,7 @@ const PREF_ENABLED = PREF_BRANCH + "enabled";
|
|||
const PREF_PREVIOUS_BUILDID = PREF_BRANCH + "previousBuildID";
|
||||
const PREF_CACHED_CLIENTID = PREF_BRANCH + "cachedClientID"
|
||||
const PREF_FHR_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled";
|
||||
const PREF_ASYNC_PLUGIN_INIT = "dom.ipc.plugins.asyncInit";
|
||||
|
||||
const MESSAGE_TELEMETRY_PAYLOAD = "Telemetry:Payload";
|
||||
|
||||
|
@ -547,7 +548,8 @@ let Impl = {
|
|||
appUpdateChannel: UpdateChannel.get(),
|
||||
platformBuildID: ai.platformBuildID,
|
||||
revision: HISTOGRAMS_FILE_VERSION,
|
||||
locale: getLocale()
|
||||
locale: getLocale(),
|
||||
asyncPluginInit: Preferences.get(PREF_ASYNC_PLUGIN_INIT, false)
|
||||
};
|
||||
|
||||
// In order to share profile data, the appName used for Metro Firefox is "Firefox",
|
||||
|
|
|
@ -396,6 +396,12 @@ DebuggerClient.prototype = {
|
|||
* received from the debugging server.
|
||||
*/
|
||||
connect: function (aOnConnected) {
|
||||
this.emit("connect");
|
||||
|
||||
// Also emit the event on the |DebuggerServer| object (not on
|
||||
// the instance), so it's possible to track all instances.
|
||||
events.emit(DebuggerClient, "connect", this);
|
||||
|
||||
this.addOneTimeListener("connected", (aName, aApplicationType, aTraits) => {
|
||||
this.traits = aTraits;
|
||||
if (aOnConnected) {
|
||||
|
|
|
@ -30,6 +30,7 @@ const StreamUtils = require("devtools/toolkit/transport/stream-utils");
|
|||
const { Packet, JSONPacket, BulkPacket } =
|
||||
require("devtools/toolkit/transport/packets");
|
||||
const promise = require("promise");
|
||||
const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
|
||||
DevToolsUtils.defineLazyGetter(this, "Pipe", () => {
|
||||
return CC("@mozilla.org/pipe;1", "nsIPipe", "init");
|
||||
|
@ -100,6 +101,8 @@ const PACKET_HEADER_MAX = 200;
|
|||
* details on the format of these packets.
|
||||
*/
|
||||
function DebuggerTransport(input, output) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this._input = input;
|
||||
this._scriptableInput = new ScriptableInputStream(input);
|
||||
this._output = output;
|
||||
|
@ -131,6 +134,8 @@ DebuggerTransport.prototype = {
|
|||
* they are passed to this method.
|
||||
*/
|
||||
send: function(object) {
|
||||
this.emit("send", object);
|
||||
|
||||
let packet = new JSONPacket(this);
|
||||
packet.object = object;
|
||||
this._outgoing.push(packet);
|
||||
|
@ -179,6 +184,8 @@ DebuggerTransport.prototype = {
|
|||
* that is copied. See stream-utils.js.
|
||||
*/
|
||||
startBulkSend: function(header) {
|
||||
this.emit("startBulkSend", header);
|
||||
|
||||
let packet = new BulkPacket(this);
|
||||
packet.header = header;
|
||||
this._outgoing.push(packet);
|
||||
|
@ -193,6 +200,8 @@ DebuggerTransport.prototype = {
|
|||
* closing the transport (likely because a stream closed or failed).
|
||||
*/
|
||||
close: function(reason) {
|
||||
this.emit("onClosed", reason);
|
||||
|
||||
this.active = false;
|
||||
this._input.close();
|
||||
this._scriptableInput.close();
|
||||
|
@ -458,6 +467,7 @@ DebuggerTransport.prototype = {
|
|||
DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => {
|
||||
// Ensure the transport is still alive by the time this runs.
|
||||
if (this.active) {
|
||||
this.emit("onPacket", object);
|
||||
this.hooks.onPacket(object);
|
||||
}
|
||||
}, "DebuggerTransport instance's this.hooks.onPacket"));
|
||||
|
@ -473,6 +483,7 @@ DebuggerTransport.prototype = {
|
|||
DevToolsUtils.executeSoon(DevToolsUtils.makeInfallible(() => {
|
||||
// Ensure the transport is still alive by the time this runs.
|
||||
if (this.active) {
|
||||
this.emit("onBulkPacket", ...args);
|
||||
this.hooks.onBulkPacket(...args);
|
||||
}
|
||||
}, "DebuggerTransport instance's this.hooks.onBulkPacket"));
|
||||
|
@ -506,6 +517,8 @@ exports.DebuggerTransport = DebuggerTransport;
|
|||
* @see DebuggerTransport
|
||||
*/
|
||||
function LocalDebuggerTransport(other) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this.other = other;
|
||||
this.hooks = null;
|
||||
|
||||
|
@ -524,6 +537,8 @@ LocalDebuggerTransport.prototype = {
|
|||
* endpoint.
|
||||
*/
|
||||
send: function(packet) {
|
||||
this.emit("send", packet);
|
||||
|
||||
let serial = this._serial.count++;
|
||||
if (dumpn.wantLogging) {
|
||||
/* Check 'from' first, as 'echo' packets have both. */
|
||||
|
@ -542,6 +557,7 @@ LocalDebuggerTransport.prototype = {
|
|||
dumpn("Received packet " + serial + ": " + JSON.stringify(packet, null, 2));
|
||||
}
|
||||
if (other.hooks) {
|
||||
other.emit("onPacket", packet);
|
||||
other.hooks.onPacket(packet);
|
||||
}
|
||||
}, "LocalDebuggerTransport instance's this.other.hooks.onPacket"));
|
||||
|
@ -558,6 +574,8 @@ LocalDebuggerTransport.prototype = {
|
|||
* done with it.
|
||||
*/
|
||||
startBulkSend: function({actor, type, length}) {
|
||||
this.emit("startBulkSend", {actor, type, length});
|
||||
|
||||
let serial = this._serial.count++;
|
||||
|
||||
dumpn("Sent bulk packet " + serial + " for actor " + actor);
|
||||
|
@ -575,8 +593,7 @@ LocalDebuggerTransport.prototype = {
|
|||
|
||||
// Receiver
|
||||
let deferred = promise.defer();
|
||||
|
||||
this.other.hooks.onBulkPacket({
|
||||
let packet = {
|
||||
actor: actor,
|
||||
type: type,
|
||||
length: length,
|
||||
|
@ -588,7 +605,10 @@ LocalDebuggerTransport.prototype = {
|
|||
},
|
||||
stream: pipe.inputStream,
|
||||
done: deferred
|
||||
});
|
||||
};
|
||||
|
||||
this.other.emit("onBulkPacket", packet);
|
||||
this.other.hooks.onBulkPacket(packet);
|
||||
|
||||
// Await the result of reading from the stream
|
||||
deferred.promise.then(() => pipe.inputStream.close(), this.close);
|
||||
|
@ -624,6 +644,8 @@ LocalDebuggerTransport.prototype = {
|
|||
* Close the transport.
|
||||
*/
|
||||
close: function() {
|
||||
this.emit("close");
|
||||
|
||||
if (this.other) {
|
||||
// Remove the reference to the other endpoint before calling close(), to
|
||||
// avoid infinite recursion.
|
||||
|
@ -681,6 +703,8 @@ exports.LocalDebuggerTransport = LocalDebuggerTransport;
|
|||
* <prefix> is |prefix|, whose data is the protocol packet.
|
||||
*/
|
||||
function ChildDebuggerTransport(sender, prefix) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this._sender = sender.QueryInterface(Ci.nsIMessageSender);
|
||||
this._messageName = "debug:" + prefix + ":packet";
|
||||
}
|
||||
|
@ -701,14 +725,17 @@ ChildDebuggerTransport.prototype = {
|
|||
|
||||
close: function () {
|
||||
this._sender.removeMessageListener(this._messageName, this);
|
||||
this.emit("onClosed");
|
||||
this.hooks.onClosed();
|
||||
},
|
||||
|
||||
receiveMessage: function ({data}) {
|
||||
this.emit("onPacket", data);
|
||||
this.hooks.onPacket(data);
|
||||
},
|
||||
|
||||
send: function (packet) {
|
||||
this.emit("send", packet);
|
||||
this._sender.sendAsyncMessage(this._messageName, packet);
|
||||
},
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче