browser/devtools/tilt/tilt.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 "use strict";
     8 const {Cu} = require("chrome");
    10 let {TiltVisualizer} = require("devtools/tilt/tilt-visualizer");
    11 let TiltGL = require("devtools/tilt/tilt-gl");
    12 let TiltUtils = require("devtools/tilt/tilt-utils");
    13 let EventEmitter = require("devtools/toolkit/event-emitter");
    14 let Telemetry = require("devtools/shared/telemetry");
    16 Cu.import("resource://gre/modules/Services.jsm");
    18 // Tilt notifications dispatched through the nsIObserverService.
    19 const TILT_NOTIFICATIONS = {
    20   // Called early in the startup of a new tilt instance
    21   STARTUP: "tilt-startup",
    23   // Fires when Tilt starts the initialization.
    24   INITIALIZING: "tilt-initializing",
    26   // Fires immediately after initialization is complete.
    27   // (when the canvas overlay is visible and the 3D mesh is completely created)
    28   INITIALIZED: "tilt-initialized",
    30   // Fires immediately before the destruction is started.
    31   DESTROYING: "tilt-destroying",
    33   // Fires immediately before the destruction is finished.
    34   // (just before the canvas overlay is removed from its parent node)
    35   BEFORE_DESTROYED: "tilt-before-destroyed",
    37   // Fires when Tilt is completely destroyed.
    38   DESTROYED: "tilt-destroyed",
    40   // Fires when Tilt is shown (after a tab-switch).
    41   SHOWN: "tilt-shown",
    43   // Fires when Tilt is hidden (after a tab-switch).
    44   HIDDEN: "tilt-hidden",
    46   // Fires once Tilt highlights an element in the page.
    47   HIGHLIGHTING: "tilt-highlighting",
    49   // Fires once Tilt stops highlighting any element.
    50   UNHIGHLIGHTING: "tilt-unhighlighting",
    52   // Fires when a node is removed from the 3D mesh.
    53   NODE_REMOVED: "tilt-node-removed"
    54 };
    56 let TiltManager = {
    57   _instances: new WeakMap(),
    58   getTiltForBrowser: function(aChromeWindow)
    59   {
    60     if (this._instances.has(aChromeWindow)) {
    61       return this._instances.get(aChromeWindow);
    62     } else {
    63       let tilt = new Tilt(aChromeWindow);
    64       this._instances.set(aChromeWindow, tilt);
    65       return tilt;
    66     }
    67   },
    68 }
    70 exports.TiltManager = TiltManager;
    72 /**
    73  * Object managing instances of the visualizer.
    74  *
    75  * @param {Window} aWindow
    76  *                 the chrome window used by each visualizer instance
    77  */
    78 function Tilt(aWindow)
    79 {
    80   /**
    81    * Save a reference to the top-level window.
    82    */
    83   this.chromeWindow = aWindow;
    85   /**
    86    * All the instances of TiltVisualizer.
    87    */
    88   this.visualizers = {};
    90   /**
    91    * Shortcut for accessing notifications strings.
    92    */
    93   this.NOTIFICATIONS = TILT_NOTIFICATIONS;
    95   EventEmitter.decorate(this);
    97   this.setup();
    99   this._telemetry = new Telemetry();
   100 }
   102 Tilt.prototype = {
   104   /**
   105    * Initializes a visualizer for the current tab or closes it if already open.
   106    */
   107   toggle: function T_toggle()
   108   {
   109     let contentWindow = this.chromeWindow.gBrowser.selectedBrowser.contentWindow;
   110     let id = this.currentWindowId;
   111     let self = this;
   113     contentWindow.addEventListener("beforeunload", function onUnload() {
   114       contentWindow.removeEventListener("beforeunload", onUnload, false);
   115       self.destroy(id, true);
   116     }, false);
   118     // if the visualizer for the current tab is already open, destroy it now
   119     if (this.visualizers[id]) {
   120       this.destroy(id, true);
   121       this._telemetry.toolClosed("tilt");
   122       return;
   123     } else {
   124       this._telemetry.toolOpened("tilt");
   125     }
   127     // create a visualizer instance for the current tab
   128     this.visualizers[id] = new TiltVisualizer({
   129       chromeWindow: this.chromeWindow,
   130       contentWindow: contentWindow,
   131       parentNode: this.chromeWindow.gBrowser.selectedBrowser.parentNode,
   132       notifications: this.NOTIFICATIONS,
   133       tab: this.chromeWindow.gBrowser.selectedTab
   134     });
   136     Services.obs.notifyObservers(contentWindow, TILT_NOTIFICATIONS.STARTUP, null);
   137     this.visualizers[id].init();
   139     // make sure the visualizer object was initialized properly
   140     if (!this.visualizers[id].isInitialized()) {
   141       this.destroy(id);
   142       this.failureCallback && this.failureCallback();
   143       return;
   144     }
   146     this.lastInstanceId = id;
   147     this.emit("change", this.chromeWindow.gBrowser.selectedTab);
   148     Services.obs.notifyObservers(contentWindow, TILT_NOTIFICATIONS.INITIALIZING, null);
   149   },
   151   /**
   152    * Starts destroying a specific instance of the visualizer.
   153    *
   154    * @param {String} aId
   155    *                 the identifier of the instance in the visualizers array
   156    * @param {Boolean} aAnimateFlag
   157    *                  optional, set to true to display a destruction transition
   158    */
   159   destroy: function T_destroy(aId, aAnimateFlag)
   160   {
   161     // if the visualizer is destroyed or destroying, don't do anything
   162     if (!this.visualizers[aId] || this._isDestroying) {
   163       return;
   164     }
   165     this._isDestroying = true;
   167     let controller = this.visualizers[aId].controller;
   168     let presenter = this.visualizers[aId].presenter;
   170     let content = presenter.contentWindow;
   171     let pageXOffset = content.pageXOffset * presenter.transforms.zoom;
   172     let pageYOffset = content.pageYOffset * presenter.transforms.zoom;
   173     TiltUtils.setDocumentZoom(this.chromeWindow, presenter.transforms.zoom);
   175     // if we're not doing any outro animation, just finish destruction directly
   176     if (!aAnimateFlag) {
   177       this._finish(aId);
   178       return;
   179     }
   181     // otherwise, trigger the outro animation and notify necessary observers
   182     Services.obs.notifyObservers(content, TILT_NOTIFICATIONS.DESTROYING, null);
   184     controller.removeEventListeners();
   185     controller.arcball.reset([-pageXOffset, -pageYOffset]);
   186     presenter.executeDestruction(this._finish.bind(this, aId));
   187   },
   189   /**
   190    * Finishes detroying a specific instance of the visualizer.
   191    *
   192    * @param {String} aId
   193    *                 the identifier of the instance in the visualizers array
   194    */
   195   _finish: function T__finish(aId)
   196   {
   197     let contentWindow = this.visualizers[aId].presenter.contentWindow;
   198     this.visualizers[aId].removeOverlay();
   199     this.visualizers[aId].cleanup();
   200     this.visualizers[aId] = null;
   202     this._isDestroying = false;
   203     this.chromeWindow.gBrowser.selectedBrowser.focus();
   204     this.emit("change", this.chromeWindow.gBrowser.selectedTab);
   205     Services.obs.notifyObservers(contentWindow, TILT_NOTIFICATIONS.DESTROYED, null);
   206   },
   208   /**
   209    * Handles the event fired when a tab is selected.
   210    */
   211   _onTabSelect: function T__onTabSelect()
   212   {
   213     if (this.visualizers[this.lastInstanceId]) {
   214       let contentWindow = this.visualizers[this.lastInstanceId].presenter.contentWindow;
   215       Services.obs.notifyObservers(contentWindow, TILT_NOTIFICATIONS.HIDDEN, null);
   216     }
   218     if (this.currentInstance) {
   219       let contentWindow = this.currentInstance.presenter.contentWindow;
   220       Services.obs.notifyObservers(contentWindow, TILT_NOTIFICATIONS.SHOWN, null);
   221     }
   223     this.lastInstanceId = this.currentWindowId;
   224   },
   226   /**
   227    * Add the browser event listeners to handle state changes.
   228    */
   229   setup: function T_setup()
   230   {
   231     // load the preferences from the devtools.tilt branch
   232     TiltVisualizer.Prefs.load();
   234     this.chromeWindow.gBrowser.tabContainer.addEventListener(
   235       "TabSelect", this._onTabSelect.bind(this), false);
   236   },
   238   /**
   239    * Returns true if this tool is enabled.
   240    */
   241   get enabled()
   242   {
   243     return (TiltVisualizer.Prefs.enabled &&
   244            (TiltGL.isWebGLForceEnabled() || TiltGL.isWebGLSupported()));
   245   },
   247   /**
   248    * Gets the ID of the current window object to identify the visualizer.
   249    */
   250   get currentWindowId()
   251   {
   252     return TiltUtils.getWindowId(
   253       this.chromeWindow.gBrowser.selectedBrowser.contentWindow);
   254   },
   256   /**
   257    * Gets the visualizer instance for the current tab.
   258    */
   259   get currentInstance()
   260   {
   261     return this.visualizers[this.currentWindowId];
   262   },
   263 };

mercurial