feat: [extensions] background pages (#21591)
This commit is contained in:
parent
cf497ea478
commit
8bc0c92137
23 changed files with 477 additions and 11 deletions
|
@ -1,4 +1,5 @@
|
|||
import("//build/config/locales.gni")
|
||||
import("//electron/buildflags/buildflags.gni")
|
||||
import("//printing/buildflags/buildflags.gni")
|
||||
import("//tools/grit/repack.gni")
|
||||
import("//ui/base/ui_features.gni")
|
||||
|
@ -87,6 +88,13 @@ template("electron_extra_paks") {
|
|||
sources += [ "$root_gen_dir/chrome/print_preview_resources.pak" ]
|
||||
deps += [ "//chrome/browser/resources:print_preview_resources" ]
|
||||
}
|
||||
if (enable_electron_extensions) {
|
||||
sources += [
|
||||
"$root_gen_dir/extensions/extensions_renderer_resources.pak",
|
||||
"$root_gen_dir/extensions/extensions_resources.pak",
|
||||
]
|
||||
deps += [ "//extensions:extensions_resources" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -607,6 +607,12 @@ filenames = {
|
|||
"shell/browser/extensions/atom_extension_web_contents_observer.h",
|
||||
"shell/browser/extensions/atom_navigation_ui_data.cc",
|
||||
"shell/browser/extensions/atom_navigation_ui_data.h",
|
||||
"shell/browser/extensions/electron_process_manager_delegate.cc",
|
||||
"shell/browser/extensions/electron_process_manager_delegate.h",
|
||||
"shell/browser/extensions/electron_extensions_api_client.cc",
|
||||
"shell/browser/extensions/electron_extensions_api_client.h",
|
||||
"shell/browser/extensions/electron_messaging_delegate.cc",
|
||||
"shell/browser/extensions/electron_messaging_delegate.h",
|
||||
"shell/common/extensions/atom_extensions_api_provider.cc",
|
||||
"shell/common/extensions/atom_extensions_api_provider.h",
|
||||
"shell/common/extensions/atom_extensions_client.cc",
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/public/common/content_constants.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "extensions/common/constants.h"
|
||||
#include "ppapi/buildflags/buildflags.h"
|
||||
#include "shell/browser/atom_paths.h"
|
||||
#include "shell/common/options_switches.h"
|
||||
|
@ -225,7 +226,7 @@ void AtomContentClient::AddAdditionalSchemes(Schemes* schemes) {
|
|||
&schemes->cors_enabled_schemes);
|
||||
|
||||
schemes->service_worker_schemes.emplace_back(url::kFileScheme);
|
||||
schemes->standard_schemes.emplace_back("chrome-extension");
|
||||
schemes->standard_schemes.emplace_back(extensions::kExtensionScheme);
|
||||
}
|
||||
|
||||
void AtomContentClient::AddPepperPlugins(
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
#include "base/mac/bundle_locations.h"
|
||||
#include "base/path_service.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
#include "components/content_settings/core/common/content_settings_pattern.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "extensions/common/constants.h"
|
||||
#include "ipc/ipc_buildflags.h"
|
||||
#include "services/service_manager/embedder/switches.h"
|
||||
#include "services/service_manager/sandbox/switches.h"
|
||||
|
@ -131,6 +133,11 @@ AtomMainDelegate::AtomMainDelegate() = default;
|
|||
|
||||
AtomMainDelegate::~AtomMainDelegate() = default;
|
||||
|
||||
const char* const AtomMainDelegate::kNonWildcardDomainNonPortSchemes[] = {
|
||||
extensions::kExtensionScheme};
|
||||
const size_t AtomMainDelegate::kNonWildcardDomainNonPortSchemesSize =
|
||||
base::size(kNonWildcardDomainNonPortSchemes);
|
||||
|
||||
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
|
||||
|
@ -187,6 +194,10 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
|||
tracing::TracingSamplerProfiler::CreateOnMainThread();
|
||||
|
||||
chrome::RegisterPathProvider();
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
ContentSettingsPattern::SetNonWildcardDomainNonPortSchemes(
|
||||
kNonWildcardDomainNonPortSchemes, kNonWildcardDomainNonPortSchemesSize);
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
OverrideChildProcessPath();
|
||||
|
|
|
@ -21,6 +21,8 @@ void LoadResourceBundle(const std::string& locale);
|
|||
|
||||
class AtomMainDelegate : public content::ContentMainDelegate {
|
||||
public:
|
||||
static const char* const kNonWildcardDomainNonPortSchemes[];
|
||||
static const size_t kNonWildcardDomainNonPortSchemesSize;
|
||||
AtomMainDelegate();
|
||||
~AtomMainDelegate() override;
|
||||
|
||||
|
|
|
@ -358,6 +358,10 @@ WebContents::WebContents(v8::Isolate* isolate,
|
|||
Init(isolate);
|
||||
AttachAsUserData(web_contents);
|
||||
InitZoomController(web_contents, gin::Dictionary::CreateEmpty(isolate));
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
extensions::AtomExtensionWebContentsObserver::CreateForWebContents(
|
||||
web_contents);
|
||||
#endif
|
||||
registry_.AddInterface(base::BindRepeating(&WebContents::BindElectronBrowser,
|
||||
base::Unretained(this)));
|
||||
bindings_.set_connection_error_handler(base::BindRepeating(
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "chrome/common/chrome_version.h"
|
||||
#include "components/net_log/chrome_net_log.h"
|
||||
#include "components/network_hints/common/network_hints.mojom.h"
|
||||
#include "content/public/browser/browser_main_runner.h"
|
||||
#include "content/public/browser/browser_ppapi_host.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
|
@ -43,6 +44,8 @@
|
|||
#include "content/public/common/web_preferences.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "electron/grit/electron_resources.h"
|
||||
#include "extensions/browser/extension_protocols.h"
|
||||
#include "extensions/common/constants.h"
|
||||
#include "net/base/escape.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
#include "ppapi/host/ppapi_host.h"
|
||||
|
@ -123,6 +126,16 @@
|
|||
#include "chrome/browser/printing/printing_message_filter.h"
|
||||
#endif // BUILDFLAG(ENABLE_PRINTING)
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
#include "extensions/browser/extension_message_filter.h"
|
||||
#include "extensions/browser/extension_navigation_throttle.h"
|
||||
#include "extensions/browser/extension_registry.h"
|
||||
#include "extensions/browser/info_map.h"
|
||||
#include "extensions/browser/process_map.h"
|
||||
#include "extensions/common/extension.h"
|
||||
#include "shell/browser/extensions/atom_extension_system.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "content/common/mac_helpers.h"
|
||||
#include "content/public/common/child_process_host.h"
|
||||
|
@ -226,6 +239,8 @@ bool AtomBrowserClient::ShouldForceNewSiteInstance(
|
|||
if (url.SchemeIs(url::kJavaScriptScheme))
|
||||
// "javacript:" scheme should always use same SiteInstance
|
||||
return false;
|
||||
if (url.SchemeIs(extensions::kExtensionScheme))
|
||||
return false;
|
||||
|
||||
content::SiteInstance* current_instance = current_rfh->GetSiteInstance();
|
||||
content::SiteInstance* speculative_instance =
|
||||
|
@ -359,9 +374,16 @@ void AtomBrowserClient::RenderProcessWillLaunch(
|
|||
if (IsProcessObserved(process_id))
|
||||
return;
|
||||
|
||||
auto* browser_context = host->GetBrowserContext();
|
||||
|
||||
#if BUILDFLAG(ENABLE_PRINTING)
|
||||
host->AddFilter(new printing::PrintingMessageFilter(
|
||||
process_id, host->GetBrowserContext()));
|
||||
host->AddFilter(
|
||||
new printing::PrintingMessageFilter(process_id, browser_context));
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
host->AddFilter(
|
||||
new extensions::ExtensionMessageFilter(process_id, browser_context));
|
||||
#endif
|
||||
|
||||
ProcessPreferences prefs;
|
||||
|
@ -708,6 +730,32 @@ void AtomBrowserClient::GetAdditionalWebUISchemes(
|
|||
additional_schemes->push_back(content::kChromeDevToolsScheme);
|
||||
}
|
||||
|
||||
void AtomBrowserClient::SiteInstanceGotProcess(
|
||||
content::SiteInstance* site_instance) {
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
auto* browser_context =
|
||||
static_cast<AtomBrowserContext*>(site_instance->GetBrowserContext());
|
||||
extensions::ExtensionRegistry* registry =
|
||||
extensions::ExtensionRegistry::Get(browser_context);
|
||||
const extensions::Extension* extension =
|
||||
registry->enabled_extensions().GetExtensionOrAppByURL(
|
||||
site_instance->GetSiteURL());
|
||||
if (!extension)
|
||||
return;
|
||||
|
||||
extensions::ProcessMap::Get(browser_context)
|
||||
->Insert(extension->id(), site_instance->GetProcess()->GetID(),
|
||||
site_instance->GetId());
|
||||
|
||||
base::PostTask(
|
||||
FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(&extensions::InfoMap::RegisterExtensionProcess,
|
||||
browser_context->extension_system()->info_map(),
|
||||
extension->id(), site_instance->GetProcess()->GetID(),
|
||||
site_instance->GetId()));
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
}
|
||||
|
||||
void AtomBrowserClient::SiteInstanceDeleting(
|
||||
content::SiteInstance* site_instance) {
|
||||
// We are storing weak_ptr, is it fundamental to maintain the map up-to-date
|
||||
|
@ -719,6 +767,34 @@ void AtomBrowserClient::SiteInstanceDeleting(
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
// Don't do anything if we're shutting down.
|
||||
if (content::BrowserMainRunner::ExitedMainMessageLoop())
|
||||
return;
|
||||
|
||||
auto* browser_context =
|
||||
static_cast<AtomBrowserContext*>(site_instance->GetBrowserContext());
|
||||
// If this isn't an extension renderer there's nothing to do.
|
||||
extensions::ExtensionRegistry* registry =
|
||||
extensions::ExtensionRegistry::Get(browser_context);
|
||||
const extensions::Extension* extension =
|
||||
registry->enabled_extensions().GetExtensionOrAppByURL(
|
||||
site_instance->GetSiteURL());
|
||||
if (!extension)
|
||||
return;
|
||||
|
||||
extensions::ProcessMap::Get(browser_context)
|
||||
->Remove(extension->id(), site_instance->GetProcess()->GetID(),
|
||||
site_instance->GetId());
|
||||
|
||||
base::PostTask(
|
||||
FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(&extensions::InfoMap::UnregisterExtensionProcess,
|
||||
browser_context->extension_system()->info_map(),
|
||||
extension->id(), site_instance->GetProcess()->GetID(),
|
||||
site_instance->GetId()));
|
||||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr<net::ClientCertStore> AtomBrowserClient::CreateClientCertStore(
|
||||
|
@ -869,6 +945,12 @@ AtomBrowserClient::CreateThrottlesForNavigation(
|
|||
content::NavigationHandle* handle) {
|
||||
std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
|
||||
throttles.push_back(std::make_unique<AtomNavigationThrottle>(handle));
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
throttles.push_back(
|
||||
std::make_unique<extensions::ExtensionNavigationThrottle>(handle));
|
||||
#endif
|
||||
|
||||
return throttles;
|
||||
}
|
||||
|
||||
|
|
|
@ -219,6 +219,7 @@ class AtomBrowserClient : public content::ContentBrowserClient,
|
|||
scoped_refptr<net::HttpResponseHeaders> response_headers,
|
||||
bool first_auth_attempt,
|
||||
LoginAuthRequiredCallback auth_required_callback) override;
|
||||
void SiteInstanceGotProcess(content::SiteInstance* site_instance) override;
|
||||
|
||||
// content::RenderProcessHostObserver:
|
||||
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
|
||||
|
|
|
@ -146,14 +146,13 @@ AtomBrowserContext::AtomBrowserContext(const std::string& partition,
|
|||
AtomBrowserContext::~AtomBrowserContext() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
NotifyWillBeDestroyed(this);
|
||||
// Notify any keyed services of browser context destruction.
|
||||
BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
|
||||
this);
|
||||
ShutdownStoragePartitions();
|
||||
|
||||
BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
|
||||
std::move(resource_context_));
|
||||
|
||||
// Notify any keyed services of browser context destruction.
|
||||
BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
|
||||
this);
|
||||
}
|
||||
|
||||
void AtomBrowserContext::InitPrefs() {
|
||||
|
|
|
@ -141,6 +141,12 @@ class AtomBrowserContext
|
|||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
extensions::AtomExtensionSystem* extension_system() {
|
||||
return extension_system_;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
AtomBrowserContext(const std::string& partition,
|
||||
bool in_memory,
|
||||
|
|
|
@ -28,6 +28,7 @@ scoped_refptr<const Extension> LoadUnpacked(
|
|||
// app_shell only supports unpacked extensions.
|
||||
// NOTE: If you add packed extension support consider removing the flag
|
||||
// FOLLOW_SYMLINKS_ANYWHERE below. Packed extensions should not have symlinks.
|
||||
// TODO(nornagon): these LOG()s should surface as JS exceptions
|
||||
if (!base::DirectoryExists(extension_dir)) {
|
||||
LOG(ERROR) << "Extension directory not found: "
|
||||
<< extension_dir.AsUTF8Unsafe();
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
// #include "shell/browser/extensions/atom_extensions_browser_api_provider.h"
|
||||
#include "services/network/public/mojom/url_loader.mojom.h"
|
||||
#include "shell/browser/extensions/atom_navigation_ui_data.h"
|
||||
#include "shell/browser/extensions/electron_extensions_api_client.h"
|
||||
#include "shell/browser/extensions/electron_process_manager_delegate.h"
|
||||
|
||||
using content::BrowserContext;
|
||||
using content::BrowserThread;
|
||||
|
@ -42,10 +44,10 @@ using content::BrowserThread;
|
|||
namespace electron {
|
||||
|
||||
AtomExtensionsBrowserClient::AtomExtensionsBrowserClient()
|
||||
: api_client_(new extensions::ExtensionsAPIClient),
|
||||
// : api_client_(new extensions::AtomExtensionsAPIClient),
|
||||
: api_client_(new extensions::ElectronExtensionsAPIClient),
|
||||
process_manager_delegate_(new extensions::ElectronProcessManagerDelegate),
|
||||
extension_cache_(new extensions::NullExtensionCache()) {
|
||||
// app_shell does not have a concept of channel yet, so leave UNKNOWN to
|
||||
// Electron does not have a concept of channel, so leave UNKNOWN to
|
||||
// enable all channel-dependent extension APIs.
|
||||
extensions::SetCurrentChannel(version_info::Channel::UNKNOWN);
|
||||
|
||||
|
@ -168,7 +170,7 @@ void AtomExtensionsBrowserClient::GetEarlyExtensionPrefsObservers(
|
|||
|
||||
extensions::ProcessManagerDelegate*
|
||||
AtomExtensionsBrowserClient::GetProcessManagerDelegate() const {
|
||||
return NULL;
|
||||
return process_manager_delegate_.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<extensions::ExtensionHostDelegate> AtomExtensionsBrowserClient::
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace extensions {
|
|||
class ExtensionsAPIClient;
|
||||
class KioskDelegate;
|
||||
class ProcessManagerDelegate;
|
||||
class ElectronProcessManagerDelegate;
|
||||
class ProcessMap;
|
||||
} // namespace extensions
|
||||
|
||||
|
@ -134,6 +135,10 @@ class AtomExtensionsBrowserClient : public extensions::ExtensionsBrowserClient {
|
|||
// Support for extension APIs.
|
||||
std::unique_ptr<extensions::ExtensionsAPIClient> api_client_;
|
||||
|
||||
// Support for ProcessManager.
|
||||
std::unique_ptr<extensions::ElectronProcessManagerDelegate>
|
||||
process_manager_delegate_;
|
||||
|
||||
// The extension cache used for download and installation.
|
||||
std::unique_ptr<extensions::ExtensionCache> extension_cache_;
|
||||
|
||||
|
|
29
shell/browser/extensions/electron_extensions_api_client.cc
Normal file
29
shell/browser/extensions/electron_extensions_api_client.cc
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2019 Slack Technologies, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/extensions/electron_extensions_api_client.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "shell/browser/extensions/atom_extension_web_contents_observer.h"
|
||||
#include "shell/browser/extensions/electron_messaging_delegate.h"
|
||||
|
||||
namespace extensions {
|
||||
|
||||
ElectronExtensionsAPIClient::ElectronExtensionsAPIClient() = default;
|
||||
ElectronExtensionsAPIClient::~ElectronExtensionsAPIClient() = default;
|
||||
|
||||
MessagingDelegate* ElectronExtensionsAPIClient::GetMessagingDelegate() {
|
||||
if (!messaging_delegate_)
|
||||
messaging_delegate_ = std::make_unique<ElectronMessagingDelegate>();
|
||||
return messaging_delegate_.get();
|
||||
}
|
||||
|
||||
void ElectronExtensionsAPIClient::AttachWebContentsHelpers(
|
||||
content::WebContents* web_contents) const {
|
||||
extensions::AtomExtensionWebContentsObserver::CreateForWebContents(
|
||||
web_contents);
|
||||
}
|
||||
|
||||
} // namespace extensions
|
32
shell/browser/extensions/electron_extensions_api_client.h
Normal file
32
shell/browser/extensions/electron_extensions_api_client.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2019 Slack Technologies, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSIONS_API_CLIENT_H_
|
||||
#define SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSIONS_API_CLIENT_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "extensions/browser/api/extensions_api_client.h"
|
||||
|
||||
namespace extensions {
|
||||
|
||||
class ElectronMessagingDelegate;
|
||||
|
||||
class ElectronExtensionsAPIClient : public ExtensionsAPIClient {
|
||||
public:
|
||||
ElectronExtensionsAPIClient();
|
||||
~ElectronExtensionsAPIClient() override;
|
||||
|
||||
// ExtensionsAPIClient
|
||||
MessagingDelegate* GetMessagingDelegate() override;
|
||||
void AttachWebContentsHelpers(
|
||||
content::WebContents* web_contents) const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<ElectronMessagingDelegate> messaging_delegate_;
|
||||
};
|
||||
|
||||
} // namespace extensions
|
||||
|
||||
#endif // SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSIONS_API_CLIENT_H_
|
94
shell/browser/extensions/electron_messaging_delegate.cc
Normal file
94
shell/browser/extensions/electron_messaging_delegate.cc
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/extensions/electron_messaging_delegate.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/logging.h"
|
||||
#include "build/build_config.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "extensions/browser/api/messaging/extension_message_port.h"
|
||||
#include "extensions/browser/api/messaging/native_message_host.h"
|
||||
#include "extensions/browser/extension_api_frame_id_map.h"
|
||||
#include "extensions/browser/pref_names.h"
|
||||
#include "extensions/common/api/messaging/port_id.h"
|
||||
#include "extensions/common/extension.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace extensions {
|
||||
|
||||
ElectronMessagingDelegate::ElectronMessagingDelegate() = default;
|
||||
ElectronMessagingDelegate::~ElectronMessagingDelegate() = default;
|
||||
|
||||
MessagingDelegate::PolicyPermission
|
||||
ElectronMessagingDelegate::IsNativeMessagingHostAllowed(
|
||||
content::BrowserContext* browser_context,
|
||||
const std::string& native_host_name) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
return PolicyPermission::DISALLOW;
|
||||
}
|
||||
|
||||
std::unique_ptr<base::DictionaryValue>
|
||||
ElectronMessagingDelegate::MaybeGetTabInfo(content::WebContents* web_contents) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
content::WebContents* ElectronMessagingDelegate::GetWebContentsByTabId(
|
||||
content::BrowserContext* browser_context,
|
||||
int tab_id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<MessagePort> ElectronMessagingDelegate::CreateReceiverForTab(
|
||||
base::WeakPtr<MessagePort::ChannelDelegate> channel_delegate,
|
||||
const std::string& extension_id,
|
||||
const PortId& receiver_port_id,
|
||||
content::WebContents* receiver_contents,
|
||||
int receiver_frame_id) {
|
||||
// Frame ID -1 is every frame in the tab.
|
||||
bool include_child_frames = receiver_frame_id == -1;
|
||||
content::RenderFrameHost* receiver_rfh =
|
||||
include_child_frames ? receiver_contents->GetMainFrame()
|
||||
: ExtensionApiFrameIdMap::GetRenderFrameHostById(
|
||||
receiver_contents, receiver_frame_id);
|
||||
if (!receiver_rfh)
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<ExtensionMessagePort>(
|
||||
channel_delegate, receiver_port_id, extension_id, receiver_rfh,
|
||||
include_child_frames);
|
||||
}
|
||||
|
||||
std::unique_ptr<MessagePort>
|
||||
ElectronMessagingDelegate::CreateReceiverForNativeApp(
|
||||
content::BrowserContext* browser_context,
|
||||
base::WeakPtr<MessagePort::ChannelDelegate> channel_delegate,
|
||||
content::RenderFrameHost* source,
|
||||
const std::string& extension_id,
|
||||
const PortId& receiver_port_id,
|
||||
const std::string& native_app_name,
|
||||
bool allow_user_level,
|
||||
std::string* error_out) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ElectronMessagingDelegate::QueryIncognitoConnectability(
|
||||
content::BrowserContext* context,
|
||||
const Extension* target_extension,
|
||||
content::WebContents* source_contents,
|
||||
const GURL& source_url,
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
DCHECK(context->IsOffTheRecord());
|
||||
callback.Run(false);
|
||||
}
|
||||
|
||||
} // namespace extensions
|
58
shell/browser/extensions/electron_messaging_delegate.h
Normal file
58
shell/browser/extensions/electron_messaging_delegate.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) 2019 Slack Technologies, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SHELL_BROWSER_EXTENSIONS_ELECTRON_MESSAGING_DELEGATE_H_
|
||||
#define SHELL_BROWSER_EXTENSIONS_ELECTRON_MESSAGING_DELEGATE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "extensions/browser/api/messaging/messaging_delegate.h"
|
||||
|
||||
namespace extensions {
|
||||
|
||||
// Helper class for Chrome-specific features of the extension messaging API.
|
||||
class ElectronMessagingDelegate : public MessagingDelegate {
|
||||
public:
|
||||
ElectronMessagingDelegate();
|
||||
~ElectronMessagingDelegate() override;
|
||||
|
||||
// MessagingDelegate:
|
||||
PolicyPermission IsNativeMessagingHostAllowed(
|
||||
content::BrowserContext* browser_context,
|
||||
const std::string& native_host_name) override;
|
||||
std::unique_ptr<base::DictionaryValue> MaybeGetTabInfo(
|
||||
content::WebContents* web_contents) override;
|
||||
content::WebContents* GetWebContentsByTabId(
|
||||
content::BrowserContext* browser_context,
|
||||
int tab_id) override;
|
||||
std::unique_ptr<MessagePort> CreateReceiverForTab(
|
||||
base::WeakPtr<MessagePort::ChannelDelegate> channel_delegate,
|
||||
const std::string& extension_id,
|
||||
const PortId& receiver_port_id,
|
||||
content::WebContents* receiver_contents,
|
||||
int receiver_frame_id) override;
|
||||
std::unique_ptr<MessagePort> CreateReceiverForNativeApp(
|
||||
content::BrowserContext* browser_context,
|
||||
base::WeakPtr<MessagePort::ChannelDelegate> channel_delegate,
|
||||
content::RenderFrameHost* source,
|
||||
const std::string& extension_id,
|
||||
const PortId& receiver_port_id,
|
||||
const std::string& native_app_name,
|
||||
bool allow_user_level,
|
||||
std::string* error_out) override;
|
||||
void QueryIncognitoConnectability(
|
||||
content::BrowserContext* context,
|
||||
const Extension* extension,
|
||||
content::WebContents* web_contents,
|
||||
const GURL& url,
|
||||
const base::Callback<void(bool)>& callback) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ElectronMessagingDelegate);
|
||||
};
|
||||
|
||||
} // namespace extensions
|
||||
|
||||
#endif // SHELL_BROWSER_EXTENSIONS_ELECTRON_MESSAGING_DELEGATE_H_
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2019 Slack Technologies, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
#include "base/debug/stack_trace.h"
|
||||
|
||||
#include "shell/browser/extensions/electron_process_manager_delegate.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/one_shot_event.h"
|
||||
#include "build/build_config.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "extensions/browser/extension_system.h"
|
||||
#include "extensions/browser/process_manager.h"
|
||||
#include "extensions/browser/process_manager_factory.h"
|
||||
#include "extensions/common/extension.h"
|
||||
#include "extensions/common/permissions/permissions_data.h"
|
||||
|
||||
namespace extensions {
|
||||
|
||||
ElectronProcessManagerDelegate::ElectronProcessManagerDelegate() = default;
|
||||
ElectronProcessManagerDelegate::~ElectronProcessManagerDelegate() = default;
|
||||
|
||||
bool ElectronProcessManagerDelegate::AreBackgroundPagesAllowedForContext(
|
||||
content::BrowserContext* context) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ElectronProcessManagerDelegate::IsExtensionBackgroundPageAllowed(
|
||||
content::BrowserContext* context,
|
||||
const Extension& extension) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ElectronProcessManagerDelegate::DeferCreatingStartupBackgroundHosts(
|
||||
content::BrowserContext* context) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace extensions
|
41
shell/browser/extensions/electron_process_manager_delegate.h
Normal file
41
shell/browser/extensions/electron_process_manager_delegate.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2019 Slack Technologies, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SHELL_BROWSER_EXTENSIONS_ELECTRON_PROCESS_MANAGER_DELEGATE_H_
|
||||
#define SHELL_BROWSER_EXTENSIONS_ELECTRON_PROCESS_MANAGER_DELEGATE_H_
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/macros.h"
|
||||
#include "content/public/browser/notification_observer.h"
|
||||
#include "content/public/browser/notification_registrar.h"
|
||||
#include "extensions/browser/process_manager_delegate.h"
|
||||
|
||||
class Browser;
|
||||
class Profile;
|
||||
|
||||
namespace extensions {
|
||||
|
||||
// Support for ProcessManager. Controls cases where Electron wishes to disallow
|
||||
// extension background pages or defer their creation.
|
||||
class ElectronProcessManagerDelegate : public ProcessManagerDelegate {
|
||||
public:
|
||||
ElectronProcessManagerDelegate();
|
||||
~ElectronProcessManagerDelegate() override;
|
||||
|
||||
// ProcessManagerDelegate implementation:
|
||||
bool AreBackgroundPagesAllowedForContext(
|
||||
content::BrowserContext* context) const override;
|
||||
bool IsExtensionBackgroundPageAllowed(
|
||||
content::BrowserContext* context,
|
||||
const Extension& extension) const override;
|
||||
bool DeferCreatingStartupBackgroundHosts(
|
||||
content::BrowserContext* context) const override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ElectronProcessManagerDelegate);
|
||||
};
|
||||
|
||||
} // namespace extensions
|
||||
|
||||
#endif // SHELL_BROWSER_EXTENSIONS_ELECTRON_PROCESS_MANAGER_DELEGATE_H_
|
|
@ -88,6 +88,24 @@ ifdescribe(process.electronBinding('features').isExtensionsEnabled())('chrome ex
|
|||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('background pages', () => {
|
||||
it('loads a lazy background page when sending a message', async () => {
|
||||
const customSession = session.fromPartition(`persist:${require('uuid').v4()}`)
|
||||
;(customSession as any).loadExtension(path.join(fixtures, 'extensions', 'lazy-background-page'))
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession, nodeIntegration: true } })
|
||||
try {
|
||||
w.loadURL(url)
|
||||
const [, resp] = await emittedOnce(ipcMain, 'bg-page-message-response')
|
||||
expect(resp.message).to.deep.equal({ some: 'message' })
|
||||
expect(resp.sender.id).to.be.a('string')
|
||||
expect(resp.sender.origin).to.equal(url)
|
||||
expect(resp.sender.url).to.equal(url + '/')
|
||||
} finally {
|
||||
w.destroy()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
ifdescribe(!process.electronBinding('features').isExtensionsEnabled())('chrome extensions', () => {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
/* eslint-disable no-undef */
|
||||
chrome.runtime.onMessage.addListener((message, sender, reply) => {
|
||||
reply({ message, sender })
|
||||
})
|
|
@ -0,0 +1,6 @@
|
|||
/* eslint-disable no-undef */
|
||||
chrome.runtime.sendMessage({ some: 'message' }, (response) => {
|
||||
const script = document.createElement('script')
|
||||
script.textContent = `require('electron').ipcRenderer.send('bg-page-message-response', ${JSON.stringify(response)})`
|
||||
document.documentElement.appendChild(script)
|
||||
})
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "lazy-background-page",
|
||||
"version": "1.0",
|
||||
"background": {
|
||||
"scripts": ["background.js"],
|
||||
"persistent": false
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"js": ["content_script.js"],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
"manifest_version": 2
|
||||
}
|
Loading…
Reference in a new issue