summaryrefslogtreecommitdiff
path: root/toolkit/devtools/responsivedesign/responsivedesign-child.js
blob: a20d4e665e51654453e90f3432b3a94175023872 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* 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/. */

const Ci = Components.interfaces;
const gDeviceSizeWasPageSize = docShell.deviceSizeIsPageSize;
const gFloatingScrollbarsStylesheet = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars.css", null, null);
let gRequiresFloatingScrollbars;

let active = false;

addMessageListener("ResponsiveMode:Start", startResponsiveMode);
addMessageListener("ResponsiveMode:Stop", stopResponsiveMode);

function startResponsiveMode({data:data}) {
  if (active) {
    return;
  }
  addMessageListener("ResponsiveMode:RequestScreenshot", screenshot);
  addMessageListener("ResponsiveMode:NotifyOnResize", notifiyOnResize);
  let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebProgress);
  webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_ALL);
  docShell.deviceSizeIsPageSize = true;
  gRequiresFloatingScrollbars = data.requiresFloatingScrollbars;

  // At this point, a content viewer might not be loaded for this
  // docshell. makeScrollbarsFloating will be triggered by onLocationChange.
  if (docShell.contentViewer) {
    makeScrollbarsFloating();
  }
  active = true;
  sendAsyncMessage("ResponsiveMode:Start:Done");
}

function notifiyOnResize() {
  content.addEventListener("resize", () => {
    sendAsyncMessage("ResponsiveMode:OnContentResize");
  }, false);
  sendAsyncMessage("ResponsiveMode:NotifyOnResize:Done");
}

function stopResponsiveMode() {
  if (!active) {
    return;
  }
  active = false;
  removeMessageListener("ResponsiveMode:RequestScreenshot", screenshot);
  removeMessageListener("ResponsiveMode:NotifyOnResize", notifiyOnResize);
  let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebProgress);
  webProgress.removeProgressListener(WebProgressListener);
  docShell.deviceSizeIsPageSize = gDeviceSizeWasPageSize;
  restoreScrollbars();
  sendAsyncMessage("ResponsiveMode:Stop:Done");
}

function makeScrollbarsFloating() {
  if (!gRequiresFloatingScrollbars) {
    return;
  }

  let allDocShells = [docShell];

  for (let i = 0; i < docShell.childCount; i++) {
    let child = docShell.getChildAt(i).QueryInterface(Ci.nsIDocShell);
    allDocShells.push(child);
  }

  for (let d of allDocShells) {
    let win = d.contentViewer.DOMDocument.defaultView;
    let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
    try {
      winUtils.loadSheet(gFloatingScrollbarsStylesheet, win.AGENT_SHEET);
    } catch(e) { }
  }

  flushStyle();
}

function restoreScrollbars() {
  let allDocShells = [docShell];
  for (let i = 0; i < docShell.childCount; i++) {
    allDocShells.push(docShell.getChildAt(i).QueryInterface(Ci.nsIDocShell));
  }
  for (let d of allDocShells) {
    let win = d.contentViewer.DOMDocument.defaultView;
    let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
    try {
      winUtils.removeSheet(gFloatingScrollbarsStylesheet, win.AGENT_SHEET);
    } catch(e) { }
  }
  flushStyle();
}

function flushStyle() {
  // Force presContext destruction
  let isSticky = docShell.contentViewer.sticky;
  docShell.contentViewer.sticky = false;
  docShell.contentViewer.hide();
  docShell.contentViewer.show();
  docShell.contentViewer.sticky = isSticky;
}

function screenshot() {
  let canvas = content.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
  let width = content.innerWidth;
  let height = content.innerHeight;
  canvas.mozOpaque = true;
  canvas.width = width;
  canvas.height = height;
  let ctx = canvas.getContext("2d");
  ctx.drawWindow(content, content.scrollX, content.scrollY, width, height, "#fff");
  sendAsyncMessage("ResponsiveMode:RequestScreenshot:Done", canvas.toDataURL());
}

let WebProgressListener = {
  onLocationChange: function onLocationChange(aWebProgress) {
    makeScrollbarsFloating();
  },
  QueryInterface: function QueryInterface(aIID) {
    if (aIID.equals(Ci.nsIWebProgressListener) ||
        aIID.equals(Ci.nsISupportsWeakReference) ||
        aIID.equals(Ci.nsISupports)) {
        return this;
    }
    throw Components.results.NS_ERROR_NO_INTERFACE;
  }
};

sendAsyncMessage("ResponsiveMode:ChildScriptReady");