Bug 1078539 - Add a doorhanger widget for the developer edition notification to browser console, developer tools, webide and responsive design mode. r=jryans

This commit is contained in:
Jordan Santell 2014-10-22 17:18:31 -07:00
parent 7880585d9d
commit a181e76100
11 changed files with 302 additions and 0 deletions

View File

@ -1306,6 +1306,17 @@ pref("browser.devedition.theme.enabled", false);
pref("browser.devedition.theme.showCustomizeButton", false);
#endif
// Developer edition promo preferences
pref("devtools.devedition.promo.shown", false);
pref("devtools.devedition.promo.url", "https://mozilla.org/firefox/developer");
// Only potentially show in beta release
#ifdef MOZ_UPDATE_CHANNEL == beta
pref("devtools.devedition.promo.enabled", true);
#else
pref("devtools.devedition.promo.enabled", false);
#endif
// Disable the error console
pref("devtools.errorconsole.enabled", false);

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,74 @@
/* 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/. */
#doorhanger-container {
width: 450px;
}
#top-panel {
padding: 20px;
background: #343c45; /* toolbars */
color: #8fa1b2; /* body text */
font-size: 15px;
line-height: 19px;
min-height: 100px;
}
#top-panel h1 {
font-weight: bold;
font-family: Open Sans, sans-serif;
font-size: 1.1em;
}
#top-panel p {
font-family: Open Sans, sans-serif;
font-size: 0.9em;
width: 300px;
display: block;
margin: 5px 0px 0px 0px;
}
#icon {
background-image: url("chrome://browser/content/devtools/framework/dev-edition-logo.png");
background-size: 64px 64px;
background-repeat: no-repeat;
width: 64px;
height: 64px;
margin-right: 20px;
}
#lower-panel {
padding: 20px;
background-color: #252c33; /* tab toolbars */
min-height: 75px;
border-top: 1px solid #292e33; /* text high contrast (light) */
}
#button-container {
margin: auto 20px;
}
#button-container button {
font: message-box !important;
font-size: 16px !important;
cursor: pointer;
width: 125px;
opacity: 1;
position: static;
-moz-appearance: none;
border-radius: 5px;
height: 30px;
width: 450px;
}
#close {
background-color: transparent;
color: #8fa1b2; /* body text */
}
#go {
margin-left: 100px;
background-color: #70bf53; /* green */
color: #f5f7fa; /* selection text color */
}

View File

@ -0,0 +1,36 @@
<?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 window [
<!ENTITY % toolboxDTD SYSTEM "chrome://browser/locale/devtools/toolbox.dtd" >
%toolboxDTD;
]>
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
<?xml-stylesheet rel="stylesheet" href="chrome://browser/content/devtools/framework/dev-edition-promo.css" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="dev-edition-promo">
<vbox id="doorhanger-container">
<hbox flex="1" id="top-panel">
<image id="icon" />
<vbox id="info">
<h1>Using Developer Tools in your browser?</h1>
<p>Download Firefox Developer Edition, our first browser made just for you.</p>
</vbox>
</hbox>
<hbox id="lower-panel" flex="1">
<hbox id="button-container" flex="1">
<button id="close"
flex="1"
standalone="true"
label="No thanks">
</button>
<button id="go"
flex="1"
standalone="true"
label="Learn more »">
</button>
</hbox>
</hbox>
</vbox>
</window>

View File

@ -17,6 +17,7 @@ let EventEmitter = require("devtools/toolkit/event-emitter");
let Telemetry = require("devtools/shared/telemetry");
let {getHighlighterUtils} = require("devtools/framework/toolbox-highlighter-utils");
let HUDService = require("devtools/webconsole/hudservice");
let {showDoorhanger} = require("devtools/shared/doorhanger");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@ -100,6 +101,7 @@ function Toolbox(target, selectedTool, hostType, hostOptions) {
this._prefChanged = this._prefChanged.bind(this);
this._saveSplitConsoleHeight = this._saveSplitConsoleHeight.bind(this);
this._onFocus = this._onFocus.bind(this);
this._showDevEditionPromo = this._showDevEditionPromo.bind(this);
this._target.on("close", this.destroy);
@ -124,6 +126,8 @@ function Toolbox(target, selectedTool, hostType, hostOptions) {
this.on("host-changed", this._refreshHostTitle);
this.on("select", this._refreshHostTitle);
this.on("ready", this._showDevEditionPromo);
gDevTools.on("tool-registered", this._toolRegistered);
gDevTools.on("tool-unregistered", this._toolUnregistered);
}
@ -1649,5 +1653,18 @@ Toolbox.prototype = {
_highlighterHidden: function() {
this.emit("highlighter-hide");
},
/**
* For displaying the promotional Doorhanger on first opening of
* the developer tools, promoting the Developer Edition.
*/
_showDevEditionPromo: function() {
// Do not display in browser toolbox
if (this.target.chrome) {
return;
}
let window = this.frame.contentWindow;
showDoorhanger({ window, type: "deveditionpromo" });
}
};

View File

@ -103,6 +103,9 @@ browser.jar:
content/browser/devtools/framework/options-panel.css (framework/options-panel.css)
content/browser/devtools/framework/toolbox-process-window.xul (framework/toolbox-process-window.xul)
content/browser/devtools/framework/toolbox-process-window.js (framework/toolbox-process-window.js)
content/browser/devtools/framework/dev-edition-promo.xul (framework/dev-edition-promo/dev-edition-promo.xul)
content/browser/devtools/framework/dev-edition-promo.css (framework/dev-edition-promo/dev-edition-promo.css)
content/browser/devtools/framework/dev-edition-logo.png (framework/dev-edition-promo/dev-edition-logo.png)
content/browser/devtools/inspector/inspector.xul (inspector/inspector.xul)
content/browser/devtools/inspector/inspector.css (inspector/inspector.css)
content/browser/devtools/connect.xhtml (framework/connect/connect.xhtml)

View File

@ -17,6 +17,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
var require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
let Telemetry = require("devtools/shared/telemetry");
let {showDoorhanger} = require("devtools/shared/doorhanger");
let {TouchEventHandler} = require("devtools/touch-events");
this.EXPORTED_SYMBOLS = ["ResponsiveUIManager"];
@ -217,6 +218,13 @@ function ResponsiveUI(aWindow, aTab)
// E10S: We should be using target here. See bug 1028234
ResponsiveUIManager.emit("on", { tab: this.tab });
// Hook to display promotional Developer Edition doorhanger. Only displayed once.
showDoorhanger({
window: this.mainWindow,
type: "deveditionpromo",
anchor: this.chromeDoc.querySelector("#content")
});
}
ResponsiveUI.prototype = {

View File

@ -0,0 +1,144 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Ci, Cc } = require("chrome");
const { Services } = require("resource://gre/modules/Services.jsm");
const { DOMHelpers } = require("resource:///modules/devtools/DOMHelpers.jsm");
const { Task } = require("resource://gre/modules/Task.jsm");
const { Promise } = require("resource://gre/modules/Promise.jsm");
const { getMostRecentBrowserWindow } = require("sdk/window/utils");
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const DEV_EDITION_PROMO_URL = "chrome://browser/content/devtools/framework/dev-edition-promo.xul";
const DEV_EDITION_PROMO_ENABLED_PREF = "devtools.devedition.promo.enabled";
const DEV_EDITION_PROMO_SHOWN_PREF = "devtools.devedition.promo.shown";
const DEV_EDITION_PROMO_URL_PREF = "devtools.devedition.promo.url";
const LOCALE = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.getSelectedLocale("global");
/**
* Only show Dev Edition promo if it's enabled (beta channel),
* if it has not been shown before, and it's a locale build
* for `en-US`
*/
function shouldDevEditionPromoShow () {
return Services.prefs.getBoolPref(DEV_EDITION_PROMO_ENABLED_PREF) &&
!Services.prefs.getBoolPref(DEV_EDITION_PROMO_SHOWN_PREF) &&
LOCALE === "en-US";
}
let TYPES = {
// The Developer Edition promo doorhanger, called by
// opening the toolbox, browser console, WebIDE, or responsive design mode
// in Beta releases. Only displayed once per profile.
deveditionpromo: {
predicate: shouldDevEditionPromoShow,
success: () => Services.prefs.setBoolPref(DEV_EDITION_PROMO_SHOWN_PREF, true),
action: () => {
let url = Services.prefs.getCharPref(DEV_EDITION_PROMO_URL_PREF);
getGBrowser().selectedTab = getGBrowser().addTab(url);
},
url: DEV_EDITION_PROMO_URL
}
};
let panelAttrs = {
orient: "vertical",
hidden: "false",
consumeoutsideclicks: "true",
noautofocus: "true",
align: "start",
role: "alert"
};
/**
* Helper to call a doorhanger, defined in `TYPES`, with defined conditions,
* success handlers and loads its own XUL in a frame. Takes an object with
* several properties:
*
* @param {XULWindow} window
* The window that should house the doorhanger.
* @param {String} type
* The type of doorhanger to be displayed is, using the `TYPES` definition.
* @param {String} selector
* The selector that the doorhanger should be appended to within `window`.
* Defaults to a XUL Document's `window` element.
*/
exports.showDoorhanger = Task.async(function *({ window, type, anchor }) {
let { predicate, success, url, action } = TYPES[type];
// Abort if predicate fails
if (!predicate()) {
return;
}
let document = window.document;
let panel = document.createElementNS(XULNS, "panel");
let frame = document.createElementNS(XULNS, "iframe");
let parentEl = document.querySelector("window");
frame.setAttribute("src", url);
let close = () => parentEl.removeChild(panel);
setDoorhangerStyle(panel, frame);
panel.appendChild(frame);
parentEl.appendChild(panel);
yield onFrameLoad(frame);
panel.openPopup(anchor);
let closeBtn = frame.contentDocument.querySelector("#close");
if (closeBtn) {
closeBtn.addEventListener("click", close);
}
let goBtn = frame.contentDocument.querySelector("#go");
if (goBtn) {
goBtn.addEventListener("click", () => {
if (action) {
action();
}
close();
});
}
// Call success function to set preferences, etc.
success();
});
function setDoorhangerStyle (panel, frame) {
Object.keys(panelAttrs).forEach(prop => panel.setAttribute(prop, panelAttrs[prop]));
panel.style.margin = "20px";
panel.style.borderRadius = "5px";
frame.style.borderRadius = "5px";
frame.setAttribute("flex", "1");
frame.setAttribute("width", "450");
frame.setAttribute("height", "179");
}
function onFrameLoad (frame) {
let { resolve, promise } = Promise.defer();
if (frame.contentWindow) {
let domHelper = new DOMHelpers(frame.contentWindow);
domHelper.onceDOMReady(resolve);
} else {
let callback = () => {
frame.removeEventListener("DOMContentLoaded", callback);
resolve();
}
frame.addEventListener("DOMContentLoaded", callback);
}
return promise;
}
function getGBrowser () {
return getMostRecentBrowserWindow().gBrowser;
}

View File

@ -33,6 +33,7 @@ EXTRA_JS_MODULES.devtools += [
EXTRA_JS_MODULES.devtools.shared += [
'autocomplete-popup.js',
'd3.js',
'doorhanger.js',
'frame-script-utils.js',
'inplace-editor.js',
'observable-object.js',

View File

@ -19,6 +19,7 @@ loader.lazyImporter(this, "devtools", "resource://gre/modules/devtools/Loader.js
loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
loader.lazyImporter(this, "DebuggerServer", "resource://gre/modules/devtools/dbg-server.jsm");
loader.lazyImporter(this, "DebuggerClient", "resource://gre/modules/devtools/dbg-client.jsm");
loader.lazyGetter(this, "showDoorhanger", () => require("devtools/shared/doorhanger").showDoorhanger);
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
@ -713,6 +714,9 @@ BrowserConsole.prototype = Heritage.extend(WebConsole.prototype,
this._telemetry.toolOpened("browserconsole");
// Hook to display promotional Developer Edition doorhanger. Only displayed once.
showDoorhanger({ window, type: "deveditionpromo" });
this._bc_init = this.$init();
return this._bc_init;
},

View File

@ -23,6 +23,7 @@ const {GetTemplatesJSON, GetAddonsJSON} = require("devtools/webide/remote-resour
const utils = require("devtools/webide/utils");
const Telemetry = require("devtools/shared/telemetry");
const {RuntimeScanners, WiFiScanner} = require("devtools/webide/runtimes");
const {showDoorhanger} = require("devtools/shared/doorhanger");
const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/webide.properties");
@ -96,6 +97,9 @@ let UI = {
}
this.setupDeck();
// Hook to display promotional Developer Edition doorhanger. Only displayed once.
showDoorhanger({ window, type: "deveditionpromo", anchor: document.querySelector("#deck") });
},
uninit: function() {