fix: Prevent a webpage document element to be detected as the Extension API object (#153)
This commit is contained in:
parent
450eee59a3
commit
ebd28186a1
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
if (typeof browser === "undefined") {
|
||||
if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.prototype) {
|
||||
const CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE = "The message port closed before a response was received.";
|
||||
const SEND_RESPONSE_DEPRECATION_WARNING = "Returning a Promise is the preferred way to send a reply from an onMessage/onMessageExternal listener, as the sendResponse will be removed from the specs (See https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)";
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Extension Background page</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<!--
|
||||
The following two DOM elements ensure that the polyfill doesn't detect the
|
||||
globals defined for these DOM element ids as the Extensions API objects.
|
||||
-->
|
||||
<div id="browser"></div>
|
||||
<div id="browser"></div>
|
||||
<div id="chrome"></div>
|
||||
|
||||
<script src="copy-original-api-objects.js"></script>
|
||||
<script src="browser-polyfill.js"></script>
|
||||
<script src="background.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,14 @@
|
|||
/* global originalAPIObjects */
|
||||
|
||||
browser.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
|
||||
if (msg !== "test-api-object-in-background-page") {
|
||||
throw new Error(`Unexpected message received: ${msg}`);
|
||||
}
|
||||
|
||||
return {
|
||||
browserIsDefined: !!browser,
|
||||
chromeIsDefined: !!chrome,
|
||||
browserIsUnchanged: browser === originalAPIObjects.browser,
|
||||
windowBrowserIsUnchanged: window.browser === originalAPIObjects.browser,
|
||||
};
|
||||
});
|
|
@ -1,10 +1,12 @@
|
|||
/* global originalAPIObjects */
|
||||
|
||||
test("browser api object in content script", (t) => {
|
||||
t.ok(browser && browser.runtime, "a global browser API object should be defined");
|
||||
t.ok(chrome && chrome.runtime, "a global chrome API object should be defined");
|
||||
|
||||
if (navigator.userAgent.includes("Firefox/")) {
|
||||
// Check that the polyfill didn't create a polyfill wrapped browser API object on Firefox.
|
||||
t.equal(browser.runtime, chrome.runtime, "browser.runtime and chrome.runtime should be equal on Firefox");
|
||||
t.equal(browser, originalAPIObjects.browser, "browser API object should not be changed on Firefox");
|
||||
// On Firefox, window is not the global object for content scripts, and so we expect window.browser to not
|
||||
// be defined.
|
||||
t.equal(window.browser, undefined, "window.browser is expected to be undefined on Firefox");
|
||||
|
@ -16,3 +18,18 @@ test("browser api object in content script", (t) => {
|
|||
t.equal(browser, window.browser, "browser and window.browser should be the same object");
|
||||
}
|
||||
});
|
||||
|
||||
test("browser api object in background page", async (t) => {
|
||||
const reply = await browser.runtime.sendMessage("test-api-object-in-background-page");
|
||||
|
||||
t.ok(reply.browserIsDefined, "a global browser API object should be defined");
|
||||
t.ok(reply.chromeIsDefined, "a global chrome API object should be defined");
|
||||
|
||||
if (navigator.userAgent.includes("Firefox/")) {
|
||||
t.ok(reply.browserIsUnchanged, "browser API object should not be changed on Firefox");
|
||||
t.ok(reply.windowBrowserIsUnchanged, "window.browser API object should not be changed on Firefox");
|
||||
} else {
|
||||
t.ok(!reply.browserIsUnchanged, "browser API object should have been defined by the polyfill");
|
||||
t.ok(!reply.windowBrowserIsUnchanged, "window.browser API object should have been defined by the polyfill");
|
||||
}
|
||||
});
|
8
test/fixtures/detect-existing-browser-api-object/copy-original-api-objects.js
vendored
Normal file
8
test/fixtures/detect-existing-browser-api-object/copy-original-api-objects.js
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
// Store a copy of the references to the original API objects.
|
||||
const originalAPIObjects = { // eslint-disable-line no-unused-vars
|
||||
// NOTE: on the Browsers that do not provide the browser API object natively,
|
||||
// this will initially point to the HTMLCollection of the <div id="browser"> elements
|
||||
// that are part of the background page.
|
||||
browser,
|
||||
chrome,
|
||||
};
|
|
@ -3,12 +3,16 @@
|
|||
"name": "test-detect-browser-api-object-in-content-script",
|
||||
"version": "0.1",
|
||||
"description": "test-detect-browser-api-object-in-content-script",
|
||||
"background": {
|
||||
"page": "background.html"
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"http://localhost/*"
|
||||
],
|
||||
"js": [
|
||||
"copy-original-api-objects.js",
|
||||
"browser-polyfill.js",
|
||||
"tape.js",
|
||||
"content.js"
|
|
@ -6,5 +6,13 @@
|
|||
</head>
|
||||
<body>
|
||||
<h1>Browser Polyfill Test Page</h1>
|
||||
|
||||
<!--
|
||||
The following two DOM elements ensure that the polyfill doesn't detect the
|
||||
globals defined for these DOM element ids as the Extensions API objects.
|
||||
-->
|
||||
<div id="browser"></div>
|
||||
<div id="browser"></div>
|
||||
<div id="chrome"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -18,8 +18,8 @@ defineExtensionTests({
|
|||
});
|
||||
|
||||
defineExtensionTests({
|
||||
description: "polyfill should detect an existent browser API object in content scripts",
|
||||
extensions: ["detect-browser-api-object-in-content-script"],
|
||||
description: "polyfill should detect an existing browser API object in content scripts and extension pages",
|
||||
extensions: ["detect-existing-browser-api-object"],
|
||||
});
|
||||
|
||||
defineExtensionTests({
|
||||
|
|
|
@ -43,7 +43,10 @@ function setupTestDOMWindow(chromeObject, browserObject = undefined) {
|
|||
|
||||
// Set (or reset) the browser property.
|
||||
if (browserObject) {
|
||||
window.browser = browserObject;
|
||||
// Make the fake browser object a `window.Object` instance, so that
|
||||
// it passes the `Object.getPrototypeOf(browser) !== Object.prototype`
|
||||
// check, otherwise it is going to be overridden by the polyfill (See #153).
|
||||
window.browser = Object.assign(window.Object(), browserObject);
|
||||
} else {
|
||||
delete window.browser;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue