Bug 817537 - Connection screen polish. r=vporof

This commit is contained in:
Paul Rouget 2012-12-18 08:54:00 +01:00
parent 1e81321e2e
commit 6eec3f0ef3
13 changed files with 253 additions and 121 deletions

View File

@ -165,7 +165,6 @@
observes="devtoolsMenuBroadcaster_PageSource"/>
<menuitem id="appmenu_errorConsole"
observes="devtoolsMenuBroadcaster_ErrorConsole"/>
<menuseparator id="appmenu_devToolsConnectSeparator"/>
<menuitem id="appmenu_devtools_connect"
observes="devtoolsMenuBroadcaster_connect"/>
<menuseparator id="appmenu_devToolsEndSeparator"/>

View File

@ -584,7 +584,6 @@
<menuitem id="javascriptConsole"
observes="devtoolsMenuBroadcaster_ErrorConsole"
accesskey="&errorConsoleCmd.accesskey;"/>
<menuseparator id="menu_devToolsConnectSeparator"/>
<menuitem id="menu_devtools_connect"
observes="devtoolsMenuBroadcaster_connect"/>
<menuseparator id="devToolsEndSeparator"/>

View File

@ -97,7 +97,7 @@
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true" hidden="true"/>
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
<command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/>
<command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)"/>
<command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)" disabled="true" hidden="true"/>
<command id="Tools:Sanitize"
oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
<command id="Tools:PrivateBrowsing"

View File

@ -1444,6 +1444,14 @@ var gBrowserInit = {
cmd.removeAttribute("hidden");
}
// Enable DevTools connection screen, if the preference allows this.
let devtoolsRemoteEnabled = gPrefService.getBoolPref("devtools.debugger.remote-enabled");
if (devtoolsRemoteEnabled) {
let cmd = document.getElementById("Tools:DevToolsConnect");
cmd.removeAttribute("disabled");
cmd.removeAttribute("hidden");
}
#ifdef MENUBAR_CAN_AUTOHIDE
// If the user (or the locale) hasn't enabled the top-level "Character
// Encoding" menu via the "browser.menu.showCharacterEncoding" preference,

View File

@ -1,14 +1,25 @@
html {
background: url("chrome://browser/skin/newtab/noise.png");
background-color: #111;
background-image: url("chrome://browser/skin/newtab/noise.png");
}
body {
font-family: Arial;
padding: 20px;
border-radius: 3px;
font-family: Arial, sans-serif;
color: white;
max-width: 600px;
min-height: 400px;
margin: 10px auto 0;
margin: 30px auto 0;
box-shadow: 0 2px 3px black;
background-color: #3C3E40;
}
h1 {
margin: 0;
padding: 20px;
background-color: rgba(0,0,0,0.12);
background-image: radial-gradient(ellipse farthest-corner at center top , rgb(159, 223, 255), rgba(101, 203, 255, 0.3)), radial-gradient(ellipse farthest-side at center top , rgba(101, 203, 255, 0.4), rgba(101, 203, 255, 0));
background-size: 100% 2px, 100% 5px;
background-repeat: no-repeat;
border-bottom: 1px solid rgba(0,0,0,0.1);
}
label {
@ -29,18 +40,21 @@ label > span {
margin-left: 160px;
}
#actors, #connection-form {
margin: 20px;
input:invalid {
box-shadow: 0 0 2px 2px #F06;
}
input {
border: 1px solid grey;
section {
min-height: 160px;
margin: 60px 20px;
display: none; /* By default, hidden */
}
#connection-form,
#connecting,
#actors-list {
.error-message {
color: red;
}
.error-message:not(.active) {
display: none;
}
@ -60,20 +74,9 @@ body.connecting > #connecting {
text-align: center;
}
#throbber {
height: 7px; width: 7px;
border-radius: 50%;
background: black;
display: inline-block;
animation-duration: 0.6s;
animation-name: anim;
animation-direction: alternate;
animation-iteration-count: infinite;
animation-timing-function: linear;
#connecting > p > img {
vertical-align: top;
}
@keyframes anim {to {
transform: scale(0.5) rotate(0.1deg);
}}
#actors {
padding-left: 0;
@ -84,4 +87,22 @@ body.connecting > #connecting {
display: block;
margin: 5px;
padding: 5px;
color: white;
}
.remote-process {
font-style: italic;
opacity: 0.8;
}
footer {
padding: 10px;
background-color: rgba(0,0,0,0.12);
border-top: 1px solid rgba(0,0,0,0.1);
font-size: small;
}
footer > a,
footer > a:visited {
color: white;
}

View File

@ -10,91 +10,158 @@ const Cu = Components.utils;
Cu.import("resource:///modules/devtools/Target.jsm");
Cu.import("resource:///modules/devtools/Toolbox.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
let gClient;
let gConnectionTimeout;
XPCOMUtils.defineLazyGetter(window, 'l10n', function () {
return Services.strings.createBundle('chrome://browser/locale/devtools/connection-screen.properties');
});
/**
* Once DOM is ready, we prefil the host/port inputs with
* pref-stored values.
*/
window.addEventListener("DOMContentLoaded", function onDOMReady() {
window.removeEventListener("DOMContentLoaded", onDOMReady, true);
let host = Services.prefs.getCharPref("devtools.debugger.remote-host");
let port = Services.prefs.getIntPref("devtools.debugger.remote-port");
if (host) {
document.getElementById("host").value = host;
}
if (port) {
document.getElementById("port").value = port;
}
}, true);
/**
* Called when the "connect" button is clicked.
*/
function submit() {
// Show the "connecting" screen
document.body.classList.add("connecting");
// Save the host/port values
let host = document.getElementById("host").value;
Services.prefs.setCharPref("devtools.debugger.remote-host", host);
let port = document.getElementById("port").value;
if (!host) {
host = Services.prefs.getCharPref("devtools.debugger.remote-host");
} else {
Services.prefs.setCharPref("devtools.debugger.remote-host", host);
}
if (!port) {
port = Services.prefs.getIntPref("devtools.debugger.remote-port");
} else {
Services.prefs.setIntPref("devtools.debugger.remote-port", port);
}
Services.prefs.setIntPref("devtools.debugger.remote-port", port);
// Initiate the connection
let transport = debuggerSocketConnect(host, port);
let client = gClient = new DebuggerClient(transport);
gClient = new DebuggerClient(transport);
let delay = Services.prefs.getIntPref("devtools.debugger.remote-timeout");
gConnectionTimeout = setTimeout(handleConnectionTimeout, delay);
gClient.connect(onConnectionReady);
}
client.connect(function(aType, aTraits) {
client.listTabs(function(aResponse) {
document.body.classList.remove("connecting");
document.body.classList.add("actors-mode");
/**
* Connection is ready. List actors and build buttons.
*/
function onConnectionReady(aType, aTraits) {
clearTimeout(gConnectionTimeout);
gClient.listTabs(function(aResponse) {
document.body.classList.remove("connecting");
document.body.classList.add("actors-mode");
let parent = document.getElementById("actors");
let focusSet = false;
let parent = document.getElementById("actors");
// Add Global Process debugging...
let globals = JSON.parse(JSON.stringify(aResponse));
delete globals.tabs;
delete globals.selected;
// ...only if there are appropriate actors (a 'from' property will always
// be there).
if (Object.keys(globals).length > 1) {
let a = document.createElement("a");
a.onclick = function() {
connect(globals, true);
}
// Add Global Process debugging...
let globals = JSON.parse(JSON.stringify(aResponse));
delete globals.tabs;
delete globals.selected;
// ...only if there are appropriate actors (a 'from' property will always
// be there).
a.title = a.textContent = "Remote process";
a.href = "#";
// Add one entry for each open tab.
for (let i = 0; i < aResponse.tabs.length; i++) {
buildLink(aResponse.tabs[i], parent, i == aResponse.selected);
}
// Build the Remote Process button
if (Object.keys(globals).length > 1) {
let a = document.createElement("a");
a.onclick = function() {
openToolbox(globals, true);
parent.appendChild(a);
}
a.title = a.textContent = window.l10n.GetStringFromName("remoteProcess");
a.className = "remote-process";
a.href = "#";
parent.appendChild(a);
}
// Move the selected tab on top
let selectedLink = parent.querySelector("a.selected");
if (selectedLink) {
parent.insertBefore(selectedLink, parent.firstChild);
}
// Add one entry for each open tab.
if (aResponse.tabs.length > 0) {
let header = document.createElement("div");
header.innerHTML = "Tabs:";
parent.appendChild(header);
}
for (let i = 0; i < aResponse.tabs.length; i++) {
let tab = aResponse.tabs[i];
// Ensure the first link is focused
let firstLink = parent.querySelector("a:first-of-type");
if (firstLink) {
firstLink.focus();
}
let a = document.createElement("a");
a.onclick = function() {
connect(tab);
}
a.title = a.textContent = tab.title;
a.href = "#";
if (i == aResponse.selected) {
a.title += " [*]";
a.textContent = a.title;
}
parent.appendChild(a);
if (!focusSet) {
a.focus();
focusSet = true;
}
}
});
});
}
function connect(form, chrome=false) {
/**
* Build one button for an actor.
*/
function buildLink(tab, parent, selected) {
let a = document.createElement("a");
a.onclick = function() {
openToolbox(tab);
}
a.textContent = tab.title;
a.title = tab.url;
if (!a.textContent) {
a.textContent = tab.url;
}
a.href = "#";
if (selected) {
a.classList.add("selected");
}
parent.appendChild(a);
}
/**
* An error occured. Let's show it and return to the first screen.
*/
function showError(type) {
document.body.className = "error";
let activeError = document.querySelector(".error-message.active");
if (activeError) {
activeError.classList.remove("active");
}
activeError = document.querySelector(".error-" + type);
if (activeError) {
activeError.classList.add("active");
}
}
/**
* Connection timeout.
*/
function handleConnectionTimeout() {
showError("timeout");
}
/**
* The user clicked on one of the buttons.
* Opens the toolbox.
*/
function openToolbox(form, chrome=false) {
let target = TargetFactory.forRemote(form, gClient, chrome);
gDevTools.showToolbox(target, "webconsole", Toolbox.HostType.WINDOW);
window.close();
}

View File

@ -12,34 +12,37 @@
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<head>
<title>&title;</title>
<link rel="stylesheet" href="chrome://browser/skin/devtools/common.css" type="text/css"/>
<link rel="stylesheet" href="chrome://browser/content/devtools/connect.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="connect.js"></script>
</head>
<body>
<p>
</p>
<h1>&header;</h1>
<section id="connection-form">
<form onsubmit="window.submit()" action="#">
<form validate="validate" onsubmit="window.submit()" action="#">
<label>
<span>&host;</span>
<input id="host" type="text" placeholder="localhost"></input>
<input required="required" class="devtools-textinput" id="host" type="text"></input>
</label>
<label>
<span>&port;</span>
<input id="port" type="number" placeholder="6000"></input>
<input required="required" class="devtools-textinput" id="port" type="number" pattern="\d+"></input>
</label>
<label>
<input id="submit" type="submit" value="&connect;"></input>
<input class="devtools-toolbarbutton" id="submit" type="submit" value="&connect;"></input>
</label>
</form>
<p class="error-message error-timeout">&errorTimeout;</p>
<p class="error-message error-refused">&errorRefused;</p>
<p class="error-message error-unexpected">&errorUnexpected;</p>
</section>
<section id="actors-list">
<p>&availability;</p>
<ul id="actors"></ul>
</section>
<section id="connecting">
<p>&connecting;</p>
<div id="throbber"></div>
<p><img src="chrome://browser/skin/tabbrowser/loading.png"></img> &connecting;</p>
</section>
<footer>&help;</footer>
</body>
</html>

View File

@ -2,14 +2,21 @@
- 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/. -->
<!-- LOCALIZATION NOTE : FILE This file contains the Remove Connection strings.
- The Remote Connection window can be start by running the command:
- `devtools connect`
<!-- LOCALIZATION NOTE : FILE This file contains the Remote Connection strings.
- The Remote Connection window can reached from the "connect…" menuitem
- in the Web Developer menu.
- -->
<!ENTITY title "Connect">
<!ENTITY header "Connect to remote device">
<!ENTITY host "Host:">
<!ENTITY port "Port:">
<!ENTITY connect "Connect">
<!ENTITY connecting "Connecting…">
<!ENTITY availability "Available remote objects:">
<!ENTITY remoteProcess "remote process">
<!ENTITY connectionError "Error:">
<!ENTITY errorTimeout "Error: connection timeout.">
<!ENTITY errorRefused "Error: connection refused.">
<!ENTITY errorUnexpected "Unexpected error.">
<!ENTITY help "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS for example). Make sure that you have turned on the 'Debugger Server' option on the remote device. See <a target='_' href='https://developer.mozilla.org/en-US/docs/Tools/Debugger#Remote_Debugging'>documentation</a>.">

View File

@ -0,0 +1,9 @@
# 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/.
# LOCALIZATION NOTE : FILE This file contains the Remote Connection strings.
# The Remote Connection window can reached from the "connect…" menuitem
# in the Web Developer menu.
remoteProcess=Remote Process

View File

@ -41,6 +41,7 @@
locale/browser/devtools/toolbox.dtd (%chrome/browser/devtools/toolbox.dtd)
locale/browser/devtools/inspector.dtd (%chrome/browser/devtools/inspector.dtd)
locale/browser/devtools/connection-screen.dtd (%chrome/browser/devtools/connection-screen.dtd)
locale/browser/devtools/connection-screen.properties (%chrome/browser/devtools/connection-screen.properties)
locale/browser/newTab.dtd (%chrome/browser/newTab.dtd)
locale/browser/newTab.properties (%chrome/browser/newTab.properties)
locale/browser/openLocation.dtd (%chrome/browser/openLocation.dtd)

View File

@ -128,27 +128,33 @@
margin: 0 3px;
}
/* Search input */
/* Text input */
.devtools-textinput,
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
border: 1px solid hsla(210,8%,5%,.6);
border-radius: 2px;
background-color: transparent;
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-repeat: no-repeat;
background-position: 4px center, top left, top left;
padding-top: 0;
padding-bottom: 0;
-moz-padding-start: 18px;
-moz-padding-end: 12px;
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
padding: 3px;
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
0 0 0 1px hsla(210,16%,76%,.1) inset,
0 1px 0 hsla(210,16%,76%,.15);
color: inherit;
}
.devtools-searchinput {
padding-top: 0;
padding-bottom: 0;
-moz-padding-start: 18px;
-moz-padding-end: 12px;
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-position: 4px center, top left, top left;
background-repeat: no-repeat;
}
.devtools-searchinput:-moz-locale-dir(rtl) {
background-position: calc(100% - 4px) center, top left, top left;
}

View File

@ -134,14 +134,24 @@
border: 0;
}
/* Search input */
/* Text input */
.devtools-textinput,
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
background-color: transparent;
border: 1px solid hsla(210,8%,5%,.6);
border-radius: 20px;
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
padding: 3px;
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
0 0 0 1px hsla(210,16%,76%,.1) inset,
0 1px 0 hsla(210,16%,76%,.15);
color: inherit;
}
.devtools-searchinput {
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-repeat: no-repeat;
background-position: 4px center, top left, top left;
@ -149,10 +159,6 @@
padding-bottom: 0;
-moz-padding-start: 18px;
-moz-padding-end: 12px;
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
0 0 0 1px hsla(210,16%,76%,.1) inset,
0 1px 0 hsla(210,16%,76%,.15);
color: inherit;
}
.devtools-searchinput:-moz-locale-dir(rtl) {

View File

@ -132,8 +132,9 @@
-moz-box-align: center;
}
/* Search input */
/* Text input */
.devtools-textinput,
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
@ -141,6 +142,15 @@
box-shadow: inset 0 1px 0 hsla(211,68%,6%,.05), 0 0 0 1px hsla(210,40%,83%,.1);
border-radius: 2px;
background-color: transparent;
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
padding: 3px;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease;
color: inherit;
}
.devtools-searchinput {
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
background-repeat: no-repeat;
background-position: 4px center, top left, top left;
@ -148,10 +158,6 @@
padding-bottom: 0;
-moz-padding-start: 18px;
-moz-padding-end: 12px;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease;
color: inherit;
}
.devtools-searchinput[focused] {