diff --git a/BUILD.gn b/BUILD.gn
index 100ebdf3a892..38712e4d4fc7 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -629,8 +629,6 @@ source_set("electron_lib") {
deps += [ "//components/printing/common:mojo_interfaces" ]
}
- deps += [ "shell/common/extensions/api:extensions_features" ]
- deps += [ "shell/common/extensions/api" ]
deps += [
"//components/pref_registry",
"//components/user_prefs",
@@ -642,12 +640,22 @@ source_set("electron_lib") {
]
if (enable_electron_extensions) {
sources += filenames.lib_sources_extensions
+ deps += [
+ "shell/browser/extensions/api:api_registration",
+ "shell/common/extensions/api",
+ "shell/common/extensions/api:extensions_features",
+ "//chrome/browser/resources:component_extension_resources",
+ "//components/zoom",
+ ]
}
if (enable_pdf) {
# Printing depends on some //pdf code, so it needs to be built even if the
# pdf viewer isn't enabled.
- deps += [ "//pdf" ]
+ deps += [
+ "//pdf",
+ "//pdf:features",
+ ]
}
if (enable_pdf_viewer) {
deps += [
diff --git a/buildflags/buildflags.gni b/buildflags/buildflags.gni
index 9bd6fe1ed6d8..ee6f22bf4357 100644
--- a/buildflags/buildflags.gni
+++ b/buildflags/buildflags.gni
@@ -14,7 +14,7 @@ declare_args() {
enable_view_api = false
- enable_pdf_viewer = false
+ enable_pdf_viewer = true
enable_tts = true
diff --git a/chromium_src/BUILD.gn b/chromium_src/BUILD.gn
index fa60b2ca5479..d19e324c51c9 100644
--- a/chromium_src/BUILD.gn
+++ b/chromium_src/BUILD.gn
@@ -232,6 +232,12 @@ static_library("chrome") {
if (enable_electron_extensions) {
sources += [
+ "//chrome/browser/extensions/chrome_url_request_util.cc",
+ "//chrome/browser/extensions/chrome_url_request_util.h",
+ "//chrome/browser/pdf/pdf_extension_util.cc",
+ "//chrome/browser/pdf/pdf_extension_util.h",
+ "//chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc",
+ "//chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h",
"//chrome/renderer/extensions/extension_hooks_delegate.cc",
"//chrome/renderer/extensions/extension_hooks_delegate.h",
"//chrome/renderer/extensions/tabs_hooks_delegate.cc",
diff --git a/electron_paks.gni b/electron_paks.gni
index 6eb6ade1d7d9..2e405e6680fc 100644
--- a/electron_paks.gni
+++ b/electron_paks.gni
@@ -92,10 +92,14 @@ template("electron_extra_paks") {
}
if (enable_electron_extensions) {
sources += [
+ "$root_gen_dir/chrome/component_extension_resources.pak",
"$root_gen_dir/extensions/extensions_renderer_resources.pak",
"$root_gen_dir/extensions/extensions_resources.pak",
]
- deps += [ "//extensions:extensions_resources" ]
+ deps += [
+ "//chrome/browser/resources:component_extension_resources",
+ "//extensions:extensions_resources",
+ ]
}
}
}
diff --git a/electron_resources.grd b/electron_resources.grd
index e46d6f6e7911..ae47cedd4232 100644
--- a/electron_resources.grd
+++ b/electron_resources.grd
@@ -17,7 +17,8 @@
-
+
+
diff --git a/filenames.gni b/filenames.gni
index 530b70919c93..70c31d964202 100644
--- a/filenames.gni
+++ b/filenames.gni
@@ -279,6 +279,8 @@ filenames = {
"shell/browser/notifications/win/win32_notification.h",
"shell/browser/notifications/win/windows_toast_notification.cc",
"shell/browser/notifications/win/windows_toast_notification.h",
+ "shell/browser/plugins/plugin_utils.cc",
+ "shell/browser/plugins/plugin_utils.h",
"shell/browser/pref_store_delegate.cc",
"shell/browser/pref_store_delegate.h",
"shell/browser/relauncher.cc",
@@ -594,14 +596,18 @@ filenames = {
]
lib_sources_extensions = [
+ "shell/browser/extensions/api/resources_private/resources_private_api.cc",
+ "shell/browser/extensions/api/resources_private/resources_private_api.h",
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.cc",
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h",
"shell/browser/extensions/api/tabs/tabs_api.cc",
"shell/browser/extensions/api/tabs/tabs_api.h",
- "shell/browser/extensions/electron_extensions_browser_client.cc",
- "shell/browser/extensions/electron_extensions_browser_client.h",
+ "shell/browser/extensions/api/streams_private/streams_private_api.cc",
+ "shell/browser/extensions/api/streams_private/streams_private_api.h",
"shell/browser/extensions/electron_browser_context_keyed_service_factories.cc",
"shell/browser/extensions/electron_browser_context_keyed_service_factories.h",
+ "shell/browser/extensions/electron_component_extension_resource_manager.cc",
+ "shell/browser/extensions/electron_component_extension_resource_manager.h",
"shell/browser/extensions/electron_display_info_provider.cc",
"shell/browser/extensions/electron_display_info_provider.h",
"shell/browser/extensions/electron_extension_host_delegate.cc",
@@ -614,24 +620,26 @@ filenames = {
"shell/browser/extensions/electron_extension_system_factory.h",
"shell/browser/extensions/electron_extension_web_contents_observer.cc",
"shell/browser/extensions/electron_extension_web_contents_observer.h",
- "shell/browser/extensions/electron_navigation_ui_data.cc",
- "shell/browser/extensions/electron_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_extensions_browser_api_provider.cc",
"shell/browser/extensions/electron_extensions_browser_api_provider.h",
+ "shell/browser/extensions/electron_extensions_browser_client.cc",
+ "shell/browser/extensions/electron_extensions_browser_client.h",
"shell/browser/extensions/electron_messaging_delegate.cc",
"shell/browser/extensions/electron_messaging_delegate.h",
+ "shell/browser/extensions/electron_navigation_ui_data.cc",
+ "shell/browser/extensions/electron_navigation_ui_data.h",
+ "shell/browser/extensions/electron_process_manager_delegate.cc",
+ "shell/browser/extensions/electron_process_manager_delegate.h",
"shell/common/extensions/electron_extensions_api_provider.cc",
"shell/common/extensions/electron_extensions_api_provider.h",
"shell/common/extensions/electron_extensions_client.cc",
"shell/common/extensions/electron_extensions_client.h",
- "shell/renderer/extensions/electron_extensions_renderer_client.cc",
- "shell/renderer/extensions/electron_extensions_renderer_client.h",
"shell/renderer/extensions/electron_extensions_dispatcher_delegate.cc",
"shell/renderer/extensions/electron_extensions_dispatcher_delegate.h",
+ "shell/renderer/extensions/electron_extensions_renderer_client.cc",
+ "shell/renderer/extensions/electron_extensions_renderer_client.h",
]
app_sources = [
diff --git a/patches/chromium/.patches b/patches/chromium/.patches
index 7e372d58f720..cc9206139258 100644
--- a/patches/chromium/.patches
+++ b/patches/chromium/.patches
@@ -82,3 +82,5 @@ accessible_pane_view.patch
fixme_grit_conflicts.patch
fix_use_the_new_mediaplaypause_key_listener_for_internal_chrome.patch
fix_use_native_window_button_positions_when_macos_locale_is_rtl.patch
+use_electron_resources_in_pdf_util.patch
+hack_plugin_response_interceptor_to_point_to_electron.patch
diff --git a/patches/chromium/hack_plugin_response_interceptor_to_point_to_electron.patch b/patches/chromium/hack_plugin_response_interceptor_to_point_to_electron.patch
new file mode 100644
index 000000000000..8952d3cf0eb0
--- /dev/null
+++ b/patches/chromium/hack_plugin_response_interceptor_to_point_to_electron.patch
@@ -0,0 +1,24 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jeremy Apthorp
+Date: Mon, 10 Feb 2020 11:52:23 -0800
+Subject: hack plugin response interceptor to point to electron
+
+chrome's streams_private_api does prerender and other things and would
+require a largeish patch to get working, so just redirect it to our
+implementation instead.
+
+diff --git a/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc b/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
+index 1c9aeb8fa71d054159c2ccccccbe57aa474d417e..0bd6412f2c79f77f936720b1a0795b50ecefd26c 100644
+--- a/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
++++ b/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
+@@ -8,8 +8,8 @@
+ #include "base/feature_list.h"
+ #include "base/guid.h"
+ #include "base/task/post_task.h"
+-#include "chrome/browser/extensions/api/streams_private/streams_private_api.h"
+-#include "chrome/browser/plugins/plugin_utils.h"
++#include "electron/shell/browser/extensions/api/streams_private/streams_private_api.h"
++#include "electron/shell/browser/plugins/plugin_utils.h"
+ #include "content/public/browser/browser_task_traits.h"
+ #include "content/public/browser/browser_thread.h"
+ #include "content/public/browser/download_utils.h"
diff --git a/patches/chromium/use_electron_resources_in_pdf_util.patch b/patches/chromium/use_electron_resources_in_pdf_util.patch
new file mode 100644
index 000000000000..d3acae7d7556
--- /dev/null
+++ b/patches/chromium/use_electron_resources_in_pdf_util.patch
@@ -0,0 +1,22 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jeremy Apthorp
+Date: Mon, 10 Feb 2020 10:37:48 -0800
+Subject: use electron resources in pdf_util
+
+Without this, the ID for IDR_PDF_MANIFEST will be wrong on linux
+and cause a DCHECK(), since the resource will be loaded as an empty
+string.
+
+diff --git a/chrome/browser/pdf/pdf_extension_util.cc b/chrome/browser/pdf/pdf_extension_util.cc
+index 877d0ba2f48359243527ddebf1d91132b3d5c455..cd69de498c4968ade0ffabf45b72d4d63b70b10f 100644
+--- a/chrome/browser/pdf/pdf_extension_util.cc
++++ b/chrome/browser/pdf/pdf_extension_util.cc
+@@ -6,7 +6,7 @@
+
+ #include "base/strings/string_util.h"
+ #include "chrome/common/chrome_content_client.h"
+-#include "chrome/grit/browser_resources.h"
++#include "electron/grit/electron_resources.h"
+ #include "ui/base/resource/resource_bundle.h"
+
+ namespace pdf_extension_util {
diff --git a/shell/app/electron_content_client.cc b/shell/app/electron_content_client.cc
index a3938c36a27a..def214d67d91 100644
--- a/shell/app/electron_content_client.cc
+++ b/shell/app/electron_content_client.cc
@@ -33,12 +33,13 @@
#endif // defined(WIDEVINE_CDM_AVAILABLE)
#if BUILDFLAG(ENABLE_PDF_VIEWER)
-#include "pdf/pdf.h" // nogncheck
-#include "pdf/pdf_ppapi.h" // nogncheck
-#include "shell/common/electron_constants.h" // nogncheck
-#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
+#include "pdf/pdf.h" // nogncheck
+#include "pdf/pdf_ppapi.h" // nogncheck
+#include "shell/common/electron_constants.h"
+#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
#if BUILDFLAG(ENABLE_PLUGINS)
+#include "content/public/browser/plugin_service.h"
#include "content/public/common/pepper_plugin_info.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
#endif // BUILDFLAG(ENABLE_PLUGINS)
@@ -155,7 +156,8 @@ void ComputeBuiltInPlugins(std::vector* plugins) {
pdf_info.is_out_of_process = true;
pdf_info.name = "Chromium PDF Viewer";
pdf_info.description = "Portable Document Format";
- pdf_info.path = base::FilePath(FILE_PATH_LITERAL("internal-pdf-viewer"));
+ // This isn't a real file path; it's just used as a unique identifier.
+ pdf_info.path = base::FilePath(kPdfPluginPath);
content::WebPluginMimeType pdf_mime_type(kPdfPluginMimeType, "pdf",
"Portable Document Format");
pdf_info.mime_types.push_back(pdf_mime_type);
@@ -166,6 +168,21 @@ void ComputeBuiltInPlugins(std::vector* plugins) {
chrome_pdf::PPP_ShutdownModule;
pdf_info.permissions = ppapi::PERMISSION_PDF | ppapi::PERMISSION_DEV;
plugins->push_back(pdf_info);
+
+ // NB. in Chrome, this plugin isn't registered until the PDF extension is
+ // loaded. However, in Electron, we load the PDF extension unconditionally
+ // when it is enabled in the build, so we're OK to load the plugin eagerly
+ // here.
+ content::WebPluginInfo info;
+ info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN;
+ info.name = base::UTF8ToUTF16("Chromium PDF Viewer");
+ // This isn't a real file path; it's just used as a unique identifier.
+ info.path = base::FilePath::FromUTF8Unsafe(extension_misc::kPdfExtensionId);
+ info.background_color = content::WebPluginInfo::kDefaultBackgroundColor;
+ info.mime_types.emplace_back("application/pdf", "pdf",
+ "Portable Document Format");
+ content::PluginService::GetInstance()->RefreshPlugins();
+ content::PluginService::GetInstance()->RegisterInternalPlugin(info, true);
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
}
#endif // BUILDFLAG(ENABLE_PLUGINS)
diff --git a/shell/app/electron_main_delegate.cc b/shell/app/electron_main_delegate.cc
index 45eae234226c..0430df19f7a4 100644
--- a/shell/app/electron_main_delegate.cc
+++ b/shell/app/electron_main_delegate.cc
@@ -118,15 +118,6 @@ void LoadResourceBundle(const std::string& locale) {
bundle.ReloadLocaleResources(locale);
bundle.AddDataPackFromPath(pak_dir.Append(FILE_PATH_LITERAL("resources.pak")),
ui::SCALE_FACTOR_NONE);
-#if BUILDFLAG(ENABLE_PDF_VIEWER)
- NOTIMPLEMENTED()
- << "Hi, whoever's fixing PDF support! Thanks! The pdf "
- "viewer resources haven't been ported over to the GN build yet, so "
- "you'll probably need to change this bit of code.";
- bundle.AddDataPackFromPath(
- pak_dir.Append(FILE_PATH_LITERAL("pdf_viewer_resources.pak")),
- ui::GetSupportedScaleFactors()[0]);
-#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
}
ElectronMainDelegate::ElectronMainDelegate() = default;
diff --git a/shell/browser/api/electron_api_session.cc b/shell/browser/api/electron_api_session.cc
index e73727c9887b..7c173c5328a8 100644
--- a/shell/browser/api/electron_api_session.cc
+++ b/shell/browser/api/electron_api_session.cc
@@ -702,7 +702,8 @@ v8::Local Session::GetAllExtensions() {
auto installed_extensions = registry->GenerateInstalledExtensionsSet();
std::vector extensions_vector;
for (const auto& extension : *installed_extensions) {
- extensions_vector.emplace_back(extension.get());
+ if (extension->location() != extensions::Manifest::COMPONENT)
+ extensions_vector.emplace_back(extension.get());
}
return gin::ConvertToV8(isolate(), extensions_vector);
}
diff --git a/shell/browser/electron_browser_client.cc b/shell/browser/electron_browser_client.cc
index 0f5f7480c05d..3a4ab2508176 100644
--- a/shell/browser/electron_browser_client.cc
+++ b/shell/browser/electron_browser_client.cc
@@ -49,6 +49,7 @@
#include "extensions/common/constants.h"
#include "net/base/escape.h"
#include "net/ssl/ssl_cert_request_info.h"
+#include "ppapi/buildflags/buildflags.h"
#include "ppapi/host/ppapi_host.h"
#include "printing/buildflags/buildflags.h"
#include "services/device/public/cpp/geolocation/location_provider.h"
@@ -129,13 +130,29 @@
#endif // BUILDFLAG(ENABLE_PRINTING)
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
+#include "chrome/common/webui_url_constants.h"
+#include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/file_url_loader.h"
+#include "content/public/browser/web_ui_url_loader_factory.h"
+#include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
+#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_message_filter.h"
#include "extensions/browser/extension_navigation_throttle.h"
#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/guest_view/extensions_guest_view_message_filter.h"
+#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "extensions/browser/info_map.h"
+#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_map.h"
+#include "extensions/common/api/mime_handler.mojom.h"
#include "extensions/common/extension.h"
#include "shell/browser/extensions/electron_extension_system.h"
+#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
+#endif
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+#include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h" // nogncheck
+#include "shell/browser/plugins/plugin_utils.h"
#endif
#if defined(OS_MACOSX)
@@ -443,6 +460,8 @@ void ElectronBrowserClient::RenderProcessWillLaunch(
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
host->AddFilter(
new extensions::ExtensionMessageFilter(process_id, browser_context));
+ host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(
+ process_id, browser_context));
#endif
ProcessPreferences prefs;
@@ -785,6 +804,7 @@ void ElectronBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
additional_schemes->insert(additional_schemes->end(), schemes_list.begin(),
schemes_list.end());
additional_schemes->push_back(content::kChromeDevToolsScheme);
+ additional_schemes->push_back(content::kChromeUIScheme);
}
void ElectronBrowserClient::GetAdditionalWebUISchemes(
@@ -1144,28 +1164,123 @@ void ElectronBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
protocol->RegisterURLLoaderFactories(factories);
}
+#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
+namespace {
+
+// The FileURLLoaderFactory provided to the extension background pages.
+// Checks with the ChildProcessSecurityPolicy to validate the file access.
+class FileURLLoaderFactory : public network::mojom::URLLoaderFactory {
+ public:
+ explicit FileURLLoaderFactory(int child_id) : child_id_(child_id) {}
+
+ private:
+ // network::mojom::URLLoaderFactory:
+ void CreateLoaderAndStart(
+ mojo::PendingReceiver loader,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& request,
+ mojo::PendingRemote client,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
+ override {
+ if (!content::ChildProcessSecurityPolicy::GetInstance()->CanRequestURL(
+ child_id_, request.url)) {
+ mojo::Remote(std::move(client))
+ ->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED));
+ return;
+ }
+ content::CreateFileURLLoaderBypassingSecurityChecks(
+ request, std::move(loader), std::move(client),
+ /*observer=*/nullptr,
+ /* allow_directory_listing */ true);
+ }
+
+ void Clone(
+ mojo::PendingReceiver loader) override {
+ receivers_.Add(this, std::move(loader));
+ }
+
+ int child_id_;
+ mojo::ReceiverSet receivers_;
+ DISALLOW_COPY_AND_ASSIGN(FileURLLoaderFactory);
+};
+
+} // namespace
+#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
+
void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
int render_process_id,
int render_frame_id,
NonNetworkURLLoaderFactoryMap* factories) {
-#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
- auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
- render_frame_id);
- if (factory)
- factories->emplace(extensions::kExtensionScheme, std::move(factory));
-#endif
-
- // Chromium may call this even when NetworkService is not enabled.
content::RenderFrameHost* frame_host =
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(frame_host);
+
if (web_contents) {
api::Protocol* protocol = api::Protocol::FromWrappedClass(
v8::Isolate::GetCurrent(), web_contents->GetBrowserContext());
if (protocol)
protocol->RegisterURLLoaderFactories(factories);
}
+#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
+ auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
+ render_frame_id);
+ if (factory)
+ factories->emplace(extensions::kExtensionScheme, std::move(factory));
+
+ if (!web_contents)
+ return;
+
+ extensions::ElectronExtensionWebContentsObserver* web_observer =
+ extensions::ElectronExtensionWebContentsObserver::FromWebContents(
+ web_contents);
+
+ // There is nothing to do if no ElectronExtensionWebContentsObserver is
+ // attached to the |web_contents|.
+ if (!web_observer)
+ return;
+
+ const extensions::Extension* extension =
+ web_observer->GetExtensionFromFrame(frame_host, false);
+ if (!extension)
+ return;
+
+ // Support for chrome:// scheme if appropriate.
+ if (extension->is_extension() &&
+ extensions::Manifest::IsComponentLocation(extension->location())) {
+ // Components of chrome that are implemented as extensions or platform apps
+ // are allowed to use chrome://resources/ and chrome://theme/ URLs.
+ factories->emplace(
+ content::kChromeUIScheme,
+ content::CreateWebUIURLLoader(frame_host, content::kChromeUIScheme,
+ {content::kChromeUIResourcesHost}));
+ }
+
+ // Extension with a background page get file access that gets approval from
+ // ChildProcessSecurityPolicy.
+ extensions::ExtensionHost* host =
+ extensions::ProcessManager::Get(web_contents->GetBrowserContext())
+ ->GetBackgroundHostForExtension(extension->id());
+ if (host) {
+ factories->emplace(url::kFileScheme, std::make_unique(
+ render_process_id));
+ }
+#endif
+}
+
+bool ElectronBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+ base::StringPiece scheme,
+ bool is_embedded_origin_secure) {
+ if (is_embedded_origin_secure && scheme == content::kChromeUIScheme)
+ return true;
+#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
+ return scheme == extensions::kExtensionScheme;
+#else
+ return false;
+#endif
}
bool ElectronBrowserClient::WillInterceptWebSocket(
@@ -1331,11 +1446,31 @@ void ElectronBrowserClient::BindHostReceiverForRenderer(
#endif
}
+#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
+void BindMimeHandlerService(
+ content::RenderFrameHost* frame_host,
+ mojo::PendingReceiver
+ receiver) {
+ content::WebContents* contents =
+ content::WebContents::FromRenderFrameHost(frame_host);
+ auto* guest_view =
+ extensions::MimeHandlerViewGuest::FromWebContents(contents);
+ if (!guest_view)
+ return;
+ extensions::MimeHandlerServiceImpl::Create(guest_view->GetStreamWeakPtr(),
+ std::move(receiver));
+}
+#endif
+
void ElectronBrowserClient::RegisterBrowserInterfaceBindersForFrame(
content::RenderFrameHost* render_frame_host,
service_manager::BinderMapWithContext* map) {
map->Add(
base::BindRepeating(&BindNetworkHintsHandler));
+#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
+ map->Add(
+ base::BindRepeating(&BindMimeHandlerService));
+#endif
}
std::unique_ptr
@@ -1353,4 +1488,35 @@ ElectronBrowserClient::CreateLoginDelegate(
first_auth_attempt, std::move(auth_required_callback));
}
+std::vector>
+ElectronBrowserClient::CreateURLLoaderThrottles(
+ const network::ResourceRequest& request,
+ content::BrowserContext* browser_context,
+ const base::RepeatingCallback& wc_getter,
+ content::NavigationUIData* navigation_ui_data,
+ int frame_tree_node_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ std::vector> result;
+
+#if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
+ result.push_back(std::make_unique(
+ request.resource_type, frame_tree_node_id));
+#endif
+
+ return result;
+}
+
+base::flat_set
+ElectronBrowserClient::GetPluginMimeTypesWithExternalHandlers(
+ content::BrowserContext* browser_context) {
+ base::flat_set mime_types;
+#if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
+ auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
+ for (const auto& pair : map)
+ mime_types.insert(pair.first);
+#endif
+ return mime_types;
+}
+
} // namespace electron
diff --git a/shell/browser/electron_browser_client.h b/shell/browser/electron_browser_client.h
index 4ac718f7c34d..280420dcbba8 100644
--- a/shell/browser/electron_browser_client.h
+++ b/shell/browser/electron_browser_client.h
@@ -195,6 +195,9 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
bool* bypass_redirect_checks,
bool* disable_secure_dns,
network::mojom::URLLoaderFactoryOverridePtr* factory_override) override;
+ bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+ base::StringPiece scheme,
+ bool is_embedded_origin_secure) override;
void OverrideURLLoaderFactoryParams(
content::BrowserContext* browser_context,
const url::Origin& origin,
@@ -230,6 +233,15 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
bool first_auth_attempt,
LoginAuthRequiredCallback auth_required_callback) override;
void SiteInstanceGotProcess(content::SiteInstance* site_instance) override;
+ std::vector>
+ CreateURLLoaderThrottles(
+ const network::ResourceRequest& request,
+ content::BrowserContext* browser_context,
+ const base::RepeatingCallback& wc_getter,
+ content::NavigationUIData* navigation_ui_data,
+ int frame_tree_node_id) override;
+ base::flat_set GetPluginMimeTypesWithExternalHandlers(
+ content::BrowserContext* browser_context) override;
bool IsSuitableHost(content::RenderProcessHost* process_host,
const GURL& site_url) override;
bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
diff --git a/shell/browser/extensions/api/BUILD.gn b/shell/browser/extensions/api/BUILD.gn
new file mode 100644
index 000000000000..bb19064bed01
--- /dev/null
+++ b/shell/browser/extensions/api/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2018 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.
+
+import("//extensions/buildflags/buildflags.gni")
+import("//tools/json_schema_compiler/json_schema_api.gni")
+
+assert(enable_extensions,
+ "Cannot depend on extensions because enable_extensions=false.")
+
+function_registration("api_registration") {
+ sources = [
+ "//electron/shell/common/extensions/api/extension.json",
+ "//electron/shell/common/extensions/api/resources_private.idl",
+ "//electron/shell/common/extensions/api/tabs.json",
+ ]
+ impl_dir = "//electron/shell/browser/extensions/api"
+ configs = [ "//build/config:precompiled_headers" ]
+ bundle_name = "Electron"
+ root_namespace = "extensions::api::%(namespace)s"
+ schema_include_rules = "extensions/common/api:extensions::api::%(namespace)s"
+
+ deps = [
+ # Different APIs include headers from these targets.
+ "//components/zoom",
+ "//content/public/browser",
+ "//extensions/browser",
+
+ # Different APIs include some headers from chrome/common that in turn
+ # include generated headers from these targets.
+ # TODO(brettw) this should be made unnecessary if possible.
+ "//electron/shell/common/extensions/api",
+ ]
+ deps += [ "//extensions/common/api" ]
+}
diff --git a/shell/browser/extensions/api/resources_private/resources_private_api.cc b/shell/browser/extensions/api/resources_private/resources_private_api.cc
new file mode 100644
index 000000000000..73d8ea1edac8
--- /dev/null
+++ b/shell/browser/extensions/api/resources_private/resources_private_api.cc
@@ -0,0 +1,113 @@
+// Copyright 2015 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/api/resources_private/resources_private_api.h"
+
+#include
+#include
+#include
+
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/extensions/api/resources_private.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/zoom/page_zoom_constants.h"
+#include "pdf/buildflags.h"
+#include "printing/buildflags/buildflags.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
+
+#if BUILDFLAG(ENABLE_PDF)
+#include "pdf/pdf_features.h"
+#endif // BUILDFLAG(ENABLE_PDF)
+
+// To add a new component to this API, simply:
+// 1. Add your component to the Component enum in
+// chrome/common/extensions/api/resources_private.idl
+// 2. Create an AddStringsForMyComponent(base::DictionaryValue * dict) method.
+// 3. Tie in that method to the switch statement in Run()
+
+namespace extensions {
+
+namespace {
+
+void AddStringsForPdf(base::DictionaryValue* dict) {
+#if BUILDFLAG(ENABLE_PDF)
+ static constexpr webui::LocalizedString kPdfResources[] = {
+ {"passwordDialogTitle", IDS_PDF_PASSWORD_DIALOG_TITLE},
+ {"passwordPrompt", IDS_PDF_NEED_PASSWORD},
+ {"passwordSubmit", IDS_PDF_PASSWORD_SUBMIT},
+ {"passwordInvalid", IDS_PDF_PASSWORD_INVALID},
+ {"pageLoading", IDS_PDF_PAGE_LOADING},
+ {"pageLoadFailed", IDS_PDF_PAGE_LOAD_FAILED},
+ {"errorDialogTitle", IDS_PDF_ERROR_DIALOG_TITLE},
+ {"pageReload", IDS_PDF_PAGE_RELOAD_BUTTON},
+ {"bookmarks", IDS_PDF_BOOKMARKS},
+ {"labelPageNumber", IDS_PDF_LABEL_PAGE_NUMBER},
+ {"tooltipRotateCW", IDS_PDF_TOOLTIP_ROTATE_CW},
+ {"tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD},
+ {"tooltipPrint", IDS_PDF_TOOLTIP_PRINT},
+ {"tooltipFitToPage", IDS_PDF_TOOLTIP_FIT_PAGE},
+ {"tooltipFitToWidth", IDS_PDF_TOOLTIP_FIT_WIDTH},
+ {"tooltipZoomIn", IDS_PDF_TOOLTIP_ZOOM_IN},
+ {"tooltipZoomOut", IDS_PDF_TOOLTIP_ZOOM_OUT},
+ };
+ for (const auto& resource : kPdfResources)
+ dict->SetString(resource.name, l10n_util::GetStringUTF16(resource.id));
+
+ dict->SetString("presetZoomFactors", zoom::GetPresetZoomFactorsAsJSON());
+#endif // BUILDFLAG(ENABLE_PDF)
+}
+
+void AddAdditionalDataForPdf(base::DictionaryValue* dict) {
+#if BUILDFLAG(ENABLE_PDF)
+ dict->SetKey("pdfFormSaveEnabled",
+ base::Value(base::FeatureList::IsEnabled(
+ chrome_pdf::features::kSaveEditedPDFForm)));
+ dict->SetKey("pdfAnnotationsEnabled",
+ base::Value(base::FeatureList::IsEnabled(
+ chrome_pdf::features::kPDFAnnotations)));
+
+ // TODO(nornagon): enable printing once it works.
+ bool enable_printing = false;
+ dict->SetKey("printingEnabled", base::Value(enable_printing));
+#endif // BUILDFLAG(ENABLE_PDF)
+}
+
+} // namespace
+
+namespace get_strings = api::resources_private::GetStrings;
+
+ResourcesPrivateGetStringsFunction::ResourcesPrivateGetStringsFunction() {}
+
+ResourcesPrivateGetStringsFunction::~ResourcesPrivateGetStringsFunction() {}
+
+ExtensionFunction::ResponseAction ResourcesPrivateGetStringsFunction::Run() {
+ std::unique_ptr params(
+ get_strings::Params::Create(*args_));
+ auto dict = std::make_unique();
+
+ api::resources_private::Component component = params->component;
+
+ switch (component) {
+ case api::resources_private::COMPONENT_PDF:
+ AddStringsForPdf(dict.get());
+ AddAdditionalDataForPdf(dict.get());
+ break;
+ case api::resources_private::COMPONENT_IDENTITY:
+ NOTREACHED();
+ break;
+ case api::resources_private::COMPONENT_NONE:
+ NOTREACHED();
+ break;
+ }
+
+ const std::string& app_locale = g_browser_process->GetApplicationLocale();
+ webui::SetLoadTimeDataDefaults(app_locale, dict.get());
+
+ return RespondNow(OneArgument(std::move(dict)));
+}
+
+} // namespace extensions
diff --git a/shell/browser/extensions/api/resources_private/resources_private_api.h b/shell/browser/extensions/api/resources_private/resources_private_api.h
new file mode 100644
index 000000000000..8dcd8f990c18
--- /dev/null
+++ b/shell/browser/extensions/api/resources_private/resources_private_api.h
@@ -0,0 +1,31 @@
+// Copyright 2015 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.
+
+#ifndef SHELL_BROWSER_EXTENSIONS_API_RESOURCES_PRIVATE_RESOURCES_PRIVATE_API_H_
+#define SHELL_BROWSER_EXTENSIONS_API_RESOURCES_PRIVATE_RESOURCES_PRIVATE_API_H_
+
+#include "base/macros.h"
+#include "extensions/browser/extension_function.h"
+
+namespace extensions {
+
+class ResourcesPrivateGetStringsFunction : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("resourcesPrivate.getStrings",
+ RESOURCESPRIVATE_GETSTRINGS)
+ ResourcesPrivateGetStringsFunction();
+
+ protected:
+ ~ResourcesPrivateGetStringsFunction() override;
+
+ // Override from ExtensionFunction:
+ ExtensionFunction::ResponseAction Run() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ResourcesPrivateGetStringsFunction);
+};
+
+} // namespace extensions
+
+#endif // SHELL_BROWSER_EXTENSIONS_API_RESOURCES_PRIVATE_RESOURCES_PRIVATE_API_H_
diff --git a/shell/browser/extensions/api/streams_private/streams_private_api.cc b/shell/browser/extensions/api/streams_private/streams_private_api.cc
new file mode 100644
index 000000000000..0976ad3d4a80
--- /dev/null
+++ b/shell/browser/extensions/api/streams_private/streams_private_api.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2012 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 "electron/shell/browser/extensions/api/streams_private/streams_private_api.h"
+
+#include
+
+#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/extension_registry.h"
+#include "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.h"
+#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
+#include "extensions/common/manifest_handlers/mime_types_handler.h"
+#include "shell/browser/api/electron_api_web_contents.h"
+
+namespace extensions {
+
+void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
+ const std::string& extension_id,
+ const std::string& view_id,
+ bool embedded,
+ int frame_tree_node_id,
+ int render_process_id,
+ int render_frame_id,
+ content::mojom::TransferrableURLLoaderPtr transferrable_loader,
+ const GURL& original_url) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ content::WebContents* web_contents = nullptr;
+ if (frame_tree_node_id != -1) {
+ web_contents =
+ content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
+ } else {
+ web_contents = content::WebContents::FromRenderFrameHost(
+ content::RenderFrameHost::FromID(render_process_id, render_frame_id));
+ }
+ if (!web_contents)
+ return;
+
+ auto* browser_context = web_contents->GetBrowserContext();
+
+ const extensions::Extension* extension =
+ extensions::ExtensionRegistry::Get(browser_context)
+ ->enabled_extensions()
+ .GetByID(extension_id);
+ if (!extension)
+ return;
+
+ MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
+ if (!handler->HasPlugin())
+ return;
+
+ // If the mime handler uses MimeHandlerViewGuest, the MimeHandlerViewGuest
+ // will take ownership of the stream.
+ GURL handler_url(
+ extensions::Extension::GetBaseURLFromExtensionId(extension_id).spec() +
+ handler->handler_url());
+ int tab_id = -1;
+ auto* api_contents = electron::api::WebContents::FromWrappedClass(
+ v8::Isolate::GetCurrent(), web_contents);
+ if (api_contents)
+ tab_id = api_contents->ID();
+ std::unique_ptr stream_container(
+ new extensions::StreamContainer(
+ tab_id, embedded, handler_url, extension_id,
+ std::move(transferrable_loader), original_url));
+ extensions::MimeHandlerStreamManager::Get(browser_context)
+ ->AddStream(view_id, std::move(stream_container), frame_tree_node_id,
+ render_process_id, render_frame_id);
+}
+
+} // namespace extensions
diff --git a/shell/browser/extensions/api/streams_private/streams_private_api.h b/shell/browser/extensions/api/streams_private/streams_private_api.h
new file mode 100644
index 000000000000..97525ecdf35c
--- /dev/null
+++ b/shell/browser/extensions/api/streams_private/streams_private_api.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2012 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.
+
+#ifndef SHELL_BROWSER_EXTENSIONS_API_STREAMS_PRIVATE_STREAMS_PRIVATE_API_H_
+#define SHELL_BROWSER_EXTENSIONS_API_STREAMS_PRIVATE_STREAMS_PRIVATE_API_H_
+
+#include
+#include
+
+#include "base/macros.h"
+#include "content/public/common/transferrable_url_loader.mojom.h"
+
+namespace extensions {
+
+// TODO(devlin): This is now only used for the MimeTypesHandler API. We should
+// rename and move it to make that clear. https://crbug.com/890401.
+class StreamsPrivateAPI {
+ public:
+ // Send the onExecuteMimeTypeHandler event to |extension_id|. If the viewer is
+ // being opened in a BrowserPlugin, specify a non-empty |view_id| of the
+ // plugin. |embedded| should be set to whether the document is embedded
+ // within another document. The |frame_tree_node_id| parameter is used for the
+ // top level plugins case. (PDF, etc). If this parameter has a valid value
+ // then it overrides the |render_process_id| and |render_frame_id| parameters.
+ // The |render_process_id| is the id of the renderer process. The
+ // |render_frame_id| is the routing id of the RenderFrameHost.
+ //
+ // If the network service is not enabled, |stream| is used; otherwise,
+ // |transferrable_loader| and |original_url| are used instead.
+ static void SendExecuteMimeTypeHandlerEvent(
+ const std::string& extension_id,
+ const std::string& view_id,
+ bool embedded,
+ int frame_tree_node_id,
+ int render_process_id,
+ int render_frame_id,
+ content::mojom::TransferrableURLLoaderPtr transferrable_loader,
+ const GURL& original_url);
+};
+
+} // namespace extensions
+
+#endif // SHELL_BROWSER_EXTENSIONS_API_STREAMS_PRIVATE_STREAMS_PRIVATE_API_H_
diff --git a/shell/browser/extensions/api/tabs/tabs_api.cc b/shell/browser/extensions/api/tabs/tabs_api.cc
index cff0bd6d121d..be7576061b79 100644
--- a/shell/browser/extensions/api/tabs/tabs_api.cc
+++ b/shell/browser/extensions/api/tabs/tabs_api.cc
@@ -12,13 +12,48 @@
#include "extensions/common/manifest_constants.h"
#include "extensions/common/permissions/permissions_data.h"
#include "shell/browser/api/electron_api_web_contents.h"
+#include "shell/browser/web_contents_zoom_controller.h"
+#include "shell/common/extensions/api/tabs.h"
+#include "third_party/blink/public/common/page/page_zoom.h"
+
+using electron::WebContentsZoomController;
namespace extensions {
+namespace tabs = api::tabs;
+
const char kFrameNotFoundError[] = "No frame with id * in tab *.";
+const char kPerOriginOnlyInAutomaticError[] =
+ "Can only set scope to "
+ "\"per-origin\" in \"automatic\" mode.";
using api::extension_types::InjectDetails;
+namespace {
+void ZoomModeToZoomSettings(WebContentsZoomController::ZoomMode zoom_mode,
+ api::tabs::ZoomSettings* zoom_settings) {
+ DCHECK(zoom_settings);
+ switch (zoom_mode) {
+ case WebContentsZoomController::ZoomMode::DEFAULT:
+ zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_AUTOMATIC;
+ zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN;
+ break;
+ case WebContentsZoomController::ZoomMode::ISOLATED:
+ zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_AUTOMATIC;
+ zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
+ break;
+ case WebContentsZoomController::ZoomMode::MANUAL:
+ zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_MANUAL;
+ zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
+ break;
+ case WebContentsZoomController::ZoomMode::DISABLED:
+ zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_DISABLED;
+ zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
+ break;
+ }
+}
+} // namespace
+
ExecuteCodeInTabFunction::ExecuteCodeInTabFunction() : execute_tab_id_(-1) {}
ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {}
@@ -130,4 +165,149 @@ bool TabsExecuteScriptFunction::ShouldInsertCSS() const {
return false;
}
+ExtensionFunction::ResponseAction TabsGetFunction::Run() {
+ std::unique_ptr params(tabs::Get::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+ int tab_id = params->tab_id;
+
+ auto* contents = electron::api::WebContents::FromWeakMapID(
+ v8::Isolate::GetCurrent(), tab_id);
+ if (!contents)
+ return RespondNow(Error("No such tab"));
+
+ tabs::Tab tab;
+
+ tab.id.reset(new int(tab_id));
+ // TODO(nornagon): in Chrome, the tab URL is only available to extensions
+ // that have the "tabs" (or "activeTab") permission. We should do the same
+ // permission check here.
+ tab.url = std::make_unique(
+ contents->web_contents()->GetLastCommittedURL().spec());
+
+ return RespondNow(ArgumentList(tabs::Get::Results::Create(std::move(tab))));
+}
+
+ExtensionFunction::ResponseAction TabsSetZoomFunction::Run() {
+ std::unique_ptr params(
+ tabs::SetZoom::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ int tab_id = params->tab_id ? *params->tab_id : -1;
+ auto* contents = electron::api::WebContents::FromWeakMapID(
+ v8::Isolate::GetCurrent(), tab_id);
+ if (!contents)
+ return RespondNow(Error("No such tab"));
+
+ auto* web_contents = contents->web_contents();
+ GURL url(web_contents->GetVisibleURL());
+ std::string error;
+ if (extension()->permissions_data()->IsRestrictedUrl(url, &error))
+ return RespondNow(Error(error));
+
+ auto* zoom_controller = contents->GetZoomController();
+ double zoom_level =
+ params->zoom_factor > 0
+ ? blink::PageZoomFactorToZoomLevel(params->zoom_factor)
+ : blink::PageZoomFactorToZoomLevel(
+ zoom_controller->GetDefaultZoomFactor());
+
+ zoom_controller->SetZoomLevel(zoom_level);
+
+ return RespondNow(NoArguments());
+}
+
+ExtensionFunction::ResponseAction TabsGetZoomFunction::Run() {
+ std::unique_ptr params(
+ tabs::GetZoom::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ int tab_id = params->tab_id ? *params->tab_id : -1;
+ auto* contents = electron::api::WebContents::FromWeakMapID(
+ v8::Isolate::GetCurrent(), tab_id);
+ if (!contents)
+ return RespondNow(Error("No such tab"));
+
+ double zoom_level = contents->GetZoomController()->GetZoomLevel();
+ double zoom_factor = blink::PageZoomLevelToZoomFactor(zoom_level);
+
+ return RespondNow(ArgumentList(tabs::GetZoom::Results::Create(zoom_factor)));
+}
+
+ExtensionFunction::ResponseAction TabsGetZoomSettingsFunction::Run() {
+ std::unique_ptr params(
+ tabs::GetZoomSettings::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ int tab_id = params->tab_id ? *params->tab_id : -1;
+ auto* contents = electron::api::WebContents::FromWeakMapID(
+ v8::Isolate::GetCurrent(), tab_id);
+ if (!contents)
+ return RespondNow(Error("No such tab"));
+
+ auto* zoom_controller = contents->GetZoomController();
+ WebContentsZoomController::ZoomMode zoom_mode =
+ contents->GetZoomController()->zoom_mode();
+ api::tabs::ZoomSettings zoom_settings;
+ ZoomModeToZoomSettings(zoom_mode, &zoom_settings);
+ zoom_settings.default_zoom_factor.reset(
+ new double(blink::PageZoomLevelToZoomFactor(
+ zoom_controller->GetDefaultZoomLevel())));
+
+ return RespondNow(
+ ArgumentList(api::tabs::GetZoomSettings::Results::Create(zoom_settings)));
+}
+
+ExtensionFunction::ResponseAction TabsSetZoomSettingsFunction::Run() {
+ using api::tabs::ZoomSettings;
+
+ std::unique_ptr params(
+ tabs::SetZoomSettings::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ int tab_id = params->tab_id ? *params->tab_id : -1;
+ auto* contents = electron::api::WebContents::FromWeakMapID(
+ v8::Isolate::GetCurrent(), tab_id);
+ if (!contents)
+ return RespondNow(Error("No such tab"));
+
+ std::string error;
+ GURL url(contents->web_contents()->GetVisibleURL());
+ if (extension()->permissions_data()->IsRestrictedUrl(url, &error))
+ return RespondNow(Error(error));
+
+ // "per-origin" scope is only available in "automatic" mode.
+ if (params->zoom_settings.scope == tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN &&
+ params->zoom_settings.mode != tabs::ZOOM_SETTINGS_MODE_AUTOMATIC &&
+ params->zoom_settings.mode != tabs::ZOOM_SETTINGS_MODE_NONE) {
+ return RespondNow(Error(kPerOriginOnlyInAutomaticError));
+ }
+
+ // Determine the correct internal zoom mode to set |web_contents| to from the
+ // user-specified |zoom_settings|.
+ WebContentsZoomController::ZoomMode zoom_mode =
+ WebContentsZoomController::ZoomMode::DEFAULT;
+ switch (params->zoom_settings.mode) {
+ case tabs::ZOOM_SETTINGS_MODE_NONE:
+ case tabs::ZOOM_SETTINGS_MODE_AUTOMATIC:
+ switch (params->zoom_settings.scope) {
+ case tabs::ZOOM_SETTINGS_SCOPE_NONE:
+ case tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN:
+ zoom_mode = WebContentsZoomController::ZoomMode::DEFAULT;
+ break;
+ case tabs::ZOOM_SETTINGS_SCOPE_PER_TAB:
+ zoom_mode = WebContentsZoomController::ZoomMode::ISOLATED;
+ }
+ break;
+ case tabs::ZOOM_SETTINGS_MODE_MANUAL:
+ zoom_mode = WebContentsZoomController::ZoomMode::MANUAL;
+ break;
+ case tabs::ZOOM_SETTINGS_MODE_DISABLED:
+ zoom_mode = WebContentsZoomController::ZoomMode::DISABLED;
+ }
+
+ contents->GetZoomController()->SetZoomMode(zoom_mode);
+
+ return RespondNow(NoArguments());
+}
+
} // namespace extensions
diff --git a/shell/browser/extensions/api/tabs/tabs_api.h b/shell/browser/extensions/api/tabs/tabs_api.h
index 1848907e17ff..0a3ed2d3cb59 100644
--- a/shell/browser/extensions/api/tabs/tabs_api.h
+++ b/shell/browser/extensions/api/tabs/tabs_api.h
@@ -44,6 +44,48 @@ class TabsExecuteScriptFunction : public ExecuteCodeInTabFunction {
DECLARE_EXTENSION_FUNCTION("tabs.executeScript", TABS_EXECUTESCRIPT)
};
+class TabsGetFunction : public ExtensionFunction {
+ ~TabsGetFunction() override {}
+ ResponseAction Run() override;
+ DECLARE_EXTENSION_FUNCTION("tabs.get", TABS_GET)
+};
+
+class TabsSetZoomFunction : public ExtensionFunction {
+ private:
+ ~TabsSetZoomFunction() override {}
+
+ ResponseAction Run() override;
+
+ DECLARE_EXTENSION_FUNCTION("tabs.setZoom", TABS_SETZOOM)
+};
+
+class TabsGetZoomFunction : public ExtensionFunction {
+ private:
+ ~TabsGetZoomFunction() override {}
+
+ ResponseAction Run() override;
+
+ DECLARE_EXTENSION_FUNCTION("tabs.getZoom", TABS_GETZOOM)
+};
+
+class TabsSetZoomSettingsFunction : public ExtensionFunction {
+ private:
+ ~TabsSetZoomSettingsFunction() override {}
+
+ ResponseAction Run() override;
+
+ DECLARE_EXTENSION_FUNCTION("tabs.setZoomSettings", TABS_SETZOOMSETTINGS)
+};
+
+class TabsGetZoomSettingsFunction : public ExtensionFunction {
+ private:
+ ~TabsGetZoomSettingsFunction() override {}
+
+ ResponseAction Run() override;
+
+ DECLARE_EXTENSION_FUNCTION("tabs.getZoomSettings", TABS_GETZOOMSETTINGS)
+};
+
} // namespace extensions
#endif // SHELL_BROWSER_EXTENSIONS_API_TABS_TABS_API_H_
diff --git a/shell/browser/extensions/electron_browser_context_keyed_service_factories.cc b/shell/browser/extensions/electron_browser_context_keyed_service_factories.cc
index eb0a91fc9150..5b6213f260b4 100644
--- a/shell/browser/extensions/electron_browser_context_keyed_service_factories.cc
+++ b/shell/browser/extensions/electron_browser_context_keyed_service_factories.cc
@@ -5,15 +5,12 @@
#include "shell/browser/extensions/electron_browser_context_keyed_service_factories.h"
#include "extensions/browser/updater/update_service_factory.h"
-// #include "extensions/shell/browser/api/identity/identity_api.h"
#include "shell/browser/extensions/electron_extension_system_factory.h"
namespace extensions {
namespace electron {
void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
- // IdentityAPI::GetFactoryInstance();
-
// TODO(rockot): Remove this once UpdateService is supported across all
// extensions embedders (and namely chrome.)
UpdateServiceFactory::GetInstance();
diff --git a/shell/browser/extensions/electron_component_extension_resource_manager.cc b/shell/browser/extensions/electron_component_extension_resource_manager.cc
new file mode 100644
index 000000000000..e4a548b4b892
--- /dev/null
+++ b/shell/browser/extensions/electron_component_extension_resource_manager.cc
@@ -0,0 +1,89 @@
+// Copyright 2014 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_component_extension_resource_manager.h"
+
+#include
+
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/stl_util.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/grit/component_extension_resources_map.h"
+
+namespace extensions {
+
+ElectronComponentExtensionResourceManager::
+ ElectronComponentExtensionResourceManager() {
+ AddComponentResourceEntries(kComponentExtensionResources,
+ kComponentExtensionResourcesSize);
+}
+
+ElectronComponentExtensionResourceManager::
+ ~ElectronComponentExtensionResourceManager() {}
+
+bool ElectronComponentExtensionResourceManager::IsComponentExtensionResource(
+ const base::FilePath& extension_path,
+ const base::FilePath& resource_path,
+ int* resource_id) const {
+ base::FilePath directory_path = extension_path;
+ base::FilePath resources_dir;
+ base::FilePath relative_path;
+ if (!base::PathService::Get(chrome::DIR_RESOURCES, &resources_dir) ||
+ !resources_dir.AppendRelativePath(directory_path, &relative_path)) {
+ return false;
+ }
+ relative_path = relative_path.Append(resource_path);
+ relative_path = relative_path.NormalizePathSeparators();
+
+ auto entry = path_to_resource_id_.find(relative_path);
+ if (entry != path_to_resource_id_.end()) {
+ *resource_id = entry->second;
+ return true;
+ }
+
+ return false;
+}
+
+const ui::TemplateReplacements*
+ElectronComponentExtensionResourceManager::GetTemplateReplacementsForExtension(
+ const std::string& extension_id) const {
+ auto it = extension_template_replacements_.find(extension_id);
+ if (it == extension_template_replacements_.end()) {
+ return nullptr;
+ }
+ return &it->second;
+}
+
+void ElectronComponentExtensionResourceManager::AddComponentResourceEntries(
+ const GritResourceMap* entries,
+ size_t size) {
+ base::FilePath gen_folder_path = base::FilePath().AppendASCII(
+ "@out_folder@/gen/chrome/browser/resources/");
+ gen_folder_path = gen_folder_path.NormalizePathSeparators();
+
+ for (size_t i = 0; i < size; ++i) {
+ base::FilePath resource_path =
+ base::FilePath().AppendASCII(entries[i].name);
+ resource_path = resource_path.NormalizePathSeparators();
+
+ if (!gen_folder_path.IsParent(resource_path)) {
+ DCHECK(!base::Contains(path_to_resource_id_, resource_path));
+ path_to_resource_id_[resource_path] = entries[i].value;
+ } else {
+ // If the resource is a generated file, strip the generated folder's path,
+ // so that it can be served from a normal URL (as if it were not
+ // generated).
+ base::FilePath effective_path =
+ base::FilePath().AppendASCII(resource_path.AsUTF8Unsafe().substr(
+ gen_folder_path.value().length()));
+ DCHECK(!base::Contains(path_to_resource_id_, effective_path));
+ path_to_resource_id_[effective_path] = entries[i].value;
+ }
+ }
+}
+
+} // namespace extensions
diff --git a/shell/browser/extensions/electron_component_extension_resource_manager.h b/shell/browser/extensions/electron_component_extension_resource_manager.h
new file mode 100644
index 000000000000..5823ea5b2bd3
--- /dev/null
+++ b/shell/browser/extensions/electron_component_extension_resource_manager.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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.
+
+#ifndef SHELL_BROWSER_EXTENSIONS_ELECTRON_COMPONENT_EXTENSION_RESOURCE_MANAGER_H_
+#define SHELL_BROWSER_EXTENSIONS_ELECTRON_COMPONENT_EXTENSION_RESOURCE_MANAGER_H_
+
+#include
+
+#include