diff options
Diffstat (limited to 'devtools/client/responsive.html/index.js')
-rw-r--r-- | devtools/client/responsive.html/index.js | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/devtools/client/responsive.html/index.js b/devtools/client/responsive.html/index.js new file mode 100644 index 000000000..7e8f8aeac --- /dev/null +++ b/devtools/client/responsive.html/index.js @@ -0,0 +1,166 @@ +/* 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 { utils: Cu } = Components; +const { BrowserLoader } = + Cu.import("resource://devtools/client/shared/browser-loader.js", {}); +const { require } = BrowserLoader({ + baseURI: "resource://devtools/client/responsive.html/", + window +}); +const { Task } = require("devtools/shared/task"); +const Telemetry = require("devtools/client/shared/telemetry"); +const { loadSheet } = require("sdk/stylesheet/utils"); + +const { createFactory, createElement } = + require("devtools/client/shared/vendor/react"); +const ReactDOM = require("devtools/client/shared/vendor/react-dom"); +const { Provider } = require("devtools/client/shared/vendor/react-redux"); + +const message = require("./utils/message"); +const App = createFactory(require("./app")); +const Store = require("./store"); +const { changeLocation } = require("./actions/location"); +const { changeDisplayPixelRatio } = require("./actions/display-pixel-ratio"); +const { addViewport, resizeViewport } = require("./actions/viewports"); +const { loadDevices } = require("./actions/devices"); + +// Exposed for use by tests +window.require = require; + +let bootstrap = { + + telemetry: new Telemetry(), + + store: null, + + init: Task.async(function* () { + // Load a special UA stylesheet to reset certain styles such as dropdown + // lists. + loadSheet(window, + "resource://devtools/client/responsive.html/responsive-ua.css", + "agent"); + this.telemetry.toolOpened("responsive"); + let store = this.store = Store(); + let provider = createElement(Provider, { store }, App()); + ReactDOM.render(provider, document.querySelector("#root")); + message.post(window, "init:done"); + }), + + destroy() { + this.store = null; + this.telemetry.toolClosed("responsive"); + this.telemetry = null; + }, + + /** + * While most actions will be dispatched by React components, some external + * APIs that coordinate with the larger browser UI may also have actions to + * to dispatch. They can do so here. + */ + dispatch(action) { + if (!this.store) { + // If actions are dispatched after store is destroyed, ignore them. This + // can happen in tests that close the tool quickly while async tasks like + // initDevices() below are still pending. + return; + } + this.store.dispatch(action); + }, + +}; + +// manager.js sends a message to signal init +message.wait(window, "init").then(() => bootstrap.init()); + +// manager.js sends a message to signal init is done, which can be used for delayed +// startup work that shouldn't block initial load +message.wait(window, "post-init").then(() => bootstrap.dispatch(loadDevices())); + +window.addEventListener("unload", function onUnload() { + window.removeEventListener("unload", onUnload); + bootstrap.destroy(); +}); + +// Allows quick testing of actions from the console +window.dispatch = action => bootstrap.dispatch(action); + +// Expose the store on window for testing +Object.defineProperty(window, "store", { + get: () => bootstrap.store, + enumerable: true, +}); + +// Dispatch a `changeDisplayPixelRatio` action when the browser's pixel ratio is changing. +// This is usually triggered when the user changes the monitor resolution, or when the +// browser's window is dragged to a different display with a different pixel ratio. +function onDPRChange() { + let dpr = window.devicePixelRatio; + let mql = window.matchMedia(`(resolution: ${dpr}dppx)`); + + function listener() { + bootstrap.dispatch(changeDisplayPixelRatio(window.devicePixelRatio)); + mql.removeListener(listener); + onDPRChange(); + } + + mql.addListener(listener); +} + +/** + * Called by manager.js to add the initial viewport based on the original page. + */ +window.addInitialViewport = contentURI => { + try { + onDPRChange(); + bootstrap.dispatch(changeLocation(contentURI)); + bootstrap.dispatch(changeDisplayPixelRatio(window.devicePixelRatio)); + bootstrap.dispatch(addViewport()); + } catch (e) { + console.error(e); + } +}; + +/** + * Called by manager.js when tests want to check the viewport size. + */ +window.getViewportSize = () => { + let { width, height } = bootstrap.store.getState().viewports[0]; + return { width, height }; +}; + +/** + * Called by manager.js to set viewport size from tests, GCLI, etc. + */ +window.setViewportSize = ({ width, height }) => { + try { + bootstrap.dispatch(resizeViewport(0, width, height)); + } catch (e) { + console.error(e); + } +}; + +/** + * Called by manager.js to access the viewport's browser, either for testing + * purposes or to reload it when touch simulation is enabled. + * A messageManager getter is added on the object to provide an easy access + * to the message manager without pulling the frame loader. + */ +window.getViewportBrowser = () => { + let browser = document.querySelector("iframe.browser"); + if (!browser.messageManager) { + Object.defineProperty(browser, "messageManager", { + get() { + return this.frameLoader.messageManager; + }, + configurable: true, + enumerable: true, + }); + } + return browser; +}; |