Files
tubestation/devtools/client/responsive.html/components/browser.js
J. Ryan Stinnett 1604814567 Bug 1353045 - Remove SDK usage from RDM. r=pbro
MozReview-Commit-ID: I2dodBb9NHh
2017-04-06 21:42:21 -05:00

151 lines
5.1 KiB
JavaScript

/* 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";
const { Task } = require("devtools/shared/task");
const flags = require("devtools/shared/flags");
const { getToplevelWindow } = require("../utils/window");
const { DOM: dom, createClass, addons, PropTypes } =
require("devtools/client/shared/vendor/react");
const Types = require("../types");
const e10s = require("../utils/e10s");
const message = require("../utils/message");
module.exports = createClass({
/**
* This component is not allowed to depend directly on frequently changing
* data (width, height) due to the use of `dangerouslySetInnerHTML` below.
* Any changes in props will cause the <iframe> to be removed and added again,
* throwing away the current state of the page.
*/
displayName: "Browser",
propTypes: {
location: Types.location.isRequired,
swapAfterMount: PropTypes.bool.isRequired,
onBrowserMounted: PropTypes.func.isRequired,
onContentResize: PropTypes.func.isRequired,
},
mixins: [ addons.PureRenderMixin ],
/**
* Once the browser element has mounted, load the frame script and enable
* various features, like floating scrollbars.
*/
componentDidMount: Task.async(function* () {
// If we are not swapping browsers after mount, it's safe to start the frame
// script now.
if (!this.props.swapAfterMount) {
yield this.startFrameScript();
}
// Notify manager.js that this browser has mounted, so that it can trigger
// a swap if needed and continue with the rest of its startup.
this.props.onBrowserMounted();
// If we are swapping browsers after mount, wait for the swap to complete
// and start the frame script after that.
if (this.props.swapAfterMount) {
yield message.wait(window, "start-frame-script");
yield this.startFrameScript();
message.post(window, "start-frame-script:done");
}
// Stop the frame script when requested in the future.
message.wait(window, "stop-frame-script").then(() => {
this.stopFrameScript();
});
}),
onContentResize(msg) {
let { onContentResize } = this.props;
let { width, height } = msg.data;
onContentResize({
width,
height,
});
},
startFrameScript: Task.async(function* () {
let { onContentResize } = this;
let browser = this.refs.browserContainer.querySelector("iframe.browser");
let mm = browser.frameLoader.messageManager;
// Notify tests when the content has received a resize event. This is not
// quite the same timing as when we _set_ a new size around the browser,
// since it still needs to do async work before the content is actually
// resized to match.
e10s.on(mm, "OnContentResize", onContentResize);
let ready = e10s.once(mm, "ChildScriptReady");
mm.loadFrameScript("resource://devtools/client/responsivedesign/" +
"responsivedesign-child.js", true);
yield ready;
let browserWindow = getToplevelWindow(window);
let requiresFloatingScrollbars =
!browserWindow.matchMedia("(-moz-overlay-scrollbars)").matches;
yield e10s.request(mm, "Start", {
requiresFloatingScrollbars,
// Tests expect events on resize to yield on various size changes
notifyOnResize: flags.testing,
});
}),
stopFrameScript: Task.async(function* () {
let { onContentResize } = this;
let browser = this.refs.browserContainer.querySelector("iframe.browser");
let mm = browser.frameLoader.messageManager;
e10s.off(mm, "OnContentResize", onContentResize);
yield e10s.request(mm, "Stop");
message.post(window, "stop-frame-script:done");
}),
render() {
let {
location,
} = this.props;
// innerHTML expects & to be an HTML entity
location = location.replace(/&/g, "&amp;");
return dom.div(
{
ref: "browserContainer",
className: "browser-container",
/**
* React uses a whitelist for attributes, so we need some way to set
* attributes it does not know about, such as @mozbrowser. If this were
* the only issue, we could use componentDidMount or ref: node => {} to
* set the atttibutes. In the case of @remote and @remoteType, the
* attribute must be set before the element is added to the DOM to have
* any effect, which we are able to do with this approach.
*
* @noisolation and @allowfullscreen are needed so that these frames
* have the same access to browser features as regular browser tabs.
* The `swapFrameLoaders` platform API we use compares such features
* before allowing the swap to proceed.
*/
dangerouslySetInnerHTML: {
__html: `<iframe class="browser" mozbrowser="true"
remote="true" remoteType="web"
noisolation="true" allowfullscreen="true"
src="${location}" width="100%" height="100%">
</iframe>`
}
}
);
},
});