gecko-dev/remote/targets/TabTarget.jsm
Alexandre Poirot 111854b5a5 Bug 1563689 - Revamp how targets are watched and reported. r=remote-protocol-reviewers,ato,jdescottes
* TabObserver is rather an helper class of Targets rather than RemoteAgent.
  Targets is the class which holds all the targets and reports about their
  creation and destructor. It feels legitimate to have it directly integrate
  with TabObserver.
* To better sort of the files. i.e. avoid having "random files" in /remote/
  I'm renaming and moving TabObserver according to its usage.
* We were emitting "connect" and "disconnect" event when a target was created
  or destroyed. But this is misleading as there is no connection to anything
  being made. Only later, a CDP client might connect to a target HTTP endpoint
  and initiate a connection. These events are making this hard to understand
  that the connection actually happens when Target.handle is called.

Differential Revision: https://phabricator.services.mozilla.com/D37043

--HG--
rename : remote/WindowManager.jsm => remote/targets/TabObserver.jsm
extra : moz-landing-system : lando
2019-07-18 12:30:10 +00:00

163 lines
3.5 KiB
JavaScript

/* 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";
var EXPORTED_SYMBOLS = ["TabTarget"];
const { Target } = ChromeUtils.import(
"chrome://remote/content/targets/Target.jsm"
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { TabSession } = ChromeUtils.import(
"chrome://remote/content/sessions/TabSession.jsm"
);
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
const { RemoteAgent } = ChromeUtils.import(
"chrome://remote/content/RemoteAgent.jsm"
);
XPCOMUtils.defineLazyServiceGetter(
this,
"Favicons",
"@mozilla.org/browser/favicon-service;1",
"nsIFaviconService"
);
/**
* Target for a local tab or a remoted frame.
*/
class TabTarget extends Target {
/**
* @param Targets targets
* @param BrowserElement browser
*/
constructor(targets, browser) {
super(targets, TabSession);
this.browser = browser;
// Define the HTTP path to query this target
this.path = `/devtools/page/${this.id}`;
Services.obs.addObserver(this, "message-manager-disconnect");
}
destructor() {
Services.obs.removeObserver(this, "message-manager-disconnect");
super.destructor();
}
get id() {
return this.browsingContext.id;
}
get browserContextId() {
return parseInt(this.browser.getAttribute("usercontextid"));
}
get browsingContext() {
return this.browser.browsingContext;
}
get mm() {
return this.browser.messageManager;
}
get window() {
return this.browser.ownerGlobal;
}
get tab() {
return this.window.gBrowser.getTabForBrowser(this.browser);
}
/**
* Determines if the content browser remains attached
* to its parent chrome window.
*
* We determine this by checking if the <browser> element
* is still attached to the DOM.
*
* @return {boolean}
* True if target's browser is still attached,
* false if it has been disconnected.
*/
get closed() {
return !this.browser || !this.browser.isConnected;
}
get description() {
return "";
}
get frontendURL() {
return null;
}
/** @return {Promise.<String=>} */
get faviconUrl() {
return new Promise((resolve, reject) => {
Favicons.getFaviconURLForPage(this.browser.currentURI, url => {
if (url) {
resolve(url.spec);
} else {
resolve(null);
}
});
});
}
get type() {
return "page";
}
get url() {
return this.browser.currentURI.spec;
}
get wsDebuggerURL() {
const { host, port } = RemoteAgent;
return `ws://${host}:${port}${this.path}`;
}
toString() {
return `[object Target ${this.id}]`;
}
toJSON() {
return {
description: this.description,
devtoolsFrontendUrl: this.frontendURL,
// TODO(ato): toJSON cannot be marked async )-:
faviconUrl: "",
id: this.id,
title: this.title,
type: this.type,
url: this.url,
webSocketDebuggerUrl: this.wsDebuggerURL,
};
}
// nsIObserver
observe(subject, topic, data) {
if (subject === this.mm && subject == "message-manager-disconnect") {
// disconnect debugging target if <browser> is disconnected,
// otherwise this is just a host process change
if (this.closed) {
this.disconnect();
}
}
}
// XPCOM
get QueryInterface() {
return ChromeUtils.generateQI([Ci.nsIHttpRequestHandler, Ci.nsIObserver]);
}
}