feat: [extensions] support extension.getBackgroundPage (#21951)
* feat: [extensions] support extension.getBackgroundPage * cleanup * how does c++ * tests * test for runtime.getBackgroundPage too
This commit is contained in:
parent
eca1dd7f8b
commit
9107157073
16 changed files with 217 additions and 23 deletions
|
@ -186,6 +186,63 @@ const base::FilePath::StringPieceType kPathDelimiter = FILE_PATH_LITERAL(";");
|
||||||
const base::FilePath::StringPieceType kPathDelimiter = FILE_PATH_LITERAL(":");
|
const base::FilePath::StringPieceType kPathDelimiter = FILE_PATH_LITERAL(":");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
// Used by the GetPrivilegeRequiredByUrl() and GetProcessPrivilege() functions
|
||||||
|
// below. Extension, and isolated apps require different privileges to be
|
||||||
|
// granted to their RenderProcessHosts. This classification allows us to make
|
||||||
|
// sure URLs are served by hosts with the right set of privileges.
|
||||||
|
enum RenderProcessHostPrivilege {
|
||||||
|
PRIV_NORMAL,
|
||||||
|
PRIV_HOSTED,
|
||||||
|
PRIV_ISOLATED,
|
||||||
|
PRIV_EXTENSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
RenderProcessHostPrivilege GetPrivilegeRequiredByUrl(
|
||||||
|
const GURL& url,
|
||||||
|
extensions::ExtensionRegistry* registry) {
|
||||||
|
// Default to a normal renderer cause it is lower privileged. This should only
|
||||||
|
// occur if the URL on a site instance is either malformed, or uninitialized.
|
||||||
|
// If it is malformed, then there is no need for better privileges anyways.
|
||||||
|
// If it is uninitialized, but eventually settles on being an a scheme other
|
||||||
|
// than normal webrenderer, the navigation logic will correct us out of band
|
||||||
|
// anyways.
|
||||||
|
if (!url.is_valid())
|
||||||
|
return PRIV_NORMAL;
|
||||||
|
|
||||||
|
if (!url.SchemeIs(extensions::kExtensionScheme))
|
||||||
|
return PRIV_NORMAL;
|
||||||
|
|
||||||
|
return PRIV_EXTENSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderProcessHostPrivilege GetProcessPrivilege(
|
||||||
|
content::RenderProcessHost* process_host,
|
||||||
|
extensions::ProcessMap* process_map,
|
||||||
|
extensions::ExtensionRegistry* registry) {
|
||||||
|
std::set<std::string> extension_ids =
|
||||||
|
process_map->GetExtensionsInProcess(process_host->GetID());
|
||||||
|
if (extension_ids.empty())
|
||||||
|
return PRIV_NORMAL;
|
||||||
|
|
||||||
|
return PRIV_EXTENSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
const extensions::Extension* GetEnabledExtensionFromEffectiveURL(
|
||||||
|
content::BrowserContext* context,
|
||||||
|
const GURL& effective_url) {
|
||||||
|
if (!effective_url.SchemeIs(extensions::kExtensionScheme))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
extensions::ExtensionRegistry* registry =
|
||||||
|
extensions::ExtensionRegistry::Get(context);
|
||||||
|
if (!registry)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return registry->enabled_extensions().GetByID(effective_url.host());
|
||||||
|
}
|
||||||
|
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -760,6 +817,40 @@ void ElectronBrowserClient::SiteInstanceGotProcess(
|
||||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ElectronBrowserClient::IsSuitableHost(
|
||||||
|
content::RenderProcessHost* process_host,
|
||||||
|
const GURL& site_url) {
|
||||||
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
auto* browser_context = process_host->GetBrowserContext();
|
||||||
|
extensions::ExtensionRegistry* registry =
|
||||||
|
extensions::ExtensionRegistry::Get(browser_context);
|
||||||
|
extensions::ProcessMap* process_map =
|
||||||
|
extensions::ProcessMap::Get(browser_context);
|
||||||
|
|
||||||
|
// Otherwise, just make sure the process privilege matches the privilege
|
||||||
|
// required by the site.
|
||||||
|
RenderProcessHostPrivilege privilege_required =
|
||||||
|
GetPrivilegeRequiredByUrl(site_url, registry);
|
||||||
|
return GetProcessPrivilege(process_host, process_map, registry) ==
|
||||||
|
privilege_required;
|
||||||
|
#else
|
||||||
|
return content::ContentBrowserClient::IsSuitableHost(process_host, site_url);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ElectronBrowserClient::ShouldUseProcessPerSite(
|
||||||
|
content::BrowserContext* browser_context,
|
||||||
|
const GURL& effective_url) {
|
||||||
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
const extensions::Extension* extension =
|
||||||
|
GetEnabledExtensionFromEffectiveURL(browser_context, effective_url);
|
||||||
|
return extension != nullptr;
|
||||||
|
#else
|
||||||
|
return content::ContentBrowserClient::ShouldUseProcessPerSite(browser_context,
|
||||||
|
effective_url);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void ElectronBrowserClient::SiteInstanceDeleting(
|
void ElectronBrowserClient::SiteInstanceDeleting(
|
||||||
content::SiteInstance* site_instance) {
|
content::SiteInstance* site_instance) {
|
||||||
// We are storing weak_ptr, is it fundamental to maintain the map up-to-date
|
// We are storing weak_ptr, is it fundamental to maintain the map up-to-date
|
||||||
|
|
|
@ -221,6 +221,10 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
|
||||||
bool first_auth_attempt,
|
bool first_auth_attempt,
|
||||||
LoginAuthRequiredCallback auth_required_callback) override;
|
LoginAuthRequiredCallback auth_required_callback) override;
|
||||||
void SiteInstanceGotProcess(content::SiteInstance* site_instance) override;
|
void SiteInstanceGotProcess(content::SiteInstance* site_instance) override;
|
||||||
|
bool IsSuitableHost(content::RenderProcessHost* process_host,
|
||||||
|
const GURL& site_url) override;
|
||||||
|
bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
|
||||||
|
const GURL& effective_url) override;
|
||||||
|
|
||||||
// content::RenderProcessHostObserver:
|
// content::RenderProcessHostObserver:
|
||||||
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
|
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
"extension_types": ["extension"],
|
"extension_types": ["extension"],
|
||||||
"contexts": ["blessed_extension"]
|
"contexts": ["blessed_extension"]
|
||||||
},
|
},
|
||||||
|
"extension.getBackgroundPage": {
|
||||||
|
"contexts": ["blessed_extension"],
|
||||||
|
"disallow_for_service_workers": true
|
||||||
|
},
|
||||||
"extension.getURL": {
|
"extension.getURL": {
|
||||||
"contexts": ["blessed_extension", "unblessed_extension", "content_script"]
|
"contexts": ["blessed_extension", "unblessed_extension", "content_script"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,20 @@
|
||||||
"properties": {
|
"properties": {
|
||||||
},
|
},
|
||||||
"functions": [
|
"functions": [
|
||||||
|
{
|
||||||
|
"name": "getBackgroundPage",
|
||||||
|
"nocompile": true,
|
||||||
|
"type": "function",
|
||||||
|
"description": "Returns the JavaScript 'window' object for the background page running inside the current extension. Returns null if the extension has no background page.",
|
||||||
|
"parameters": [],
|
||||||
|
"returns": {
|
||||||
|
"type": "object",
|
||||||
|
"optional": true,
|
||||||
|
"name": "backgroundPageGlobal",
|
||||||
|
"isInstanceOf": "Window",
|
||||||
|
"additionalProperties": { "type": "any" }
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "getURL",
|
"name": "getURL",
|
||||||
"deprecated": "Please use $(ref:runtime.getURL).",
|
"deprecated": "Please use $(ref:runtime.getURL).",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"namespace": "tabs",
|
"namespace": "tabs",
|
||||||
|
"description": "Use the <code>chrome.tabs</code> API to interact with the browser's tab system. You can use this API to create, modify, and rearrange tabs in the browser.",
|
||||||
"functions": [
|
"functions": [
|
||||||
{
|
{
|
||||||
"name": "executeScript",
|
"name": "executeScript",
|
||||||
|
|
|
@ -31,8 +31,8 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
// extension registry is redirected to the main session. so installing an
|
// extension registry is redirected to the main session. so installing an
|
||||||
// extension in an in-memory session results in it being installed in the
|
// extension in an in-memory session results in it being installed in the
|
||||||
// default session.
|
// default session.
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
(customSession as any).loadExtension(path.join(fixtures, 'extensions', 'red-bg'))
|
await customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'))
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
||||||
await w.loadURL(url)
|
await w.loadURL(url)
|
||||||
const bg = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor')
|
const bg = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor')
|
||||||
|
@ -41,14 +41,14 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
|
|
||||||
it('removes an extension', async () => {
|
it('removes an extension', async () => {
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
const { id } = await (customSession as any).loadExtension(path.join(fixtures, 'extensions', 'red-bg'))
|
const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'))
|
||||||
{
|
{
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
||||||
await w.loadURL(url)
|
await w.loadURL(url)
|
||||||
const bg = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor')
|
const bg = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor')
|
||||||
expect(bg).to.equal('red')
|
expect(bg).to.equal('red')
|
||||||
}
|
}
|
||||||
(customSession as any).removeExtension(id)
|
customSession.removeExtension(id)
|
||||||
{
|
{
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
||||||
await w.loadURL(url)
|
await w.loadURL(url)
|
||||||
|
@ -59,21 +59,21 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
|
|
||||||
it('lists loaded extensions in getAllExtensions', async () => {
|
it('lists loaded extensions in getAllExtensions', async () => {
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
const e = await (customSession as any).loadExtension(path.join(fixtures, 'extensions', 'red-bg'))
|
const e = await customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'))
|
||||||
expect((customSession as any).getAllExtensions()).to.deep.equal([e]);
|
expect(customSession.getAllExtensions()).to.deep.equal([e])
|
||||||
(customSession as any).removeExtension(e.id)
|
customSession.removeExtension(e.id)
|
||||||
expect((customSession as any).getAllExtensions()).to.deep.equal([])
|
expect(customSession.getAllExtensions()).to.deep.equal([])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('gets an extension by id', async () => {
|
it('gets an extension by id', async () => {
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
const e = await (customSession as any).loadExtension(path.join(fixtures, 'extensions', 'red-bg'))
|
const e = await customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'))
|
||||||
expect((customSession as any).getExtension(e.id)).to.deep.equal(e)
|
expect(customSession.getExtension(e.id)).to.deep.equal(e)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('confines an extension to the session it was loaded in', async () => {
|
it('confines an extension to the session it was loaded in', async () => {
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
(customSession as any).loadExtension(path.join(fixtures, 'extensions', 'red-bg'))
|
customSession.loadExtension(path.join(fixtures, 'extensions', 'red-bg'))
|
||||||
const w = new BrowserWindow({ show: false }) // not in the session
|
const w = new BrowserWindow({ show: false }) // not in the session
|
||||||
await w.loadURL(url)
|
await w.loadURL(url)
|
||||||
const bg = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor')
|
const bg = await w.webContents.executeJavaScript('document.documentElement.style.backgroundColor')
|
||||||
|
@ -83,8 +83,8 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
describe('chrome.runtime', () => {
|
describe('chrome.runtime', () => {
|
||||||
let content: any
|
let content: any
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
(customSession as any).loadExtension(path.join(fixtures, 'extensions', 'chrome-runtime'))
|
customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-runtime'))
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
||||||
try {
|
try {
|
||||||
await w.loadURL(url)
|
await w.loadURL(url)
|
||||||
|
@ -107,8 +107,8 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
|
|
||||||
describe('chrome.storage', () => {
|
describe('chrome.storage', () => {
|
||||||
it('stores and retrieves a key', async () => {
|
it('stores and retrieves a key', async () => {
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
(customSession as any).loadExtension(path.join(fixtures, 'extensions', 'chrome-storage'))
|
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-storage'))
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true } })
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true } })
|
||||||
try {
|
try {
|
||||||
const p = emittedOnce(ipcMain, 'storage-success')
|
const p = emittedOnce(ipcMain, 'storage-success')
|
||||||
|
@ -124,7 +124,7 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
describe('chrome.tabs', () => {
|
describe('chrome.tabs', () => {
|
||||||
it('executeScript', async () => {
|
it('executeScript', async () => {
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
;(customSession as any).loadExtension(path.join(fixtures, 'extensions', 'chrome-api'))
|
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-api'))
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true } })
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true } })
|
||||||
await w.loadURL(url)
|
await w.loadURL(url)
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
|
|
||||||
it('sendMessage receives the response', async function () {
|
it('sendMessage receives the response', async function () {
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
;(customSession as any).loadExtension(path.join(fixtures, 'extensions', 'chrome-api'))
|
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-api'))
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true } })
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true } })
|
||||||
await w.loadURL(url)
|
await w.loadURL(url)
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
describe('background pages', () => {
|
describe('background pages', () => {
|
||||||
it('loads a lazy background page when sending a message', async () => {
|
it('loads a lazy background page when sending a message', async () => {
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
;(customSession as any).loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'))
|
await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'))
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true } })
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true } })
|
||||||
try {
|
try {
|
||||||
w.loadURL(url)
|
w.loadURL(url)
|
||||||
|
@ -170,6 +170,33 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
w.destroy()
|
w.destroy()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('can use extension.getBackgroundPage from a ui page', async () => {
|
||||||
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
|
const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'))
|
||||||
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
||||||
|
await w.loadURL(`chrome-extension://${id}/page-get-background.html`)
|
||||||
|
const receivedMessage = await w.webContents.executeJavaScript(`window.completionPromise`)
|
||||||
|
expect(receivedMessage).to.deep.equal({ some: 'message' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can use extension.getBackgroundPage from a ui page', async () => {
|
||||||
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
|
const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'))
|
||||||
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
||||||
|
await w.loadURL(`chrome-extension://${id}/page-get-background.html`)
|
||||||
|
const receivedMessage = await w.webContents.executeJavaScript(`window.completionPromise`)
|
||||||
|
expect(receivedMessage).to.deep.equal({ some: 'message' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can use runtime.getBackgroundPage from a ui page', async () => {
|
||||||
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
|
const { id } = await customSession.loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'))
|
||||||
|
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } })
|
||||||
|
await w.loadURL(`chrome-extension://${id}/page-runtime-get-background.html`)
|
||||||
|
const receivedMessage = await w.webContents.executeJavaScript(`window.completionPromise`)
|
||||||
|
expect(receivedMessage).to.deep.equal({ some: 'message' })
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('devtools extensions', () => {
|
describe('devtools extensions', () => {
|
||||||
|
@ -201,8 +228,8 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
}
|
}
|
||||||
|
|
||||||
it('loads a devtools extension', async () => {
|
it('loads a devtools extension', async () => {
|
||||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`);
|
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||||
(customSession as any).loadExtension(path.join(fixtures, 'extensions', 'devtools-extension'))
|
customSession.loadExtension(path.join(fixtures, 'extensions', 'devtools-extension'))
|
||||||
const w = new BrowserWindow({ show: true, webPreferences: { session: customSession, nodeIntegration: true } })
|
const w = new BrowserWindow({ show: true, webPreferences: { session: customSession, nodeIntegration: true } })
|
||||||
await w.loadURL('data:text/html,hello')
|
await w.loadURL('data:text/html,hello')
|
||||||
w.webContents.openDevTools()
|
w.webContents.openDevTools()
|
||||||
|
@ -213,8 +240,8 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
|
|
||||||
describe('deprecation shims', () => {
|
describe('deprecation shims', () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
(session.defaultSession as any).getAllExtensions().forEach((e: any) => {
|
session.defaultSession.getAllExtensions().forEach((e: any) => {
|
||||||
(session.defaultSession as any).removeExtension(e.id)
|
session.defaultSession.removeExtension(e.id)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -387,6 +414,30 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
||||||
generateTests(true, false)
|
generateTests(true, false)
|
||||||
generateTests(true, true)
|
generateTests(true, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('extension ui pages', () => {
|
||||||
|
afterEach(() => {
|
||||||
|
session.defaultSession.getAllExtensions().forEach(e => {
|
||||||
|
session.defaultSession.removeExtension(e.id)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('loads a ui page of an extension', async () => {
|
||||||
|
const { id } = await session.defaultSession.loadExtension(path.join(fixtures, 'extensions', 'ui-page'))
|
||||||
|
const w = new BrowserWindow({ show: false })
|
||||||
|
await w.loadURL(`chrome-extension://${id}/bare-page.html`)
|
||||||
|
const textContent = await w.webContents.executeJavaScript(`document.body.textContent`)
|
||||||
|
expect(textContent).to.equal('ui page loaded ok\n')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can load resources', async () => {
|
||||||
|
const { id } = await session.defaultSession.loadExtension(path.join(fixtures, 'extensions', 'ui-page'))
|
||||||
|
const w = new BrowserWindow({ show: false })
|
||||||
|
await w.loadURL(`chrome-extension://${id}/page-script-load.html`)
|
||||||
|
const textContent = await w.webContents.executeJavaScript(`document.body.textContent`)
|
||||||
|
expect(textContent).to.equal('script loaded ok\n')
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
ifdescribe(!process.electronBinding('features').isExtensionsEnabled())('chrome extensions', () => {
|
ifdescribe(!process.electronBinding('features').isExtensionsEnabled())('chrome extensions', () => {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* eslint-disable no-undef */
|
/* eslint-disable no-undef */
|
||||||
chrome.runtime.onMessage.addListener((message, sender, reply) => {
|
chrome.runtime.onMessage.addListener((message, sender, reply) => {
|
||||||
|
window.receivedMessage = message
|
||||||
reply({ message, sender })
|
reply({ message, sender })
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
/* global chrome */
|
||||||
|
window.completionPromise = new Promise((resolve) => {
|
||||||
|
window.completionPromiseResolve = resolve
|
||||||
|
})
|
||||||
|
chrome.runtime.sendMessage({ some: 'message' }, (response) => {
|
||||||
|
window.completionPromiseResolve(chrome.extension.getBackgroundPage().receivedMessage)
|
||||||
|
})
|
|
@ -0,0 +1 @@
|
||||||
|
<script src="get-background-page.js"></script>
|
|
@ -0,0 +1 @@
|
||||||
|
<script src="runtime-get-background-page.js"></script>
|
|
@ -0,0 +1,9 @@
|
||||||
|
/* global chrome */
|
||||||
|
window.completionPromise = new Promise((resolve) => {
|
||||||
|
window.completionPromiseResolve = resolve
|
||||||
|
})
|
||||||
|
chrome.runtime.sendMessage({ some: 'message' }, (response) => {
|
||||||
|
chrome.runtime.getBackgroundPage((bgPage) => {
|
||||||
|
window.completionPromiseResolve(bgPage.receivedMessage)
|
||||||
|
})
|
||||||
|
})
|
2
spec-main/fixtures/extensions/ui-page/bare-page.html
Normal file
2
spec-main/fixtures/extensions/ui-page/bare-page.html
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<!doctype html>
|
||||||
|
<body>ui page loaded ok</body>
|
5
spec-main/fixtures/extensions/ui-page/manifest.json
Normal file
5
spec-main/fixtures/extensions/ui-page/manifest.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name": "ui-page",
|
||||||
|
"version": "1.0",
|
||||||
|
"manifest_version": 2
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<script src="get-background-page.js"></script>
|
|
@ -0,0 +1 @@
|
||||||
|
<script src="script.js"></script>
|
1
spec-main/fixtures/extensions/ui-page/script.js
Normal file
1
spec-main/fixtures/extensions/ui-page/script.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
document.write('script loaded ok')
|
Loading…
Reference in a new issue