summaryrefslogtreecommitdiffstats
path: root/devtools/client/fronts/descriptors/webextension.js
blob: 5db86ee5f82c3e0e7ba77acbb67346fe60af6f03 (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/* 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/. */
"use strict";

const {
  webExtensionDescriptorSpec,
} = require("resource://devtools/shared/specs/descriptors/webextension.js");
const {
  FrontClassWithSpec,
  registerFront,
} = require("resource://devtools/shared/protocol.js");
const {
  DescriptorMixin,
} = require("resource://devtools/client/fronts/descriptors/descriptor-mixin.js");
const DESCRIPTOR_TYPES = require("resource://devtools/client/fronts/descriptors/descriptor-types.js");
loader.lazyRequireGetter(
  this,
  "WindowGlobalTargetFront",
  "resource://devtools/client/fronts/targets/window-global.js",
  true
);

class WebExtensionDescriptorFront extends DescriptorMixin(
  FrontClassWithSpec(webExtensionDescriptorSpec)
) {
  constructor(client, targetFront, parentFront) {
    super(client, targetFront, parentFront);
    this.traits = {};
  }

  descriptorType = DESCRIPTOR_TYPES.EXTENSION;

  form(json) {
    this.actorID = json.actor;

    // Do not use `form` name to avoid colliding with protocol.js's `form` method
    this._form = json;
    this.traits = json.traits || {};
  }

  get backgroundScriptStatus() {
    return this._form.backgroundScriptStatus;
  }

  get debuggable() {
    return this._form.debuggable;
  }

  get hidden() {
    return this._form.hidden;
  }

  get iconDataURL() {
    return this._form.iconDataURL;
  }

  get iconURL() {
    return this._form.iconURL;
  }

  get id() {
    return this._form.id;
  }

  get isSystem() {
    return this._form.isSystem;
  }

  get isWebExtensionDescriptor() {
    return true;
  }

  get isWebExtension() {
    return this._form.isWebExtension;
  }

  get manifestURL() {
    return this._form.manifestURL;
  }

  get name() {
    return this._form.name;
  }

  get persistentBackgroundScript() {
    return this._form.persistentBackgroundScript;
  }

  get temporarilyInstalled() {
    return this._form.temporarilyInstalled;
  }

  get url() {
    return this._form.url;
  }

  get warnings() {
    return this._form.warnings;
  }

  isServerTargetSwitchingEnabled() {
    // For now, we don't expose any target out of the WatcherActor.
    // And the top level target is still manually instantiated by the descriptor.
    // We most likely need to wait for full enabling of EFT before being able to spawn
    // the extension target from the server side as doing this would most likely break
    // the iframe dropdown. It would break it as spawning the targets from the server
    // would probably mean getting rid of the usage of WindowGlobalTargetActor._setWindow
    // and instead spawn one target per extension document.
    // That, instead of having a unique target for all the documents.
    return false;
  }

  getWatcher() {
    return super.getWatcher({
      isServerTargetSwitchingEnabled: this.isServerTargetSwitchingEnabled(),
    });
  }

  _createWebExtensionTarget(form) {
    const front = new WindowGlobalTargetFront(this.conn, null, this);
    front.form(form);
    this.manage(front);
    return front;
  }

  /**
   * Retrieve the WindowGlobalTargetFront representing a
   * WebExtensionTargetActor if this addon is a webextension.
   *
   * WebExtensionDescriptors will be created for any type of addon type
   * (webextension, search plugin, themes). Only webextensions can be targets.
   * This method will throw for other addon types.
   *
   * TODO: We should filter out non-webextension & non-debuggable addons on the
   * server to avoid the isWebExtension check here. See Bug 1644355.
   */
  async getTarget() {
    if (!this.isWebExtension) {
      throw new Error(
        "Tried to create a target for an addon which is not a webextension: " +
          this.actorID
      );
    }

    if (this._targetFront && !this._targetFront.isDestroyed()) {
      return this._targetFront;
    }

    if (this._targetFrontPromise) {
      return this._targetFrontPromise;
    }

    this._targetFrontPromise = (async () => {
      let targetFront = null;
      try {
        const targetForm = await super.getTarget();
        targetFront = this._createWebExtensionTarget(targetForm);
      } catch (e) {
        console.log(
          `Request to connect to WebExtensionDescriptor "${this.id}" failed: ${e}`
        );
      }
      this._targetFront = targetFront;
      this._targetFrontPromise = null;
      return targetFront;
    })();
    return this._targetFrontPromise;
  }
}

exports.WebExtensionDescriptorFront = WebExtensionDescriptorFront;
registerFront(WebExtensionDescriptorFront);