|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 const ObservableObject = require("devtools/shared/observable-object"); |
|
6 const {getDeviceFront} = require("devtools/server/actors/device"); |
|
7 const {Connection} = require("devtools/client/connection-manager"); |
|
8 |
|
9 const {Cu} = require("chrome"); |
|
10 |
|
11 const _knownDeviceStores = new WeakMap(); |
|
12 |
|
13 let DeviceStore; |
|
14 |
|
15 module.exports = DeviceStore = function(connection) { |
|
16 // If we already know about this connection, |
|
17 // let's re-use the existing store. |
|
18 if (_knownDeviceStores.has(connection)) { |
|
19 return _knownDeviceStores.get(connection); |
|
20 } |
|
21 |
|
22 _knownDeviceStores.set(connection, this); |
|
23 |
|
24 ObservableObject.call(this, {}); |
|
25 |
|
26 this._resetStore(); |
|
27 |
|
28 this.destroy = this.destroy.bind(this); |
|
29 this._onStatusChanged = this._onStatusChanged.bind(this); |
|
30 |
|
31 this._connection = connection; |
|
32 this._connection.once(Connection.Events.DESTROYED, this.destroy); |
|
33 this._connection.on(Connection.Events.STATUS_CHANGED, this._onStatusChanged); |
|
34 this._onTabListChanged = this._onTabListChanged.bind(this); |
|
35 this._onStatusChanged(); |
|
36 return this; |
|
37 }; |
|
38 |
|
39 DeviceStore.prototype = { |
|
40 destroy: function() { |
|
41 if (this._connection) { |
|
42 // While this.destroy is bound using .once() above, that event may not |
|
43 // have occurred when the DeviceStore client calls destroy, so we |
|
44 // manually remove it here. |
|
45 this._connection.off(Connection.Events.DESTROYED, this.destroy); |
|
46 this._connection.off(Connection.Events.STATUS_CHANGED, this._onStatusChanged); |
|
47 _knownDeviceStores.delete(this._connection); |
|
48 this._connection = null; |
|
49 } |
|
50 }, |
|
51 |
|
52 _resetStore: function() { |
|
53 this.object.description = {}; |
|
54 this.object.permissions = []; |
|
55 this.object.tabs = []; |
|
56 }, |
|
57 |
|
58 _onStatusChanged: function() { |
|
59 if (this._connection.status == Connection.Status.CONNECTED) { |
|
60 // Watch for changes to remote browser tabs |
|
61 this._connection.client.addListener("tabListChanged", |
|
62 this._onTabListChanged); |
|
63 this._listTabs(); |
|
64 } else { |
|
65 if (this._connection.client) { |
|
66 this._connection.client.removeListener("tabListChanged", |
|
67 this._onTabListChanged); |
|
68 } |
|
69 this._resetStore(); |
|
70 } |
|
71 }, |
|
72 |
|
73 _onTabListChanged: function() { |
|
74 this._listTabs(); |
|
75 }, |
|
76 |
|
77 _listTabs: function() { |
|
78 if (!this._connection) { |
|
79 return; |
|
80 } |
|
81 this._connection.client.listTabs((resp) => { |
|
82 if (resp.error) { |
|
83 this._connection.disconnect(); |
|
84 return; |
|
85 } |
|
86 this._deviceFront = getDeviceFront(this._connection.client, resp); |
|
87 // Save remote browser's tabs |
|
88 this.object.tabs = resp.tabs; |
|
89 this._feedStore(); |
|
90 }); |
|
91 }, |
|
92 |
|
93 _feedStore: function() { |
|
94 this._getDeviceDescription(); |
|
95 this._getDevicePermissionsTable(); |
|
96 }, |
|
97 |
|
98 _getDeviceDescription: function() { |
|
99 return this._deviceFront.getDescription() |
|
100 .then(json => { |
|
101 json.dpi = Math.ceil(json.dpi); |
|
102 this.object.description = json; |
|
103 }); |
|
104 }, |
|
105 |
|
106 _getDevicePermissionsTable: function() { |
|
107 return this._deviceFront.getRawPermissionsTable() |
|
108 .then(json => { |
|
109 let permissionsTable = json.rawPermissionsTable; |
|
110 let permissionsArray = []; |
|
111 for (let name in permissionsTable) { |
|
112 permissionsArray.push({ |
|
113 name: name, |
|
114 app: permissionsTable[name].app, |
|
115 privileged: permissionsTable[name].privileged, |
|
116 certified: permissionsTable[name].certified, |
|
117 }); |
|
118 } |
|
119 this.object.permissions = permissionsArray; |
|
120 }); |
|
121 } |
|
122 }; |