Bug 1239437 - Add a basic viewport frame. r=pbrosset

This commit is contained in:
J. Ryan Stinnett 2016-01-22 15:11:10 -06:00
parent a8561e25d9
commit dd55540fd1
4 changed files with 118 additions and 5 deletions

View File

@ -145,6 +145,8 @@ devtools.jar:
content/aboutdebugging/aboutdebugging.xhtml (aboutdebugging/aboutdebugging.xhtml)
content/aboutdebugging/aboutdebugging.css (aboutdebugging/aboutdebugging.css)
content/aboutdebugging/aboutdebugging.js (aboutdebugging/aboutdebugging.js)
content/responsive.html/index.xhtml (responsive.html/index.xhtml)
content/responsive.html/index.js (responsive.html/index.js)
% skin devtools classic/1.0 %skin/
skin/devtools-browser.css (themes/devtools-browser.css)
skin/common.css (themes/common.css)

View File

@ -0,0 +1,17 @@
/* 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/. */
/* eslint-env browser */
"use strict";
window.addViewport = contentURI => {
try {
let frame = document.createElement("iframe");
frame.setAttribute("src", contentURI);
document.body.appendChild(frame);
} catch (e) {
console.error(e);
}
};

View File

@ -0,0 +1,18 @@
<?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>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css"
href="chrome://devtools/skin/common.css"/>
<script type="application/javascript;version=1.8"
src="chrome://devtools/content/shared/theme-switching.js"></script>
<script type="application/javascript;version=1.8"
src="./index.js"></script>
</head>
<body class="theme-body" role="application">
</body>
</html>

View File

@ -5,8 +5,11 @@
"use strict";
const promise = require("promise");
const { Task } = require("resource://gre/modules/Task.jsm");
const EventEmitter = require("devtools/shared/event-emitter");
const TOOL_URL = "chrome://devtools/content/responsive.html/index.xhtml";
/**
* ResponsiveUIManager is the external API for the browser UI, etc. to use when
* opening and closing the responsive UI.
@ -30,7 +33,8 @@ exports.ResponsiveUIManager = {
*/
toggle(window, tab) {
if (this.isActiveForTab(tab)) {
this.activeTabs.get(tab).close();
this.activeTabs.get(tab).destroy();
this.activeTabs.delete(tab);
} else {
this.runIfNeeded(window, tab);
}
@ -48,7 +52,7 @@ exports.ResponsiveUIManager = {
*/
runIfNeeded(window, tab) {
if (!this.isActiveForTab(tab)) {
// TODO: Unimplemented
this.activeTabs.set(tab, new ResponsiveUI(window, tab));
}
},
@ -68,7 +72,8 @@ exports.ResponsiveUIManager = {
*
* @param tab
* The browser tab.
* @return TODO: Some object!
* @return ResponsiveUI
* The UI instance for this tab.
*/
getResponsiveUIForTab(tab) {
return this.activeTabs.get(tab);
@ -98,8 +103,8 @@ exports.ResponsiveUIManager = {
break;
case "resize off":
if (this.isActiveForTab(tab)) {
// TODO: Probably the wrong API
this.activeTabs.get(tab).close();
this.activeTabs.get(tab).destroy();
this.activeTabs.delete(tab);
}
break;
case "resize toggle":
@ -113,3 +118,74 @@ exports.ResponsiveUIManager = {
// GCLI commands in ../responsivedesign/resize-commands.js listen for events
// from this object to know when the UI for a tab has opened or closed.
EventEmitter.decorate(exports.ResponsiveUIManager);
/**
* ResponsiveUI manages the responsive design tool for a specific tab. The
* actual tool itself lives in a separate chrome:// document that is loaded into
* the tab upon opening responsive design. This object acts a helper to
* integrate the tool into the surrounding browser UI as needed.
*/
function ResponsiveUI(window, tab) {
this.window = window;
this.tab = tab;
this.init();
}
ResponsiveUI.prototype = {
/**
* The main browser chrome window (that holds many tabs).
*/
window: null,
/**
* The specific browser tab this responsive instance is for.
*/
tab: null,
/**
* For the moment, we open the tool by:
* 1. Recording the tab's URL
* 2. Navigating the tab to the tool
* 3. Passing along the URL to the tool to open in the viewport
*
* This approach is simple, but it also discards the user's state on the page.
* It's just like opening a fresh tab and pasting the URL.
*
* In the future, we can do better by using swapFrameLoaders to preserve the
* state. Platform discussions are in progress to make this happen. See
* bug 1238160 about <iframe mozbrowser> for more details.
*/
init: Task.async(function*() {
let tabBrowser = this.tab.linkedBrowser;
let contentURI = tabBrowser.documentURI.spec;
tabBrowser.loadURI(TOOL_URL);
yield tabLoaded(this.tab);
let toolWindow = tabBrowser.contentWindow;
toolWindow.addViewport(contentURI);
}),
destroy() {
let tabBrowser = this.tab.linkedBrowser;
tabBrowser.goBack();
this.window = null;
this.tab = null;
},
};
function tabLoaded(tab) {
let deferred = promise.defer();
function handle(event) {
if (event.originalTarget != tab.linkedBrowser.contentDocument ||
event.target.location.href == "about:blank") {
return;
}
tab.linkedBrowser.removeEventListener("load", handle, true);
deferred.resolve(event);
}
tab.linkedBrowser.addEventListener("load", handle, true);
return deferred.promise;
}