fix: Throw error when loaded in non-extension contexts (#190)

Fixes #186
This commit is contained in:
Rob Wu 2019-07-18 15:21:49 +02:00 committed by GitHub
parent 10bc37b342
commit ad207a84b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 1 deletions

View File

@ -508,6 +508,10 @@ if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.
return wrapObject(extensionAPIs, staticWrappers, apiMetadata); return wrapObject(extensionAPIs, staticWrappers, apiMetadata);
}; };
if (typeof chrome != "object" || !chrome || !chrome.runtime || !chrome.runtime.id) {
throw new Error("This script should only be loaded in a browser extension.");
}
// The build process adds a UMD wrapper around this file, which makes the // The build process adds a UMD wrapper around this file, which makes the
// `module` variable available. // `module` variable available.
module.exports = wrapAPIs(chrome); module.exports = wrapAPIs(chrome);

View File

@ -37,6 +37,17 @@ function setupTestDOMWindow(chromeObject, browserObject = undefined) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const window = testDOMWindow; const window = testDOMWindow;
// Ensure that "chrome.runtime.id" is set, because the polyfill is only
// loaded in extension environments.
if (chromeObject) {
if (!chromeObject.runtime) {
chromeObject.runtime = {};
}
if (!chromeObject.runtime.id) {
chromeObject.runtime.id = "some-test-id-from-test-setup";
}
}
// Inject the fake chrome object used as a fixture for the particular // Inject the fake chrome object used as a fixture for the particular
// browser-polyfill test scenario. // browser-polyfill test scenario.
window.chrome = chromeObject; window.chrome = chromeObject;

View File

@ -5,6 +5,17 @@ const {deepEqual, equal, ok} = require("chai").assert;
const {setupTestDOMWindow} = require("./setup"); const {setupTestDOMWindow} = require("./setup");
describe("browser-polyfill", () => { describe("browser-polyfill", () => {
it("throws an error in a non-extension environment", async () => {
try {
await setupTestDOMWindow(null);
ok(false, "The polyfill script should have failed to load.");
} catch (e) {
equal(e.message,
"This script should only be loaded in a browser extension.",
"Expected script to not load in a non-extension environment");
}
});
it("wraps the global chrome namespace with a global browser namespace", () => { it("wraps the global chrome namespace with a global browser namespace", () => {
const fakeChrome = {}; const fakeChrome = {};
return setupTestDOMWindow(fakeChrome).then(window => { return setupTestDOMWindow(fakeChrome).then(window => {

View File

@ -159,9 +159,16 @@ describe("browser-polyfill", () => {
Object.defineProperty(this, "runtime", {value}); Object.defineProperty(this, "runtime", {value});
return value; return value;
}, },
get tabs() {
ok(false, "chrome.tabs should not lazily be initialized without explicit API call");
},
}; };
return setupTestDOMWindow(fakeChrome).then(window => { return setupTestDOMWindow(fakeChrome).then(window => {
equal(lazyInitCount, 0, "chrome.runtime should not be initialized without explicit API call"); // This used to be equal(lazyInitCount, 0, ...), but was changed to
// accomodate a change in the implementation of the polyfill.
// To verify that APIs are not unnecessarily initialized, the fakeChrome
// object has a "tabs" getter that fails the test upon access.
equal(lazyInitCount, 1, "chrome.runtime should be initialized because chrome.runtime.id is accessed during polyfill initialization");
window.browser.runtime.onMessage.addListener(() => {}); window.browser.runtime.onMessage.addListener(() => {});
equal(lazyInitCount, 1, "chrome.runtime should be initialized upon accessing browser.runtime"); equal(lazyInitCount, 1, "chrome.runtime should be initialized upon accessing browser.runtime");