Skip to content

Commit

Permalink
feat: [extensions] background pages (electron#21591)
Browse files Browse the repository at this point in the history
  • Loading branch information
nornagon committed Jan 13, 2020
1 parent cf497ea commit 8bc0c92
Show file tree
Hide file tree
Showing 23 changed files with 477 additions and 11 deletions.
8 changes: 8 additions & 0 deletions electron_paks.gni
Original file line number Diff line number Diff line change
@@ -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")
Expand Down Expand Up @@ -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" ]
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions filenames.gni
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 2 additions & 1 deletion shell/app/atom_content_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(
Expand Down
11 changes: 11 additions & 0 deletions shell/app/atom_main_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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();
Expand Down
2 changes: 2 additions & 0 deletions shell/app/atom_main_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 4 additions & 0 deletions shell/browser/api/atom_api_web_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
86 changes: 84 additions & 2 deletions shell/browser/atom_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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(
Expand Down Expand Up @@ -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;
}

Expand Down
1 change: 1 addition & 0 deletions shell/browser/atom_browser_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 3 additions & 4 deletions shell/browser/atom_browser_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
6 changes: 6 additions & 0 deletions shell/browser/atom_browser_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions shell/browser/extensions/atom_extension_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
10 changes: 6 additions & 4 deletions shell/browser/extensions/atom_extensions_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,19 @@
// #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;

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);

Expand Down Expand Up @@ -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::
Expand Down
5 changes: 5 additions & 0 deletions shell/browser/extensions/atom_extensions_browser_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace extensions {
class ExtensionsAPIClient;
class KioskDelegate;
class ProcessManagerDelegate;
class ElectronProcessManagerDelegate;
class ProcessMap;
} // namespace extensions

Expand Down Expand Up @@ -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_;

Expand Down
29 changes: 29 additions & 0 deletions shell/browser/extensions/electron_extensions_api_client.cc
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 8bc0c92

Please sign in to comment.