Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 "use strict";
9 const Cu = Components.utils;
10 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
11 Cu.import("resource://gre/modules/Services.jsm");
12 Cu.import("resource://gre/modules/Task.jsm");
13 Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
14 let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
15 let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
16 let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
18 let gClient;
19 let gConnectionTimeout;
21 XPCOMUtils.defineLazyGetter(window, 'l10n', function () {
22 return Services.strings.createBundle('chrome://browser/locale/devtools/connection-screen.properties');
23 });
25 /**
26 * Once DOM is ready, we prefil the host/port inputs with
27 * pref-stored values.
28 */
29 window.addEventListener("DOMContentLoaded", function onDOMReady() {
30 window.removeEventListener("DOMContentLoaded", onDOMReady, true);
31 let host = Services.prefs.getCharPref("devtools.debugger.remote-host");
32 let port = Services.prefs.getIntPref("devtools.debugger.remote-port");
34 if (host) {
35 document.getElementById("host").value = host;
36 }
38 if (port) {
39 document.getElementById("port").value = port;
40 }
42 let form = document.querySelector("#connection-form form");
43 form.addEventListener("submit", function() {
44 window.submit();
45 });
46 }, true);
48 /**
49 * Called when the "connect" button is clicked.
50 */
51 function submit() {
52 // Show the "connecting" screen
53 document.body.classList.add("connecting");
55 // Save the host/port values
56 let host = document.getElementById("host").value;
57 Services.prefs.setCharPref("devtools.debugger.remote-host", host);
59 let port = document.getElementById("port").value;
60 Services.prefs.setIntPref("devtools.debugger.remote-port", port);
62 // Initiate the connection
63 let transport;
64 try {
65 transport = debuggerSocketConnect(host, port);
66 } catch(e) {
67 // Bug 921850: catch rare exception from debuggerSocketConnect
68 showError("unexpected");
69 return;
70 }
71 gClient = new DebuggerClient(transport);
72 let delay = Services.prefs.getIntPref("devtools.debugger.remote-timeout");
73 gConnectionTimeout = setTimeout(handleConnectionTimeout, delay);
74 gClient.connect(onConnectionReady);
75 }
77 /**
78 * Connection is ready. List actors and build buttons.
79 */
80 let onConnectionReady = Task.async(function*(aType, aTraits) {
81 clearTimeout(gConnectionTimeout);
83 let deferred = promise.defer();
84 gClient.listAddons(deferred.resolve);
85 let response = yield deferred.promise;
87 let parent = document.getElementById("addonActors")
88 if (!response.error && response.addons.length > 0) {
89 // Add one entry for each add-on.
90 for (let addon of response.addons) {
91 if (!addon.debuggable) {
92 continue;
93 }
94 buildAddonLink(addon, parent);
95 }
96 }
97 else {
98 // Hide the section when there are no add-ons
99 parent.previousElementSibling.remove();
100 parent.remove();
101 }
103 deferred = promise.defer();
104 gClient.listTabs(deferred.resolve);
105 response = yield deferred.promise;
107 parent = document.getElementById("tabActors");
109 // Add Global Process debugging...
110 let globals = JSON.parse(JSON.stringify(response));
111 delete globals.tabs;
112 delete globals.selected;
113 // ...only if there are appropriate actors (a 'from' property will always
114 // be there).
116 // Add one entry for each open tab.
117 for (let i = 0; i < response.tabs.length; i++) {
118 buildTabLink(response.tabs[i], parent, i == response.selected);
119 }
121 let gParent = document.getElementById("globalActors");
123 // Build the Remote Process button
124 if (Object.keys(globals).length > 1) {
125 let a = document.createElement("a");
126 a.onclick = function() {
127 openToolbox(globals, true);
129 }
130 a.title = a.textContent = window.l10n.GetStringFromName("mainProcess");
131 a.className = "remote-process";
132 a.href = "#";
133 gParent.appendChild(a);
134 }
135 // Move the selected tab on top
136 let selectedLink = parent.querySelector("a.selected");
137 if (selectedLink) {
138 parent.insertBefore(selectedLink, parent.firstChild);
139 }
141 document.body.classList.remove("connecting");
142 document.body.classList.add("actors-mode");
144 // Ensure the first link is focused
145 let firstLink = parent.querySelector("a:first-of-type");
146 if (firstLink) {
147 firstLink.focus();
148 }
149 });
151 /**
152 * Build one button for an add-on actor.
153 */
154 function buildAddonLink(addon, parent) {
155 let a = document.createElement("a");
156 a.onclick = function() {
157 openToolbox({ addonActor: addon.actor, title: addon.name }, true, "jsdebugger");
158 }
160 a.textContent = addon.name;
161 a.title = addon.id;
162 a.href = "#";
164 parent.appendChild(a);
165 }
167 /**
168 * Build one button for a tab actor.
169 */
170 function buildTabLink(tab, parent, selected) {
171 let a = document.createElement("a");
172 a.onclick = function() {
173 openToolbox(tab);
174 }
176 a.textContent = tab.title;
177 a.title = tab.url;
178 if (!a.textContent) {
179 a.textContent = tab.url;
180 }
181 a.href = "#";
183 if (selected) {
184 a.classList.add("selected");
185 }
187 parent.appendChild(a);
188 }
190 /**
191 * An error occured. Let's show it and return to the first screen.
192 */
193 function showError(type) {
194 document.body.className = "error";
195 let activeError = document.querySelector(".error-message.active");
196 if (activeError) {
197 activeError.classList.remove("active");
198 }
199 activeError = document.querySelector(".error-" + type);
200 if (activeError) {
201 activeError.classList.add("active");
202 }
203 }
205 /**
206 * Connection timeout.
207 */
208 function handleConnectionTimeout() {
209 showError("timeout");
210 }
212 /**
213 * The user clicked on one of the buttons.
214 * Opens the toolbox.
215 */
216 function openToolbox(form, chrome=false, tool="webconsole") {
217 let options = {
218 form: form,
219 client: gClient,
220 chrome: chrome
221 };
222 devtools.TargetFactory.forRemoteTab(options).then((target) => {
223 let hostType = devtools.Toolbox.HostType.WINDOW;
224 gDevTools.showToolbox(target, tool, hostType).then((toolbox) => {
225 toolbox.once("destroyed", function() {
226 gClient.close();
227 });
228 });
229 window.close();
230 });
231 }