feat: enable pdf viewer (#21794)
This commit is contained in:
parent
85f9c779a8
commit
d590f2efe3
51 changed files with 1579 additions and 210 deletions
14
BUILD.gn
14
BUILD.gn
|
@ -629,8 +629,6 @@ source_set("electron_lib") {
|
||||||
deps += [ "//components/printing/common:mojo_interfaces" ]
|
deps += [ "//components/printing/common:mojo_interfaces" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
deps += [ "shell/common/extensions/api:extensions_features" ]
|
|
||||||
deps += [ "shell/common/extensions/api" ]
|
|
||||||
deps += [
|
deps += [
|
||||||
"//components/pref_registry",
|
"//components/pref_registry",
|
||||||
"//components/user_prefs",
|
"//components/user_prefs",
|
||||||
|
@ -642,12 +640,22 @@ source_set("electron_lib") {
|
||||||
]
|
]
|
||||||
if (enable_electron_extensions) {
|
if (enable_electron_extensions) {
|
||||||
sources += filenames.lib_sources_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) {
|
if (enable_pdf) {
|
||||||
# Printing depends on some //pdf code, so it needs to be built even if the
|
# Printing depends on some //pdf code, so it needs to be built even if the
|
||||||
# pdf viewer isn't enabled.
|
# pdf viewer isn't enabled.
|
||||||
deps += [ "//pdf" ]
|
deps += [
|
||||||
|
"//pdf",
|
||||||
|
"//pdf:features",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
if (enable_pdf_viewer) {
|
if (enable_pdf_viewer) {
|
||||||
deps += [
|
deps += [
|
||||||
|
|
|
@ -14,7 +14,7 @@ declare_args() {
|
||||||
|
|
||||||
enable_view_api = false
|
enable_view_api = false
|
||||||
|
|
||||||
enable_pdf_viewer = false
|
enable_pdf_viewer = true
|
||||||
|
|
||||||
enable_tts = true
|
enable_tts = true
|
||||||
|
|
||||||
|
|
|
@ -232,6 +232,12 @@ static_library("chrome") {
|
||||||
|
|
||||||
if (enable_electron_extensions) {
|
if (enable_electron_extensions) {
|
||||||
sources += [
|
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.cc",
|
||||||
"//chrome/renderer/extensions/extension_hooks_delegate.h",
|
"//chrome/renderer/extensions/extension_hooks_delegate.h",
|
||||||
"//chrome/renderer/extensions/tabs_hooks_delegate.cc",
|
"//chrome/renderer/extensions/tabs_hooks_delegate.cc",
|
||||||
|
|
|
@ -92,10 +92,14 @@ template("electron_extra_paks") {
|
||||||
}
|
}
|
||||||
if (enable_electron_extensions) {
|
if (enable_electron_extensions) {
|
||||||
sources += [
|
sources += [
|
||||||
|
"$root_gen_dir/chrome/component_extension_resources.pak",
|
||||||
"$root_gen_dir/extensions/extensions_renderer_resources.pak",
|
"$root_gen_dir/extensions/extensions_renderer_resources.pak",
|
||||||
"$root_gen_dir/extensions/extensions_resources.pak",
|
"$root_gen_dir/extensions/extensions_resources.pak",
|
||||||
]
|
]
|
||||||
deps += [ "//extensions:extensions_resources" ]
|
deps += [
|
||||||
|
"//chrome/browser/resources:component_extension_resources",
|
||||||
|
"//extensions:extensions_resources",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
<part file="electron_strings.grdp" />
|
<part file="electron_strings.grdp" />
|
||||||
</messages>
|
</messages>
|
||||||
<includes>
|
<includes>
|
||||||
<include name="IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE" file="${target_gen_dir}\shell_devtools_discovery_page.html" use_base_dir="false" type="BINDATA" />
|
<include name="IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE" file="${target_gen_dir}/shell_devtools_discovery_page.html" use_base_dir="false" type="BINDATA" />
|
||||||
|
<include name="IDR_PDF_MANIFEST" file="../chrome/browser/resources/pdf/manifest.json" type="BINDATA" />
|
||||||
</includes>
|
</includes>
|
||||||
</release>
|
</release>
|
||||||
</grit>
|
</grit>
|
||||||
|
|
|
@ -279,6 +279,8 @@ filenames = {
|
||||||
"shell/browser/notifications/win/win32_notification.h",
|
"shell/browser/notifications/win/win32_notification.h",
|
||||||
"shell/browser/notifications/win/windows_toast_notification.cc",
|
"shell/browser/notifications/win/windows_toast_notification.cc",
|
||||||
"shell/browser/notifications/win/windows_toast_notification.h",
|
"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.cc",
|
||||||
"shell/browser/pref_store_delegate.h",
|
"shell/browser/pref_store_delegate.h",
|
||||||
"shell/browser/relauncher.cc",
|
"shell/browser/relauncher.cc",
|
||||||
|
@ -594,14 +596,18 @@ filenames = {
|
||||||
]
|
]
|
||||||
|
|
||||||
lib_sources_extensions = [
|
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.cc",
|
||||||
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h",
|
"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.cc",
|
||||||
"shell/browser/extensions/api/tabs/tabs_api.h",
|
"shell/browser/extensions/api/tabs/tabs_api.h",
|
||||||
"shell/browser/extensions/electron_extensions_browser_client.cc",
|
"shell/browser/extensions/api/streams_private/streams_private_api.cc",
|
||||||
"shell/browser/extensions/electron_extensions_browser_client.h",
|
"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.cc",
|
||||||
"shell/browser/extensions/electron_browser_context_keyed_service_factories.h",
|
"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.cc",
|
||||||
"shell/browser/extensions/electron_display_info_provider.h",
|
"shell/browser/extensions/electron_display_info_provider.h",
|
||||||
"shell/browser/extensions/electron_extension_host_delegate.cc",
|
"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_system_factory.h",
|
||||||
"shell/browser/extensions/electron_extension_web_contents_observer.cc",
|
"shell/browser/extensions/electron_extension_web_contents_observer.cc",
|
||||||
"shell/browser/extensions/electron_extension_web_contents_observer.h",
|
"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.cc",
|
||||||
"shell/browser/extensions/electron_extensions_api_client.h",
|
"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.cc",
|
||||||
"shell/browser/extensions/electron_extensions_browser_api_provider.h",
|
"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.cc",
|
||||||
"shell/browser/extensions/electron_messaging_delegate.h",
|
"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.cc",
|
||||||
"shell/common/extensions/electron_extensions_api_provider.h",
|
"shell/common/extensions/electron_extensions_api_provider.h",
|
||||||
"shell/common/extensions/electron_extensions_client.cc",
|
"shell/common/extensions/electron_extensions_client.cc",
|
||||||
"shell/common/extensions/electron_extensions_client.h",
|
"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.cc",
|
||||||
"shell/renderer/extensions/electron_extensions_dispatcher_delegate.h",
|
"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 = [
|
app_sources = [
|
||||||
|
|
|
@ -82,3 +82,5 @@ accessible_pane_view.patch
|
||||||
fixme_grit_conflicts.patch
|
fixme_grit_conflicts.patch
|
||||||
fix_use_the_new_mediaplaypause_key_listener_for_internal_chrome.patch
|
fix_use_the_new_mediaplaypause_key_listener_for_internal_chrome.patch
|
||||||
fix_use_native_window_button_positions_when_macos_locale_is_rtl.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
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jeremy Apthorp <nornagon@nornagon.net>
|
||||||
|
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"
|
22
patches/chromium/use_electron_resources_in_pdf_util.patch
Normal file
22
patches/chromium/use_electron_resources_in_pdf_util.patch
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jeremy Apthorp <nornagon@nornagon.net>
|
||||||
|
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 {
|
|
@ -33,12 +33,13 @@
|
||||||
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||||
#include "pdf/pdf.h" // nogncheck
|
#include "pdf/pdf.h" // nogncheck
|
||||||
#include "pdf/pdf_ppapi.h" // nogncheck
|
#include "pdf/pdf_ppapi.h" // nogncheck
|
||||||
#include "shell/common/electron_constants.h" // nogncheck
|
#include "shell/common/electron_constants.h"
|
||||||
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
|
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_PLUGINS)
|
#if BUILDFLAG(ENABLE_PLUGINS)
|
||||||
|
#include "content/public/browser/plugin_service.h"
|
||||||
#include "content/public/common/pepper_plugin_info.h"
|
#include "content/public/common/pepper_plugin_info.h"
|
||||||
#include "ppapi/shared_impl/ppapi_permissions.h"
|
#include "ppapi/shared_impl/ppapi_permissions.h"
|
||||||
#endif // BUILDFLAG(ENABLE_PLUGINS)
|
#endif // BUILDFLAG(ENABLE_PLUGINS)
|
||||||
|
@ -155,7 +156,8 @@ void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
|
||||||
pdf_info.is_out_of_process = true;
|
pdf_info.is_out_of_process = true;
|
||||||
pdf_info.name = "Chromium PDF Viewer";
|
pdf_info.name = "Chromium PDF Viewer";
|
||||||
pdf_info.description = "Portable Document Format";
|
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",
|
content::WebPluginMimeType pdf_mime_type(kPdfPluginMimeType, "pdf",
|
||||||
"Portable Document Format");
|
"Portable Document Format");
|
||||||
pdf_info.mime_types.push_back(pdf_mime_type);
|
pdf_info.mime_types.push_back(pdf_mime_type);
|
||||||
|
@ -166,6 +168,21 @@ void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
|
||||||
chrome_pdf::PPP_ShutdownModule;
|
chrome_pdf::PPP_ShutdownModule;
|
||||||
pdf_info.permissions = ppapi::PERMISSION_PDF | ppapi::PERMISSION_DEV;
|
pdf_info.permissions = ppapi::PERMISSION_PDF | ppapi::PERMISSION_DEV;
|
||||||
plugins->push_back(pdf_info);
|
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_PDF_VIEWER)
|
||||||
}
|
}
|
||||||
#endif // BUILDFLAG(ENABLE_PLUGINS)
|
#endif // BUILDFLAG(ENABLE_PLUGINS)
|
||||||
|
|
|
@ -118,15 +118,6 @@ void LoadResourceBundle(const std::string& locale) {
|
||||||
bundle.ReloadLocaleResources(locale);
|
bundle.ReloadLocaleResources(locale);
|
||||||
bundle.AddDataPackFromPath(pak_dir.Append(FILE_PATH_LITERAL("resources.pak")),
|
bundle.AddDataPackFromPath(pak_dir.Append(FILE_PATH_LITERAL("resources.pak")),
|
||||||
ui::SCALE_FACTOR_NONE);
|
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;
|
ElectronMainDelegate::ElectronMainDelegate() = default;
|
||||||
|
|
|
@ -702,7 +702,8 @@ v8::Local<v8::Value> Session::GetAllExtensions() {
|
||||||
auto installed_extensions = registry->GenerateInstalledExtensionsSet();
|
auto installed_extensions = registry->GenerateInstalledExtensionsSet();
|
||||||
std::vector<const extensions::Extension*> extensions_vector;
|
std::vector<const extensions::Extension*> extensions_vector;
|
||||||
for (const auto& extension : *installed_extensions) {
|
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);
|
return gin::ConvertToV8(isolate(), extensions_vector);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "extensions/common/constants.h"
|
#include "extensions/common/constants.h"
|
||||||
#include "net/base/escape.h"
|
#include "net/base/escape.h"
|
||||||
#include "net/ssl/ssl_cert_request_info.h"
|
#include "net/ssl/ssl_cert_request_info.h"
|
||||||
|
#include "ppapi/buildflags/buildflags.h"
|
||||||
#include "ppapi/host/ppapi_host.h"
|
#include "ppapi/host/ppapi_host.h"
|
||||||
#include "printing/buildflags/buildflags.h"
|
#include "printing/buildflags/buildflags.h"
|
||||||
#include "services/device/public/cpp/geolocation/location_provider.h"
|
#include "services/device/public/cpp/geolocation/location_provider.h"
|
||||||
|
@ -129,13 +130,29 @@
|
||||||
#endif // BUILDFLAG(ENABLE_PRINTING)
|
#endif // BUILDFLAG(ENABLE_PRINTING)
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#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_message_filter.h"
|
||||||
#include "extensions/browser/extension_navigation_throttle.h"
|
#include "extensions/browser/extension_navigation_throttle.h"
|
||||||
#include "extensions/browser/extension_registry.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/info_map.h"
|
||||||
|
#include "extensions/browser/process_manager.h"
|
||||||
#include "extensions/browser/process_map.h"
|
#include "extensions/browser/process_map.h"
|
||||||
|
#include "extensions/common/api/mime_handler.mojom.h"
|
||||||
#include "extensions/common/extension.h"
|
#include "extensions/common/extension.h"
|
||||||
#include "shell/browser/extensions/electron_extension_system.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
|
#endif
|
||||||
|
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
|
@ -443,6 +460,8 @@ void ElectronBrowserClient::RenderProcessWillLaunch(
|
||||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
host->AddFilter(
|
host->AddFilter(
|
||||||
new extensions::ExtensionMessageFilter(process_id, browser_context));
|
new extensions::ExtensionMessageFilter(process_id, browser_context));
|
||||||
|
host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(
|
||||||
|
process_id, browser_context));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ProcessPreferences prefs;
|
ProcessPreferences prefs;
|
||||||
|
@ -785,6 +804,7 @@ void ElectronBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
|
||||||
additional_schemes->insert(additional_schemes->end(), schemes_list.begin(),
|
additional_schemes->insert(additional_schemes->end(), schemes_list.begin(),
|
||||||
schemes_list.end());
|
schemes_list.end());
|
||||||
additional_schemes->push_back(content::kChromeDevToolsScheme);
|
additional_schemes->push_back(content::kChromeDevToolsScheme);
|
||||||
|
additional_schemes->push_back(content::kChromeUIScheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectronBrowserClient::GetAdditionalWebUISchemes(
|
void ElectronBrowserClient::GetAdditionalWebUISchemes(
|
||||||
|
@ -1144,28 +1164,123 @@ void ElectronBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
|
||||||
protocol->RegisterURLLoaderFactories(factories);
|
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<network::mojom::URLLoader> loader,
|
||||||
|
int32_t routing_id,
|
||||||
|
int32_t request_id,
|
||||||
|
uint32_t options,
|
||||||
|
const network::ResourceRequest& request,
|
||||||
|
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||||
|
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
|
||||||
|
override {
|
||||||
|
if (!content::ChildProcessSecurityPolicy::GetInstance()->CanRequestURL(
|
||||||
|
child_id_, request.url)) {
|
||||||
|
mojo::Remote<network::mojom::URLLoaderClient>(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<network::mojom::URLLoaderFactory> loader) override {
|
||||||
|
receivers_.Add(this, std::move(loader));
|
||||||
|
}
|
||||||
|
|
||||||
|
int child_id_;
|
||||||
|
mojo::ReceiverSet<network::mojom::URLLoaderFactory> receivers_;
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(FileURLLoaderFactory);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
|
||||||
void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
|
void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
|
||||||
int render_process_id,
|
int render_process_id,
|
||||||
int render_frame_id,
|
int render_frame_id,
|
||||||
NonNetworkURLLoaderFactoryMap* factories) {
|
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* frame_host =
|
||||||
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
|
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
|
||||||
content::WebContents* web_contents =
|
content::WebContents* web_contents =
|
||||||
content::WebContents::FromRenderFrameHost(frame_host);
|
content::WebContents::FromRenderFrameHost(frame_host);
|
||||||
|
|
||||||
if (web_contents) {
|
if (web_contents) {
|
||||||
api::Protocol* protocol = api::Protocol::FromWrappedClass(
|
api::Protocol* protocol = api::Protocol::FromWrappedClass(
|
||||||
v8::Isolate::GetCurrent(), web_contents->GetBrowserContext());
|
v8::Isolate::GetCurrent(), web_contents->GetBrowserContext());
|
||||||
if (protocol)
|
if (protocol)
|
||||||
protocol->RegisterURLLoaderFactories(factories);
|
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<FileURLLoaderFactory>(
|
||||||
|
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(
|
bool ElectronBrowserClient::WillInterceptWebSocket(
|
||||||
|
@ -1331,11 +1446,31 @@ void ElectronBrowserClient::BindHostReceiverForRenderer(
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
void BindMimeHandlerService(
|
||||||
|
content::RenderFrameHost* frame_host,
|
||||||
|
mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService>
|
||||||
|
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(
|
void ElectronBrowserClient::RegisterBrowserInterfaceBindersForFrame(
|
||||||
content::RenderFrameHost* render_frame_host,
|
content::RenderFrameHost* render_frame_host,
|
||||||
service_manager::BinderMapWithContext<content::RenderFrameHost*>* map) {
|
service_manager::BinderMapWithContext<content::RenderFrameHost*>* map) {
|
||||||
map->Add<network_hints::mojom::NetworkHintsHandler>(
|
map->Add<network_hints::mojom::NetworkHintsHandler>(
|
||||||
base::BindRepeating(&BindNetworkHintsHandler));
|
base::BindRepeating(&BindNetworkHintsHandler));
|
||||||
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
map->Add<extensions::mime_handler::MimeHandlerService>(
|
||||||
|
base::BindRepeating(&BindMimeHandlerService));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<content::LoginDelegate>
|
std::unique_ptr<content::LoginDelegate>
|
||||||
|
@ -1353,4 +1488,35 @@ ElectronBrowserClient::CreateLoginDelegate(
|
||||||
first_auth_attempt, std::move(auth_required_callback));
|
first_auth_attempt, std::move(auth_required_callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
|
||||||
|
ElectronBrowserClient::CreateURLLoaderThrottles(
|
||||||
|
const network::ResourceRequest& request,
|
||||||
|
content::BrowserContext* browser_context,
|
||||||
|
const base::RepeatingCallback<content::WebContents*()>& wc_getter,
|
||||||
|
content::NavigationUIData* navigation_ui_data,
|
||||||
|
int frame_tree_node_id) {
|
||||||
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
|
||||||
|
|
||||||
|
#if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
|
||||||
|
request.resource_type, frame_tree_node_id));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
base::flat_set<std::string>
|
||||||
|
ElectronBrowserClient::GetPluginMimeTypesWithExternalHandlers(
|
||||||
|
content::BrowserContext* browser_context) {
|
||||||
|
base::flat_set<std::string> 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
|
} // namespace electron
|
||||||
|
|
|
@ -195,6 +195,9 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
|
||||||
bool* bypass_redirect_checks,
|
bool* bypass_redirect_checks,
|
||||||
bool* disable_secure_dns,
|
bool* disable_secure_dns,
|
||||||
network::mojom::URLLoaderFactoryOverridePtr* factory_override) override;
|
network::mojom::URLLoaderFactoryOverridePtr* factory_override) override;
|
||||||
|
bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
|
||||||
|
base::StringPiece scheme,
|
||||||
|
bool is_embedded_origin_secure) override;
|
||||||
void OverrideURLLoaderFactoryParams(
|
void OverrideURLLoaderFactoryParams(
|
||||||
content::BrowserContext* browser_context,
|
content::BrowserContext* browser_context,
|
||||||
const url::Origin& origin,
|
const url::Origin& origin,
|
||||||
|
@ -230,6 +233,15 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
|
||||||
bool first_auth_attempt,
|
bool first_auth_attempt,
|
||||||
LoginAuthRequiredCallback auth_required_callback) override;
|
LoginAuthRequiredCallback auth_required_callback) override;
|
||||||
void SiteInstanceGotProcess(content::SiteInstance* site_instance) override;
|
void SiteInstanceGotProcess(content::SiteInstance* site_instance) override;
|
||||||
|
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
|
||||||
|
CreateURLLoaderThrottles(
|
||||||
|
const network::ResourceRequest& request,
|
||||||
|
content::BrowserContext* browser_context,
|
||||||
|
const base::RepeatingCallback<content::WebContents*()>& wc_getter,
|
||||||
|
content::NavigationUIData* navigation_ui_data,
|
||||||
|
int frame_tree_node_id) override;
|
||||||
|
base::flat_set<std::string> GetPluginMimeTypesWithExternalHandlers(
|
||||||
|
content::BrowserContext* browser_context) override;
|
||||||
bool IsSuitableHost(content::RenderProcessHost* process_host,
|
bool IsSuitableHost(content::RenderProcessHost* process_host,
|
||||||
const GURL& site_url) override;
|
const GURL& site_url) override;
|
||||||
bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
|
bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
|
||||||
|
|
35
shell/browser/extensions/api/BUILD.gn
Normal file
35
shell/browser/extensions/api/BUILD.gn
Normal file
|
@ -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" ]
|
||||||
|
}
|
|
@ -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 <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#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<get_strings::Params> params(
|
||||||
|
get_strings::Params::Create(*args_));
|
||||||
|
auto dict = std::make_unique<base::DictionaryValue>();
|
||||||
|
|
||||||
|
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
|
|
@ -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_
|
|
@ -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 <utility>
|
||||||
|
|
||||||
|
#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<extensions::StreamContainer> 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
|
|
@ -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 <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#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_
|
|
@ -12,13 +12,48 @@
|
||||||
#include "extensions/common/manifest_constants.h"
|
#include "extensions/common/manifest_constants.h"
|
||||||
#include "extensions/common/permissions/permissions_data.h"
|
#include "extensions/common/permissions/permissions_data.h"
|
||||||
#include "shell/browser/api/electron_api_web_contents.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 extensions {
|
||||||
|
|
||||||
|
namespace tabs = api::tabs;
|
||||||
|
|
||||||
const char kFrameNotFoundError[] = "No frame with id * in tab *.";
|
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;
|
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() : execute_tab_id_(-1) {}
|
||||||
|
|
||||||
ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {}
|
ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {}
|
||||||
|
@ -130,4 +165,149 @@ bool TabsExecuteScriptFunction::ShouldInsertCSS() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExtensionFunction::ResponseAction TabsGetFunction::Run() {
|
||||||
|
std::unique_ptr<tabs::Get::Params> 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<std::string>(
|
||||||
|
contents->web_contents()->GetLastCommittedURL().spec());
|
||||||
|
|
||||||
|
return RespondNow(ArgumentList(tabs::Get::Results::Create(std::move(tab))));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtensionFunction::ResponseAction TabsSetZoomFunction::Run() {
|
||||||
|
std::unique_ptr<tabs::SetZoom::Params> 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<tabs::GetZoom::Params> 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<tabs::GetZoomSettings::Params> 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<tabs::SetZoomSettings::Params> 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
|
} // namespace extensions
|
||||||
|
|
|
@ -44,6 +44,48 @@ class TabsExecuteScriptFunction : public ExecuteCodeInTabFunction {
|
||||||
DECLARE_EXTENSION_FUNCTION("tabs.executeScript", TABS_EXECUTESCRIPT)
|
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
|
} // namespace extensions
|
||||||
|
|
||||||
#endif // SHELL_BROWSER_EXTENSIONS_API_TABS_TABS_API_H_
|
#endif // SHELL_BROWSER_EXTENSIONS_API_TABS_TABS_API_H_
|
||||||
|
|
|
@ -5,15 +5,12 @@
|
||||||
#include "shell/browser/extensions/electron_browser_context_keyed_service_factories.h"
|
#include "shell/browser/extensions/electron_browser_context_keyed_service_factories.h"
|
||||||
|
|
||||||
#include "extensions/browser/updater/update_service_factory.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"
|
#include "shell/browser/extensions/electron_extension_system_factory.h"
|
||||||
|
|
||||||
namespace extensions {
|
namespace extensions {
|
||||||
namespace electron {
|
namespace electron {
|
||||||
|
|
||||||
void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
|
void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
|
||||||
// IdentityAPI::GetFactoryInstance();
|
|
||||||
|
|
||||||
// TODO(rockot): Remove this once UpdateService is supported across all
|
// TODO(rockot): Remove this once UpdateService is supported across all
|
||||||
// extensions embedders (and namely chrome.)
|
// extensions embedders (and namely chrome.)
|
||||||
UpdateServiceFactory::GetInstance();
|
UpdateServiceFactory::GetInstance();
|
||||||
|
|
|
@ -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 <string>
|
||||||
|
|
||||||
|
#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
|
|
@ -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 <stddef.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
#include "base/macros.h"
|
||||||
|
#include "extensions/browser/component_extension_resource_manager.h"
|
||||||
|
|
||||||
|
struct GritResourceMap;
|
||||||
|
|
||||||
|
namespace extensions {
|
||||||
|
|
||||||
|
class ElectronComponentExtensionResourceManager
|
||||||
|
: public ComponentExtensionResourceManager {
|
||||||
|
public:
|
||||||
|
ElectronComponentExtensionResourceManager();
|
||||||
|
~ElectronComponentExtensionResourceManager() override;
|
||||||
|
|
||||||
|
// Overridden from ComponentExtensionResourceManager:
|
||||||
|
bool IsComponentExtensionResource(const base::FilePath& extension_path,
|
||||||
|
const base::FilePath& resource_path,
|
||||||
|
int* resource_id) const override;
|
||||||
|
const ui::TemplateReplacements* GetTemplateReplacementsForExtension(
|
||||||
|
const std::string& extension_id) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AddComponentResourceEntries(const GritResourceMap* entries, size_t size);
|
||||||
|
|
||||||
|
// A map from a resource path to the resource ID. Used by
|
||||||
|
// IsComponentExtensionResource.
|
||||||
|
std::map<base::FilePath, int> path_to_resource_id_;
|
||||||
|
|
||||||
|
// A map from an extension ID to its i18n template replacements.
|
||||||
|
std::map<std::string, ui::TemplateReplacements>
|
||||||
|
extension_template_replacements_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ElectronComponentExtensionResourceManager);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace extensions
|
||||||
|
|
||||||
|
#endif // SHELL_BROWSER_EXTENSIONS_ELECTRON_COMPONENT_EXTENSION_RESOURCE_MANAGER_H_
|
|
@ -49,6 +49,8 @@ class ElectronExtensionLoader : public ExtensionRegistrar::Delegate {
|
||||||
void UnloadExtension(const ExtensionId& extension_id,
|
void UnloadExtension(const ExtensionId& extension_id,
|
||||||
extensions::UnloadedExtensionReason reason);
|
extensions::UnloadedExtensionReason reason);
|
||||||
|
|
||||||
|
ExtensionRegistrar* registrar() { return &extension_registrar_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// If the extension loaded successfully, enables it. If it's an app, launches
|
// If the extension loaded successfully, enables it. If it's an app, launches
|
||||||
// it. If the load failed, updates ShellKeepAliveRequester.
|
// it. If the load failed, updates ShellKeepAliveRequester.
|
||||||
|
|
|
@ -11,7 +11,11 @@
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
#include "base/files/file_util.h"
|
#include "base/files/file_util.h"
|
||||||
|
#include "base/json/json_string_value_serializer.h"
|
||||||
|
#include "base/path_service.h"
|
||||||
#include "base/task/post_task.h"
|
#include "base/task/post_task.h"
|
||||||
|
#include "chrome/browser/pdf/pdf_extension_util.h"
|
||||||
|
#include "chrome/common/chrome_paths.h"
|
||||||
#include "content/public/browser/browser_context.h"
|
#include "content/public/browser/browser_context.h"
|
||||||
#include "content/public/browser/browser_task_traits.h"
|
#include "content/public/browser/browser_task_traits.h"
|
||||||
#include "content/public/browser/browser_thread.h"
|
#include "content/public/browser/browser_thread.h"
|
||||||
|
@ -84,6 +88,35 @@ void ElectronExtensionSystem::InitForRegularProfile(bool extensions_enabled) {
|
||||||
app_sorting_ = std::make_unique<NullAppSorting>();
|
app_sorting_ = std::make_unique<NullAppSorting>();
|
||||||
extension_loader_ =
|
extension_loader_ =
|
||||||
std::make_unique<ElectronExtensionLoader>(browser_context_);
|
std::make_unique<ElectronExtensionLoader>(browser_context_);
|
||||||
|
|
||||||
|
if (!browser_context_->IsOffTheRecord())
|
||||||
|
LoadComponentExtensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<base::DictionaryValue> ParseManifest(
|
||||||
|
base::StringPiece manifest_contents) {
|
||||||
|
JSONStringValueDeserializer deserializer(manifest_contents);
|
||||||
|
std::unique_ptr<base::Value> manifest = deserializer.Deserialize(NULL, NULL);
|
||||||
|
|
||||||
|
if (!manifest.get() || !manifest->is_dict()) {
|
||||||
|
LOG(ERROR) << "Failed to parse extension manifest.";
|
||||||
|
return std::unique_ptr<base::DictionaryValue>();
|
||||||
|
}
|
||||||
|
return base::DictionaryValue::From(std::move(manifest));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElectronExtensionSystem::LoadComponentExtensions() {
|
||||||
|
std::string utf8_error;
|
||||||
|
std::string pdf_manifest_string = pdf_extension_util::GetManifest();
|
||||||
|
std::unique_ptr<base::DictionaryValue> pdf_manifest =
|
||||||
|
ParseManifest(pdf_manifest_string);
|
||||||
|
base::FilePath root_directory;
|
||||||
|
CHECK(base::PathService::Get(chrome::DIR_RESOURCES, &root_directory));
|
||||||
|
root_directory = root_directory.Append(FILE_PATH_LITERAL("pdf"));
|
||||||
|
scoped_refptr<const Extension> pdf_extension = extensions::Extension::Create(
|
||||||
|
root_directory, extensions::Manifest::COMPONENT, *pdf_manifest,
|
||||||
|
extensions::Extension::REQUIRE_KEY, &utf8_error);
|
||||||
|
extension_loader_->registrar()->AddExtension(pdf_extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtensionService* ElectronExtensionSystem::extension_service() {
|
ExtensionService* ElectronExtensionSystem::extension_service() {
|
||||||
|
|
|
@ -88,6 +88,8 @@ class ElectronExtensionSystem : public ExtensionSystem {
|
||||||
private:
|
private:
|
||||||
void OnExtensionRegisteredWithRequestContexts(
|
void OnExtensionRegisteredWithRequestContexts(
|
||||||
scoped_refptr<Extension> extension);
|
scoped_refptr<Extension> extension);
|
||||||
|
void LoadComponentExtensions();
|
||||||
|
|
||||||
content::BrowserContext* browser_context_; // Not owned.
|
content::BrowserContext* browser_context_; // Not owned.
|
||||||
|
|
||||||
// Data to be accessed on the IO thread. Must outlive process_manager_.
|
// Data to be accessed on the IO thread. Must outlive process_manager_.
|
||||||
|
|
|
@ -5,12 +5,34 @@
|
||||||
#include "shell/browser/extensions/electron_extensions_api_client.h"
|
#include "shell/browser/extensions/electron_extensions_api_client.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h"
|
||||||
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
|
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
|
||||||
#include "shell/browser/extensions/electron_messaging_delegate.h"
|
#include "shell/browser/extensions/electron_messaging_delegate.h"
|
||||||
|
|
||||||
namespace extensions {
|
namespace extensions {
|
||||||
|
|
||||||
|
class ElectronMimeHandlerViewGuestDelegate
|
||||||
|
: public MimeHandlerViewGuestDelegate {
|
||||||
|
public:
|
||||||
|
ElectronMimeHandlerViewGuestDelegate() {}
|
||||||
|
~ElectronMimeHandlerViewGuestDelegate() override {}
|
||||||
|
|
||||||
|
// MimeHandlerViewGuestDelegate.
|
||||||
|
bool HandleContextMenu(content::WebContents* web_contents,
|
||||||
|
const content::ContextMenuParams& params) override {
|
||||||
|
// TODO(nornagon): surface this event to JS
|
||||||
|
LOG(INFO) << "HCM";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void RecordLoadMetric(bool in_main_frame,
|
||||||
|
const std::string& mime_type) override {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ElectronMimeHandlerViewGuestDelegate);
|
||||||
|
};
|
||||||
|
|
||||||
ElectronExtensionsAPIClient::ElectronExtensionsAPIClient() = default;
|
ElectronExtensionsAPIClient::ElectronExtensionsAPIClient() = default;
|
||||||
ElectronExtensionsAPIClient::~ElectronExtensionsAPIClient() = default;
|
ElectronExtensionsAPIClient::~ElectronExtensionsAPIClient() = default;
|
||||||
|
|
||||||
|
@ -26,4 +48,10 @@ void ElectronExtensionsAPIClient::AttachWebContentsHelpers(
|
||||||
web_contents);
|
web_contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<MimeHandlerViewGuestDelegate>
|
||||||
|
ElectronExtensionsAPIClient::CreateMimeHandlerViewGuestDelegate(
|
||||||
|
MimeHandlerViewGuest* guest) const {
|
||||||
|
return std::make_unique<ElectronMimeHandlerViewGuestDelegate>();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace extensions
|
} // namespace extensions
|
||||||
|
|
|
@ -22,6 +22,9 @@ class ElectronExtensionsAPIClient : public ExtensionsAPIClient {
|
||||||
MessagingDelegate* GetMessagingDelegate() override;
|
MessagingDelegate* GetMessagingDelegate() override;
|
||||||
void AttachWebContentsHelpers(
|
void AttachWebContentsHelpers(
|
||||||
content::WebContents* web_contents) const override;
|
content::WebContents* web_contents) const override;
|
||||||
|
std::unique_ptr<MimeHandlerViewGuestDelegate>
|
||||||
|
CreateMimeHandlerViewGuestDelegate(
|
||||||
|
MimeHandlerViewGuest* guest) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<ElectronMessagingDelegate> messaging_delegate_;
|
std::unique_ptr<ElectronMessagingDelegate> messaging_delegate_;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "shell/browser/extensions/electron_extensions_browser_api_provider.h"
|
#include "shell/browser/extensions/electron_extensions_browser_api_provider.h"
|
||||||
|
|
||||||
#include "extensions/browser/extension_function_registry.h"
|
#include "extensions/browser/extension_function_registry.h"
|
||||||
|
#include "shell/browser/extensions/api/generated_api_registration.h"
|
||||||
#include "shell/browser/extensions/api/tabs/tabs_api.h"
|
#include "shell/browser/extensions/api/tabs/tabs_api.h"
|
||||||
|
|
||||||
namespace extensions {
|
namespace extensions {
|
||||||
|
@ -16,11 +17,8 @@ ElectronExtensionsBrowserAPIProvider::~ElectronExtensionsBrowserAPIProvider() =
|
||||||
|
|
||||||
void ElectronExtensionsBrowserAPIProvider::RegisterExtensionFunctions(
|
void ElectronExtensionsBrowserAPIProvider::RegisterExtensionFunctions(
|
||||||
ExtensionFunctionRegistry* registry) {
|
ExtensionFunctionRegistry* registry) {
|
||||||
registry->RegisterFunction<TabsExecuteScriptFunction>();
|
|
||||||
/*
|
|
||||||
// Generated APIs from Electron.
|
// Generated APIs from Electron.
|
||||||
api::ElectronGeneratedFunctionRegistry::RegisterAll(registry);
|
api::ElectronGeneratedFunctionRegistry::RegisterAll(registry);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace extensions
|
} // namespace extensions
|
||||||
|
|
|
@ -8,8 +8,12 @@
|
||||||
|
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "base/memory/ptr_util.h"
|
#include "base/memory/ptr_util.h"
|
||||||
|
#include "base/path_service.h"
|
||||||
#include "base/task/post_task.h"
|
#include "base/task/post_task.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
#include "chrome/browser/extensions/chrome_url_request_util.h"
|
||||||
|
#include "chrome/common/chrome_paths.h"
|
||||||
|
#include "chrome/common/extensions/chrome_manifest_url_handlers.h"
|
||||||
#include "components/version_info/version_info.h"
|
#include "components/version_info/version_info.h"
|
||||||
#include "content/public/browser/browser_context.h"
|
#include "content/public/browser/browser_context.h"
|
||||||
#include "content/public/browser/browser_task_traits.h"
|
#include "content/public/browser/browser_task_traits.h"
|
||||||
|
@ -20,17 +24,21 @@
|
||||||
#include "extensions/browser/component_extension_resource_manager.h"
|
#include "extensions/browser/component_extension_resource_manager.h"
|
||||||
#include "extensions/browser/core_extensions_browser_api_provider.h"
|
#include "extensions/browser/core_extensions_browser_api_provider.h"
|
||||||
#include "extensions/browser/event_router.h"
|
#include "extensions/browser/event_router.h"
|
||||||
|
#include "extensions/browser/extension_protocols.h"
|
||||||
#include "extensions/browser/null_app_sorting.h"
|
#include "extensions/browser/null_app_sorting.h"
|
||||||
#include "extensions/browser/updater/null_extension_cache.h"
|
#include "extensions/browser/updater/null_extension_cache.h"
|
||||||
#include "extensions/browser/url_request_util.h"
|
#include "extensions/browser/url_request_util.h"
|
||||||
#include "extensions/common/features/feature_channel.h"
|
#include "extensions/common/features/feature_channel.h"
|
||||||
|
#include "extensions/common/file_util.h"
|
||||||
#include "extensions/common/manifest_constants.h"
|
#include "extensions/common/manifest_constants.h"
|
||||||
#include "extensions/common/manifest_url_handlers.h"
|
#include "extensions/common/manifest_url_handlers.h"
|
||||||
|
#include "net/base/mime_util.h"
|
||||||
#include "services/network/public/mojom/url_loader.mojom.h"
|
#include "services/network/public/mojom/url_loader.mojom.h"
|
||||||
#include "shell/browser/browser.h"
|
#include "shell/browser/browser.h"
|
||||||
#include "shell/browser/electron_browser_client.h"
|
#include "shell/browser/electron_browser_client.h"
|
||||||
#include "shell/browser/electron_browser_context.h"
|
#include "shell/browser/electron_browser_context.h"
|
||||||
#include "shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h"
|
#include "shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h"
|
||||||
|
#include "shell/browser/extensions/electron_component_extension_resource_manager.h"
|
||||||
#include "shell/browser/extensions/electron_extension_host_delegate.h"
|
#include "shell/browser/extensions/electron_extension_host_delegate.h"
|
||||||
#include "shell/browser/extensions/electron_extension_system_factory.h"
|
#include "shell/browser/extensions/electron_extension_system_factory.h"
|
||||||
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
|
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
|
||||||
|
@ -38,9 +46,11 @@
|
||||||
#include "shell/browser/extensions/electron_extensions_browser_api_provider.h"
|
#include "shell/browser/extensions/electron_extensions_browser_api_provider.h"
|
||||||
#include "shell/browser/extensions/electron_navigation_ui_data.h"
|
#include "shell/browser/extensions/electron_navigation_ui_data.h"
|
||||||
#include "shell/browser/extensions/electron_process_manager_delegate.h"
|
#include "shell/browser/extensions/electron_process_manager_delegate.h"
|
||||||
|
#include "ui/base/resource/resource_bundle.h"
|
||||||
|
|
||||||
using content::BrowserContext;
|
using content::BrowserContext;
|
||||||
using content::BrowserThread;
|
using content::BrowserThread;
|
||||||
|
using extensions::ExtensionsBrowserClient;
|
||||||
|
|
||||||
namespace electron {
|
namespace electron {
|
||||||
|
|
||||||
|
@ -51,6 +61,8 @@ ElectronExtensionsBrowserClient::ElectronExtensionsBrowserClient()
|
||||||
// Electron does not have a concept of channel, so leave UNKNOWN to
|
// Electron does not have a concept of channel, so leave UNKNOWN to
|
||||||
// enable all channel-dependent extension APIs.
|
// enable all channel-dependent extension APIs.
|
||||||
extensions::SetCurrentChannel(version_info::Channel::UNKNOWN);
|
extensions::SetCurrentChannel(version_info::Channel::UNKNOWN);
|
||||||
|
resource_manager_.reset(
|
||||||
|
new extensions::ElectronComponentExtensionResourceManager());
|
||||||
|
|
||||||
AddAPIProvider(
|
AddAPIProvider(
|
||||||
std::make_unique<extensions::CoreExtensionsBrowserAPIProvider>());
|
std::make_unique<extensions::CoreExtensionsBrowserAPIProvider>());
|
||||||
|
@ -127,7 +139,28 @@ base::FilePath ElectronExtensionsBrowserClient::GetBundleResourcePath(
|
||||||
const base::FilePath& extension_resources_path,
|
const base::FilePath& extension_resources_path,
|
||||||
int* resource_id) const {
|
int* resource_id) const {
|
||||||
*resource_id = 0;
|
*resource_id = 0;
|
||||||
return base::FilePath();
|
base::FilePath chrome_resources_path;
|
||||||
|
if (!base::PathService::Get(chrome::DIR_RESOURCES, &chrome_resources_path))
|
||||||
|
return base::FilePath();
|
||||||
|
|
||||||
|
// Since component extension resources are included in
|
||||||
|
// component_extension_resources.pak file in |chrome_resources_path|,
|
||||||
|
// calculate the extension |request_relative_path| against
|
||||||
|
// |chrome_resources_path|.
|
||||||
|
if (!chrome_resources_path.IsParent(extension_resources_path))
|
||||||
|
return base::FilePath();
|
||||||
|
|
||||||
|
const base::FilePath request_relative_path =
|
||||||
|
extensions::file_util::ExtensionURLToRelativeFilePath(request.url);
|
||||||
|
if (!ExtensionsBrowserClient::Get()
|
||||||
|
->GetComponentExtensionResourceManager()
|
||||||
|
->IsComponentExtensionResource(extension_resources_path,
|
||||||
|
request_relative_path, resource_id)) {
|
||||||
|
return base::FilePath();
|
||||||
|
}
|
||||||
|
DCHECK_NE(0, *resource_id);
|
||||||
|
|
||||||
|
return request_relative_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectronExtensionsBrowserClient::LoadResourceFromResourceBundle(
|
void ElectronExtensionsBrowserClient::LoadResourceFromResourceBundle(
|
||||||
|
@ -138,7 +171,9 @@ void ElectronExtensionsBrowserClient::LoadResourceFromResourceBundle(
|
||||||
const std::string& content_security_policy,
|
const std::string& content_security_policy,
|
||||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||||
bool send_cors_header) {
|
bool send_cors_header) {
|
||||||
NOTREACHED() << "Load resources from bundles not supported.";
|
extensions::chrome_url_request_util::LoadResourceFromResourceBundle(
|
||||||
|
request, std::move(loader), resource_relative_path, resource_id,
|
||||||
|
content_security_policy, std::move(client), send_cors_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -160,8 +195,7 @@ bool AllowCrossRendererResourceLoad(const GURL& url,
|
||||||
// If there aren't any explicitly marked web accessible resources, the
|
// If there aren't any explicitly marked web accessible resources, the
|
||||||
// load should be allowed only if it is by DevTools. A close approximation is
|
// load should be allowed only if it is by DevTools. A close approximation is
|
||||||
// checking if the extension contains a DevTools page.
|
// checking if the extension contains a DevTools page.
|
||||||
if (extension && !extensions::ManifestURL::Get(
|
if (extension && !extensions::chrome_manifest_urls::GetDevToolsPage(extension)
|
||||||
extension, extensions::manifest_keys::kDevToolsPage)
|
|
||||||
.is_empty()) {
|
.is_empty()) {
|
||||||
*allowed = true;
|
*allowed = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -255,7 +289,7 @@ ElectronExtensionsBrowserClient::CreateRuntimeAPIDelegate(
|
||||||
|
|
||||||
const extensions::ComponentExtensionResourceManager*
|
const extensions::ComponentExtensionResourceManager*
|
||||||
ElectronExtensionsBrowserClient::GetComponentExtensionResourceManager() {
|
ElectronExtensionsBrowserClient::GetComponentExtensionResourceManager() {
|
||||||
return NULL;
|
return resource_manager_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectronExtensionsBrowserClient::BroadcastEventToRenderers(
|
void ElectronExtensionsBrowserClient::BroadcastEventToRenderers(
|
||||||
|
|
|
@ -24,6 +24,7 @@ class KioskDelegate;
|
||||||
class ProcessManagerDelegate;
|
class ProcessManagerDelegate;
|
||||||
class ElectronProcessManagerDelegate;
|
class ElectronProcessManagerDelegate;
|
||||||
class ProcessMap;
|
class ProcessMap;
|
||||||
|
class ElectronComponentExtensionResourceManager;
|
||||||
} // namespace extensions
|
} // namespace extensions
|
||||||
|
|
||||||
namespace electron {
|
namespace electron {
|
||||||
|
@ -139,6 +140,9 @@ class ElectronExtensionsBrowserClient
|
||||||
// The extension cache used for download and installation.
|
// The extension cache used for download and installation.
|
||||||
std::unique_ptr<extensions::ExtensionCache> extension_cache_;
|
std::unique_ptr<extensions::ExtensionCache> extension_cache_;
|
||||||
|
|
||||||
|
std::unique_ptr<extensions::ElectronComponentExtensionResourceManager>
|
||||||
|
resource_manager_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ElectronExtensionsBrowserClient);
|
DISALLOW_COPY_AND_ASSIGN(ElectronExtensionsBrowserClient);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
63
shell/browser/plugins/plugin_utils.cc
Normal file
63
shell/browser/plugins/plugin_utils.cc
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright 2016 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/plugins/plugin_utils.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/values.h"
|
||||||
|
#include "content/public/common/webplugininfo.h"
|
||||||
|
#include "extensions/buildflags/buildflags.h"
|
||||||
|
#include "url/gurl.h"
|
||||||
|
#include "url/origin.h"
|
||||||
|
|
||||||
|
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||||
|
#include "extensions/browser/extension_registry.h"
|
||||||
|
#include "extensions/browser/extension_util.h"
|
||||||
|
#include "extensions/common/constants.h"
|
||||||
|
#include "extensions/common/extension.h"
|
||||||
|
#include "extensions/common/manifest_handlers/mime_types_handler.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::string PluginUtils::GetExtensionIdForMimeType(
|
||||||
|
content::BrowserContext* browser_context,
|
||||||
|
const std::string& mime_type) {
|
||||||
|
auto map = GetMimeTypeToExtensionIdMap(browser_context);
|
||||||
|
auto it = map.find(mime_type);
|
||||||
|
if (it != map.end())
|
||||||
|
return it->second;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
base::flat_map<std::string, std::string>
|
||||||
|
PluginUtils::GetMimeTypeToExtensionIdMap(
|
||||||
|
content::BrowserContext* browser_context) {
|
||||||
|
base::flat_map<std::string, std::string> mime_type_to_extension_id_map;
|
||||||
|
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||||
|
std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist();
|
||||||
|
// Go through the white-listed extensions and try to use them to intercept
|
||||||
|
// the URL request.
|
||||||
|
for (const std::string& extension_id : whitelist) {
|
||||||
|
const extensions::Extension* extension =
|
||||||
|
extensions::ExtensionRegistry::Get(browser_context)
|
||||||
|
->enabled_extensions()
|
||||||
|
.GetByID(extension_id);
|
||||||
|
// The white-listed extension may not be installed, so we have to nullptr
|
||||||
|
// check |extension|.
|
||||||
|
if (!extension) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension)) {
|
||||||
|
for (const auto& supported_mime_type : handler->mime_type_set()) {
|
||||||
|
DCHECK(!base::Contains(mime_type_to_extension_id_map,
|
||||||
|
supported_mime_type));
|
||||||
|
mime_type_to_extension_id_map[supported_mime_type] = extension_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return mime_type_to_extension_id_map;
|
||||||
|
}
|
34
shell/browser/plugins/plugin_utils.h
Normal file
34
shell/browser/plugins/plugin_utils.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright 2016 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_PLUGINS_PLUGIN_UTILS_H_
|
||||||
|
#define SHELL_BROWSER_PLUGINS_PLUGIN_UTILS_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "base/containers/flat_map.h"
|
||||||
|
#include "base/macros.h"
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
class BrowserContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginUtils {
|
||||||
|
public:
|
||||||
|
// If there's an extension that is allowed to handle |mime_type|, returns its
|
||||||
|
// ID. Otherwise returns an empty string.
|
||||||
|
static std::string GetExtensionIdForMimeType(
|
||||||
|
content::BrowserContext* browser_context,
|
||||||
|
const std::string& mime_type);
|
||||||
|
|
||||||
|
// Returns a map populated with MIME types that are handled by an extension as
|
||||||
|
// keys and the corresponding extensions Ids as values.
|
||||||
|
static base::flat_map<std::string, std::string> GetMimeTypeToExtensionIdMap(
|
||||||
|
content::BrowserContext* browser_context);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_IMPLICIT_CONSTRUCTORS(PluginUtils);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHELL_BROWSER_PLUGINS_PLUGIN_UTILS_H_
|
|
@ -50,11 +50,10 @@
|
||||||
#include "ui/display/screen.h"
|
#include "ui/display/screen.h"
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
#include "chrome/common/extensions/chrome_manifest_url_handlers.h"
|
||||||
#include "content/public/browser/child_process_security_policy.h"
|
#include "content/public/browser/child_process_security_policy.h"
|
||||||
#include "content/public/browser/render_process_host.h"
|
#include "content/public/browser/render_process_host.h"
|
||||||
#include "extensions/browser/extension_registry.h"
|
#include "extensions/browser/extension_registry.h"
|
||||||
#include "extensions/common/manifest_constants.h"
|
|
||||||
#include "extensions/common/manifest_url_handlers.h"
|
|
||||||
#include "extensions/common/permissions/permissions_data.h"
|
#include "extensions/common/permissions/permissions_data.h"
|
||||||
#include "shell/browser/electron_browser_context.h"
|
#include "shell/browser/electron_browser_context.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -601,8 +600,8 @@ void InspectableWebContentsImpl::AddDevToolsExtensionsToClient() {
|
||||||
|
|
||||||
base::ListValue results;
|
base::ListValue results;
|
||||||
for (auto& extension : registry->enabled_extensions()) {
|
for (auto& extension : registry->enabled_extensions()) {
|
||||||
auto devtools_page_url = extensions::ManifestURL::Get(
|
auto devtools_page_url =
|
||||||
extension.get(), extensions::manifest_keys::kDevToolsPage);
|
extensions::chrome_manifest_urls::GetDevToolsPage(extension.get());
|
||||||
if (devtools_page_url.is_empty())
|
if (devtools_page_url.is_empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,8 @@ const char kRunAsNode[] = "ELECTRON_RUN_AS_NODE";
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||||
const char kPdfPluginMimeType[] = "application/x-google-chrome-pdf";
|
const char kPdfPluginMimeType[] = "application/x-google-chrome-pdf";
|
||||||
const char kPdfPluginPath[] = "chrome://pdf-viewer/";
|
const base::FilePath::CharType kPdfPluginPath[] =
|
||||||
const char kPdfPluginSrc[] = "src";
|
FILE_PATH_LITERAL("internal-pdf-viewer");
|
||||||
|
|
||||||
const char kPdfViewerUIOrigin[] = "chrome://pdf-viewer/";
|
|
||||||
const char kPdfViewerUIHost[] = "pdf-viewer";
|
|
||||||
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
|
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||||
|
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#ifndef SHELL_COMMON_ELECTRON_CONSTANTS_H_
|
#ifndef SHELL_COMMON_ELECTRON_CONSTANTS_H_
|
||||||
#define SHELL_COMMON_ELECTRON_CONSTANTS_H_
|
#define SHELL_COMMON_ELECTRON_CONSTANTS_H_
|
||||||
|
|
||||||
|
#include "base/files/file_path.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
#include "electron/buildflags/buildflags.h"
|
#include "electron/buildflags/buildflags.h"
|
||||||
|
|
||||||
|
@ -39,12 +40,7 @@ extern const char kRunAsNode[];
|
||||||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||||
// The MIME type used for the PDF plugin.
|
// The MIME type used for the PDF plugin.
|
||||||
extern const char kPdfPluginMimeType[];
|
extern const char kPdfPluginMimeType[];
|
||||||
extern const char kPdfPluginPath[];
|
extern const base::FilePath::CharType kPdfPluginPath[];
|
||||||
extern const char kPdfPluginSrc[];
|
|
||||||
|
|
||||||
// Constants for PDF viewer webui.
|
|
||||||
extern const char kPdfViewerUIOrigin[];
|
|
||||||
extern const char kPdfViewerUIHost[];
|
|
||||||
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
|
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||||
|
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|
|
@ -22,6 +22,7 @@ group("extensions_features") {
|
||||||
public_deps = [
|
public_deps = [
|
||||||
":api_features",
|
":api_features",
|
||||||
":manifest_features",
|
":manifest_features",
|
||||||
|
":permission_features",
|
||||||
|
|
||||||
# TODO(devlin): It would be nicer to have this dependency hoisted up to
|
# TODO(devlin): It would be nicer to have this dependency hoisted up to
|
||||||
# //extensions/common (since that's where it's consumed), but there's some
|
# //extensions/common (since that's where it's consumed), but there's some
|
||||||
|
@ -36,6 +37,7 @@ group("extensions_features") {
|
||||||
generated_json_strings("generated_api_json_strings") {
|
generated_json_strings("generated_api_json_strings") {
|
||||||
sources = [
|
sources = [
|
||||||
"extension.json",
|
"extension.json",
|
||||||
|
"resources_private.idl",
|
||||||
"tabs.json",
|
"tabs.json",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -50,7 +52,10 @@ generated_json_strings("generated_api_json_strings") {
|
||||||
}
|
}
|
||||||
|
|
||||||
generated_types("generated_api_types") {
|
generated_types("generated_api_types") {
|
||||||
sources = [ "tabs.json" ]
|
sources = [
|
||||||
|
"resources_private.idl",
|
||||||
|
"tabs.json",
|
||||||
|
]
|
||||||
configs = [ "//build/config:precompiled_headers" ]
|
configs = [ "//build/config:precompiled_headers" ]
|
||||||
schema_include_rules = "extensions/common/api:extensions::api::%(namespace)s"
|
schema_include_rules = "extensions/common/api:extensions::api::%(namespace)s"
|
||||||
|
|
||||||
|
@ -73,3 +78,10 @@ json_features("api_features") {
|
||||||
sources = [ "_api_features.json" ]
|
sources = [ "_api_features.json" ]
|
||||||
visibility = [ ":extensions_features" ]
|
visibility = [ ":extensions_features" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json_features("permission_features") {
|
||||||
|
feature_type = "PermissionFeature"
|
||||||
|
method_name = "AddElectronPermissionFeatures"
|
||||||
|
sources = [ "_permission_features.json" ]
|
||||||
|
visibility = [ ":extensions_features" ]
|
||||||
|
}
|
||||||
|
|
|
@ -15,5 +15,21 @@
|
||||||
},
|
},
|
||||||
"extension.getURL": {
|
"extension.getURL": {
|
||||||
"contexts": ["blessed_extension", "unblessed_extension", "content_script"]
|
"contexts": ["blessed_extension", "unblessed_extension", "content_script"]
|
||||||
}
|
},
|
||||||
|
"mimeHandlerViewGuestInternal": {
|
||||||
|
"internal": true,
|
||||||
|
"contexts": "all",
|
||||||
|
"channel": "stable",
|
||||||
|
"matches": ["<all_urls>"]
|
||||||
|
},
|
||||||
|
"resourcesPrivate": [{
|
||||||
|
"dependencies": ["permission:resourcesPrivate"],
|
||||||
|
"contexts": ["blessed_extension"]
|
||||||
|
}, {
|
||||||
|
"channel": "stable",
|
||||||
|
"contexts": ["webui"],
|
||||||
|
"matches": [
|
||||||
|
"chrome://print/*"
|
||||||
|
]
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
|
|
9
shell/common/extensions/api/_permission_features.json
Normal file
9
shell/common/extensions/api/_permission_features.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"resourcesPrivate": {
|
||||||
|
"channel": "stable",
|
||||||
|
"extension_types": [
|
||||||
|
"extension"
|
||||||
|
],
|
||||||
|
"location": "component"
|
||||||
|
}
|
||||||
|
}
|
23
shell/common/extensions/api/resources_private.idl
Normal file
23
shell/common/extensions/api/resources_private.idl
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// resourcesPrivate.
|
||||||
|
namespace resourcesPrivate {
|
||||||
|
enum Component { identity, pdf };
|
||||||
|
|
||||||
|
callback GetStringsCallback = void (object result);
|
||||||
|
|
||||||
|
interface Functions {
|
||||||
|
// Gets localized strings for a component extension. Includes default WebUI
|
||||||
|
// loadTimeData values for text and language settings (fontsize, fontfamily,
|
||||||
|
// language, textdirection). See
|
||||||
|
// chrome/browser/extensions/api/resources_private/resources_private_api.cc
|
||||||
|
// for instructions on adding a new component to this API.
|
||||||
|
//
|
||||||
|
// |component| : Internal chrome component to get strings for.
|
||||||
|
// |callback| : Called with a dictionary mapping names to strings.
|
||||||
|
static void getStrings(Component component,
|
||||||
|
GetStringsCallback callback);
|
||||||
|
};
|
||||||
|
};
|
|
@ -2,7 +2,142 @@
|
||||||
{
|
{
|
||||||
"namespace": "tabs",
|
"namespace": "tabs",
|
||||||
"description": "Use the <code>chrome.tabs</code> API to interact with the browser's tab system. You can use this API to create, modify, and rearrange tabs in the browser.",
|
"description": "Use the <code>chrome.tabs</code> API to interact with the browser's tab system. You can use this API to create, modify, and rearrange tabs in the browser.",
|
||||||
|
"types": [
|
||||||
|
{ "id": "MutedInfoReason",
|
||||||
|
"type": "string",
|
||||||
|
"description": "An event that caused a muted state change.",
|
||||||
|
"enum": [
|
||||||
|
{"name": "user", "description": "A user input action set the muted state."},
|
||||||
|
{"name": "capture", "description": "Tab capture was started, forcing a muted state change."},
|
||||||
|
{"name": "extension", "description": "An extension, identified by the extensionId field, set the muted state."}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "MutedInfo",
|
||||||
|
"type": "object",
|
||||||
|
"description": "The tab's muted state and the reason for the last state change.",
|
||||||
|
"properties": {
|
||||||
|
"muted": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the tab is muted (prevented from playing sound). The tab may be muted even if it has not played or is not currently playing sound. Equivalent to whether the 'muted' audio indicator is showing."
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"$ref": "MutedInfoReason",
|
||||||
|
"optional": true,
|
||||||
|
"description": "The reason the tab was muted or unmuted. Not set if the tab's mute state has never been changed."
|
||||||
|
},
|
||||||
|
"extensionId": {
|
||||||
|
"type": "string",
|
||||||
|
"optional": true,
|
||||||
|
"description": "The ID of the extension that changed the muted state. Not set if an extension was not the reason the muted state last changed."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Tab",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {"type": "integer", "minimum": -1, "optional": true, "description": "The ID of the tab. Tab IDs are unique within a browser session. Under some circumstances a tab may not be assigned an ID; for example, when querying foreign tabs using the $(ref:sessions) API, in which case a session ID may be present. Tab ID can also be set to <code>chrome.tabs.TAB_ID_NONE</code> for apps and devtools windows."},
|
||||||
|
// TODO(kalman): Investigate how this is ending up as -1 (based on window type? a bug?) and whether it should be optional instead.
|
||||||
|
"index": {"type": "integer", "minimum": -1, "description": "The zero-based index of the tab within its window."},
|
||||||
|
"windowId": {"type": "integer", "minimum": 0, "description": "The ID of the window that contains the tab."},
|
||||||
|
"openerTabId": {"type": "integer", "minimum": 0, "optional": true, "description": "The ID of the tab that opened this tab, if any. This property is only present if the opener tab still exists."},
|
||||||
|
"selected": {"type": "boolean", "description": "Whether the tab is selected.", "deprecated": "Please use $(ref:tabs.Tab.highlighted)."},
|
||||||
|
"highlighted": {"type": "boolean", "description": "Whether the tab is highlighted."},
|
||||||
|
"active": {"type": "boolean", "description": "Whether the tab is active in its window. Does not necessarily mean the window is focused."},
|
||||||
|
"pinned": {"type": "boolean", "description": "Whether the tab is pinned."},
|
||||||
|
"audible": {"type": "boolean", "optional": true, "description": "Whether the tab has produced sound over the past couple of seconds (but it might not be heard if also muted). Equivalent to whether the 'speaker audio' indicator is showing."},
|
||||||
|
"discarded": {"type": "boolean", "description": "Whether the tab is discarded. A discarded tab is one whose content has been unloaded from memory, but is still visible in the tab strip. Its content is reloaded the next time it is activated."},
|
||||||
|
"autoDiscardable": {"type": "boolean", "description": "Whether the tab can be discarded automatically by the browser when resources are low."},
|
||||||
|
"mutedInfo": {"$ref": "MutedInfo", "optional": true, "description": "The tab's muted state and the reason for the last state change."},
|
||||||
|
"url": {"type": "string", "optional": true, "description": "The last committed URL of the main frame of the tab. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission and may be an empty string if the tab has not yet committed. See also $(ref:Tab.pendingUrl)."},
|
||||||
|
"pendingUrl": {"type": "string", "optional": true, "description": "The URL the tab is navigating to, before it has committed. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission and there is a pending navigation."},
|
||||||
|
"title": {"type": "string", "optional": true, "description": "The title of the tab. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission."},
|
||||||
|
"favIconUrl": {"type": "string", "optional": true, "description": "The URL of the tab's favicon. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission. It may also be an empty string if the tab is loading."},
|
||||||
|
"status": {"type": "string", "optional": true, "description": "Either <em>loading</em> or <em>complete</em>."},
|
||||||
|
"incognito": {"type": "boolean", "description": "Whether the tab is in an incognito window."},
|
||||||
|
"width": {"type": "integer", "optional": true, "description": "The width of the tab in pixels."},
|
||||||
|
"height": {"type": "integer", "optional": true, "description": "The height of the tab in pixels."},
|
||||||
|
"sessionId": {"type": "string", "optional": true, "description": "The session ID used to uniquely identify a tab obtained from the $(ref:sessions) API."}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ZoomSettingsMode",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Defines how zoom changes are handled, i.e., which entity is responsible for the actual scaling of the page; defaults to <code>automatic</code>.",
|
||||||
|
"enum": [
|
||||||
|
{
|
||||||
|
"name": "automatic",
|
||||||
|
"description": "Zoom changes are handled automatically by the browser."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "manual",
|
||||||
|
"description": "Overrides the automatic handling of zoom changes. The <code>onZoomChange</code> event will still be dispatched, and it is the extension's responsibility to listen for this event and manually scale the page. This mode does not support <code>per-origin</code> zooming, and thus ignores the <code>scope</code> zoom setting and assumes <code>per-tab</code>."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "disabled",
|
||||||
|
"description": "Disables all zooming in the tab. The tab reverts to the default zoom level, and all attempted zoom changes are ignored."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ZoomSettingsScope",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Defines whether zoom changes persist for the page's origin, or only take effect in this tab; defaults to <code>per-origin</code> when in <code>automatic</code> mode, and <code>per-tab</code> otherwise.",
|
||||||
|
"enum": [
|
||||||
|
{
|
||||||
|
"name": "per-origin",
|
||||||
|
"description": "Zoom changes persist in the zoomed page's origin, i.e., all other tabs navigated to that same origin are zoomed as well. Moreover, <code>per-origin</code> zoom changes are saved with the origin, meaning that when navigating to other pages in the same origin, they are all zoomed to the same zoom factor. The <code>per-origin</code> scope is only available in the <code>automatic</code> mode."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "per-tab",
|
||||||
|
"description": "Zoom changes only take effect in this tab, and zoom changes in other tabs do not affect the zooming of this tab. Also, <code>per-tab</code> zoom changes are reset on navigation; navigating a tab always loads pages with their <code>per-origin</code> zoom factors."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ZoomSettings",
|
||||||
|
"type": "object",
|
||||||
|
"description": "Defines how zoom changes in a tab are handled and at what scope.",
|
||||||
|
"properties": {
|
||||||
|
"mode": {
|
||||||
|
"$ref": "ZoomSettingsMode",
|
||||||
|
"description": "Defines how zoom changes are handled, i.e., which entity is responsible for the actual scaling of the page; defaults to <code>automatic</code>.",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"$ref": "ZoomSettingsScope",
|
||||||
|
"description": "Defines whether zoom changes persist for the page's origin, or only take effect in this tab; defaults to <code>per-origin</code> when in <code>automatic</code> mode, and <code>per-tab</code> otherwise.",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"defaultZoomFactor": {
|
||||||
|
"type": "number",
|
||||||
|
"optional": true,
|
||||||
|
"description": "Used to return the default zoom level for the current tab in calls to tabs.getZoomSettings."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"functions": [
|
"functions": [
|
||||||
|
{
|
||||||
|
"name": "get",
|
||||||
|
"type": "function",
|
||||||
|
"description": "Retrieves details about the specified tab.",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"name": "tabId",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"name": "callback",
|
||||||
|
"parameters": [
|
||||||
|
{"name": "tab", "$ref": "Tab"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "executeScript",
|
"name": "executeScript",
|
||||||
"type": "function",
|
"type": "function",
|
||||||
|
@ -81,6 +216,127 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "setZoom",
|
||||||
|
"type": "function",
|
||||||
|
"description": "Zooms a specified tab.",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"name": "tabId",
|
||||||
|
"minimum": 0,
|
||||||
|
"optional": true,
|
||||||
|
"description": "The ID of the tab to zoom; defaults to the active tab of the current window."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"name": "zoomFactor",
|
||||||
|
"description": "The new zoom factor. A value of <code>0</code> sets the tab to its current default zoom factor. Values greater than <code>0</code> specify a (possibly non-default) zoom factor for the tab."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"name": "callback",
|
||||||
|
"optional": true,
|
||||||
|
"description": "Called after the zoom factor has been changed.",
|
||||||
|
"parameters": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "getZoom",
|
||||||
|
"type": "function",
|
||||||
|
"description": "Gets the current zoom factor of a specified tab.",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"name": "tabId",
|
||||||
|
"minimum": 0,
|
||||||
|
"optional": true,
|
||||||
|
"description": "The ID of the tab to get the current zoom factor from; defaults to the active tab of the current window."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"name": "callback",
|
||||||
|
"description": "Called with the tab's current zoom factor after it has been fetched.",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"name": "zoomFactor",
|
||||||
|
"description": "The tab's current zoom factor."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "setZoomSettings",
|
||||||
|
"type": "function",
|
||||||
|
"description": "Sets the zoom settings for a specified tab, which define how zoom changes are handled. These settings are reset to defaults upon navigating the tab.",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"name": "tabId",
|
||||||
|
"optional": true,
|
||||||
|
"minimum": 0,
|
||||||
|
"description": "The ID of the tab to change the zoom settings for; defaults to the active tab of the current window."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "ZoomSettings",
|
||||||
|
"name": "zoomSettings",
|
||||||
|
"description": "Defines how zoom changes are handled and at what scope."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"name": "callback",
|
||||||
|
"optional": true,
|
||||||
|
"description": "Called after the zoom settings are changed.",
|
||||||
|
"parameters": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "getZoomSettings",
|
||||||
|
"type": "function",
|
||||||
|
"description": "Gets the current zoom settings of a specified tab.",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"name": "tabId",
|
||||||
|
"optional": true,
|
||||||
|
"minimum": 0,
|
||||||
|
"description": "The ID of the tab to get the current zoom settings from; defaults to the active tab of the current window."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"name": "callback",
|
||||||
|
"description": "Called with the tab's current zoom settings.",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "ZoomSettings",
|
||||||
|
"name": "zoomSettings",
|
||||||
|
"description": "The tab's current zoom settings."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"name": "onZoomChange",
|
||||||
|
"type": "function",
|
||||||
|
"description": "Fired when a tab is zoomed.",
|
||||||
|
"parameters": [{
|
||||||
|
"type": "object",
|
||||||
|
"name": "ZoomChangeInfo",
|
||||||
|
"properties": {
|
||||||
|
"tabId": {"type": "integer", "minimum": 0},
|
||||||
|
"oldZoomFactor": {"type": "number"},
|
||||||
|
"newZoomFactor": {"type": "number"},
|
||||||
|
"zoomSettings": {"$ref": "ZoomSettings"}
|
||||||
|
}
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "base/containers/span.h"
|
#include "base/containers/span.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
#include "chrome/common/extensions/chrome_manifest_url_handlers.h"
|
||||||
#include "electron/buildflags/buildflags.h"
|
#include "electron/buildflags/buildflags.h"
|
||||||
#include "electron/shell/common/extensions/api/generated_schemas.h"
|
#include "electron/shell/common/extensions/api/generated_schemas.h"
|
||||||
#include "extensions/common/alias.h"
|
#include "extensions/common/alias.h"
|
||||||
|
@ -23,45 +24,20 @@
|
||||||
#include "extensions/common/permissions/permissions_info.h"
|
#include "extensions/common/permissions/permissions_info.h"
|
||||||
#include "shell/common/extensions/api/api_features.h"
|
#include "shell/common/extensions/api/api_features.h"
|
||||||
#include "shell/common/extensions/api/manifest_features.h"
|
#include "shell/common/extensions/api/manifest_features.h"
|
||||||
|
#include "shell/common/extensions/api/permission_features.h"
|
||||||
|
|
||||||
namespace extensions {
|
namespace extensions {
|
||||||
|
|
||||||
namespace keys = manifest_keys;
|
namespace keys = manifest_keys;
|
||||||
namespace errors = manifest_errors;
|
namespace errors = manifest_errors;
|
||||||
|
|
||||||
// Parses the "devtools_page" manifest key.
|
|
||||||
class DevToolsPageHandler : public ManifestHandler {
|
|
||||||
public:
|
|
||||||
DevToolsPageHandler() = default;
|
|
||||||
~DevToolsPageHandler() override = default;
|
|
||||||
|
|
||||||
bool Parse(Extension* extension, base::string16* error) override {
|
|
||||||
std::unique_ptr<ManifestURL> manifest_url(new ManifestURL);
|
|
||||||
std::string devtools_str;
|
|
||||||
if (!extension->manifest()->GetString(keys::kDevToolsPage, &devtools_str)) {
|
|
||||||
*error = base::ASCIIToUTF16(errors::kInvalidDevToolsPage);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
manifest_url->url_ = extension->GetResourceURL(devtools_str);
|
|
||||||
extension->SetManifestData(keys::kDevToolsPage, std::move(manifest_url));
|
|
||||||
PermissionsParser::AddAPIPermission(extension, APIPermission::kDevtools);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
base::span<const char* const> Keys() const override {
|
|
||||||
static constexpr const char* kKeys[] = {keys::kDevToolsPage};
|
|
||||||
return kKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(DevToolsPageHandler);
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr APIPermissionInfo::InitInfo permissions_to_register[] = {
|
constexpr APIPermissionInfo::InitInfo permissions_to_register[] = {
|
||||||
{APIPermission::kDevtools, "devtools",
|
{APIPermission::kDevtools, "devtools",
|
||||||
APIPermissionInfo::kFlagImpliesFullURLAccess |
|
APIPermissionInfo::kFlagImpliesFullURLAccess |
|
||||||
APIPermissionInfo::kFlagCannotBeOptional |
|
APIPermissionInfo::kFlagCannotBeOptional |
|
||||||
APIPermissionInfo::kFlagInternal},
|
APIPermissionInfo::kFlagInternal},
|
||||||
|
{APIPermission::kResourcesPrivate, "resourcesPrivate",
|
||||||
|
APIPermissionInfo::kFlagCannotBeOptional},
|
||||||
};
|
};
|
||||||
base::span<const APIPermissionInfo::InitInfo> GetPermissionInfos() {
|
base::span<const APIPermissionInfo::InitInfo> GetPermissionInfos() {
|
||||||
return base::make_span(permissions_to_register);
|
return base::make_span(permissions_to_register);
|
||||||
|
@ -89,7 +65,7 @@ void ElectronExtensionsAPIProvider::AddManifestFeatures(
|
||||||
|
|
||||||
void ElectronExtensionsAPIProvider::AddPermissionFeatures(
|
void ElectronExtensionsAPIProvider::AddPermissionFeatures(
|
||||||
extensions::FeatureProvider* provider) {
|
extensions::FeatureProvider* provider) {
|
||||||
// No shell-specific permission features.
|
extensions::AddElectronPermissionFeatures(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectronExtensionsAPIProvider::AddBehaviorFeatures(
|
void ElectronExtensionsAPIProvider::AddBehaviorFeatures(
|
||||||
|
|
|
@ -117,7 +117,6 @@ extensions::URLPatternSet
|
||||||
ElectronExtensionsClient::GetPermittedChromeSchemeHosts(
|
ElectronExtensionsClient::GetPermittedChromeSchemeHosts(
|
||||||
const extensions::Extension* extension,
|
const extensions::Extension* extension,
|
||||||
const extensions::APIPermissionSet& api_permissions) const {
|
const extensions::APIPermissionSet& api_permissions) const {
|
||||||
NOTIMPLEMENTED();
|
|
||||||
return extensions::URLPatternSet();
|
return extensions::URLPatternSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,12 +67,16 @@
|
||||||
#endif // BUILDFLAG(ENABLE_PRINTING)
|
#endif // BUILDFLAG(ENABLE_PRINTING)
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
#include "content/public/common/webplugininfo.h"
|
||||||
|
#include "extensions/common/constants.h"
|
||||||
#include "extensions/common/extensions_client.h"
|
#include "extensions/common/extensions_client.h"
|
||||||
#include "extensions/renderer/dispatcher.h"
|
#include "extensions/renderer/dispatcher.h"
|
||||||
#include "extensions/renderer/extension_frame_helper.h"
|
#include "extensions/renderer/extension_frame_helper.h"
|
||||||
#include "extensions/renderer/guest_view/extensions_guest_view_container.h"
|
#include "extensions/renderer/guest_view/extensions_guest_view_container.h"
|
||||||
#include "extensions/renderer/guest_view/extensions_guest_view_container_dispatcher.h"
|
#include "extensions/renderer/guest_view/extensions_guest_view_container_dispatcher.h"
|
||||||
#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
|
#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
|
||||||
|
#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h"
|
||||||
#include "shell/common/extensions/electron_extensions_client.h"
|
#include "shell/common/extensions/electron_extensions_client.h"
|
||||||
#include "shell/renderer/extensions/electron_extensions_renderer_client.h"
|
#include "shell/renderer/extensions/electron_extensions_renderer_client.h"
|
||||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
@ -271,6 +275,11 @@ void RendererClientBase::RenderFrameCreated(
|
||||||
new extensions::ExtensionFrameHelper(render_frame, dispatcher);
|
new extensions::ExtensionFrameHelper(render_frame, dispatcher);
|
||||||
|
|
||||||
dispatcher->OnRenderFrameCreated(render_frame);
|
dispatcher->OnRenderFrameCreated(render_frame);
|
||||||
|
|
||||||
|
render_frame->GetAssociatedInterfaceRegistry()->AddInterface(
|
||||||
|
base::BindRepeating(
|
||||||
|
&extensions::MimeHandlerViewContainerManager::BindReceiver,
|
||||||
|
render_frame->GetRoutingID()));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||||
|
@ -337,6 +346,52 @@ void RendererClientBase::DidSetUserAgent(const std::string& user_agent) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
content::BrowserPluginDelegate* RendererClientBase::CreateBrowserPluginDelegate(
|
||||||
|
content::RenderFrame* render_frame,
|
||||||
|
const content::WebPluginInfo& info,
|
||||||
|
const std::string& mime_type,
|
||||||
|
const GURL& original_url) {
|
||||||
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
// TODO(nornagon): check the mime type isn't content::kBrowserPluginMimeType?
|
||||||
|
return new extensions::MimeHandlerViewContainer(render_frame, info, mime_type,
|
||||||
|
original_url);
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RendererClientBase::IsPluginHandledExternally(
|
||||||
|
content::RenderFrame* render_frame,
|
||||||
|
const blink::WebElement& plugin_element,
|
||||||
|
const GURL& original_url,
|
||||||
|
const std::string& mime_type) {
|
||||||
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS)
|
||||||
|
DCHECK(plugin_element.HasHTMLTagName("object") ||
|
||||||
|
plugin_element.HasHTMLTagName("embed"));
|
||||||
|
// TODO(nornagon): this info should be shared with the data in
|
||||||
|
// electron_content_client.cc / ComputeBuiltInPlugins.
|
||||||
|
content::WebPluginInfo info;
|
||||||
|
info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN;
|
||||||
|
info.name = base::UTF8ToUTF16("Chromium PDF Viewer");
|
||||||
|
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");
|
||||||
|
return extensions::MimeHandlerViewContainerManager::Get(
|
||||||
|
content::RenderFrame::FromWebFrame(
|
||||||
|
plugin_element.GetDocument().GetFrame()),
|
||||||
|
true /* create_if_does_not_exist */)
|
||||||
|
->CreateFrameContainer(plugin_element, original_url, mime_type, info);
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RendererClientBase::IsOriginIsolatedPepperPlugin(
|
||||||
|
const base::FilePath& plugin_path) {
|
||||||
|
return plugin_path.value() == kPdfPluginPath;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<blink::WebPrescientNetworking>
|
std::unique_ptr<blink::WebPrescientNetworking>
|
||||||
RendererClientBase::CreatePrescientNetworking(
|
RendererClientBase::CreatePrescientNetworking(
|
||||||
content::RenderFrame* render_frame) {
|
content::RenderFrame* render_frame) {
|
||||||
|
|
|
@ -100,6 +100,16 @@ class RendererClientBase : public content::ContentRendererClient
|
||||||
override;
|
override;
|
||||||
bool IsKeySystemsUpdateNeeded() override;
|
bool IsKeySystemsUpdateNeeded() override;
|
||||||
void DidSetUserAgent(const std::string& user_agent) override;
|
void DidSetUserAgent(const std::string& user_agent) override;
|
||||||
|
content::BrowserPluginDelegate* CreateBrowserPluginDelegate(
|
||||||
|
content::RenderFrame* render_frame,
|
||||||
|
const content::WebPluginInfo& info,
|
||||||
|
const std::string& mime_type,
|
||||||
|
const GURL& original_url) override;
|
||||||
|
bool IsPluginHandledExternally(content::RenderFrame* render_frame,
|
||||||
|
const blink::WebElement& plugin_element,
|
||||||
|
const GURL& original_url,
|
||||||
|
const std::string& mime_type) override;
|
||||||
|
bool IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) override;
|
||||||
|
|
||||||
void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override;
|
void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override;
|
||||||
void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override;
|
void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override;
|
||||||
|
|
|
@ -973,117 +973,25 @@ describe('chromium features', () => {
|
||||||
|
|
||||||
ifdescribe(features.isPDFViewerEnabled())('PDF Viewer', () => {
|
ifdescribe(features.isPDFViewerEnabled())('PDF Viewer', () => {
|
||||||
const pdfSource = url.format({
|
const pdfSource = url.format({
|
||||||
pathname: path.join(fixturesPath, 'assets', 'cat.pdf').replace(/\\/g, '/'),
|
pathname: path.join(__dirname, 'fixtures', 'cat.pdf').replace(/\\/g, '/'),
|
||||||
protocol: 'file',
|
|
||||||
slashes: true
|
|
||||||
})
|
|
||||||
const pdfSourceWithParams = url.format({
|
|
||||||
pathname: path.join(fixturesPath, 'assets', 'cat.pdf').replace(/\\/g, '/'),
|
|
||||||
query: {
|
|
||||||
a: 1,
|
|
||||||
b: 2
|
|
||||||
},
|
|
||||||
protocol: 'file',
|
protocol: 'file',
|
||||||
slashes: true
|
slashes: true
|
||||||
})
|
})
|
||||||
|
|
||||||
const createBrowserWindow = ({ plugins, preload }: { plugins: boolean, preload: string }) => {
|
it('opens when loading a pdf resource as top level navigation', async () => {
|
||||||
return new BrowserWindow({
|
|
||||||
show: false,
|
|
||||||
webPreferences: {
|
|
||||||
preload: path.join(fixturesPath, 'module', preload),
|
|
||||||
plugins: plugins
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const testPDFIsLoadedInSubFrame = (page: string, preloadFile: string, done: Function) => {
|
|
||||||
const pagePath = url.format({
|
|
||||||
pathname: path.join(fixturesPath, 'pages', page).replace(/\\/g, '/'),
|
|
||||||
protocol: 'file',
|
|
||||||
slashes: true
|
|
||||||
})
|
|
||||||
|
|
||||||
const w = createBrowserWindow({ plugins: true, preload: preloadFile })
|
|
||||||
ipcMain.once('pdf-loaded', (event, state) => {
|
|
||||||
expect(state).to.equal('success')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
w.webContents.on('page-title-updated', () => {
|
|
||||||
const parsedURL = url.parse(w.webContents.getURL(), true)
|
|
||||||
expect(parsedURL.protocol).to.equal('chrome:')
|
|
||||||
expect(parsedURL.hostname).to.equal('pdf-viewer')
|
|
||||||
expect(parsedURL.query.src).to.equal(pagePath)
|
|
||||||
expect(w.webContents.getTitle()).to.equal('cat.pdf')
|
|
||||||
})
|
|
||||||
w.loadFile(path.join(fixturesPath, 'pages', page))
|
|
||||||
}
|
|
||||||
|
|
||||||
it('opens when loading a pdf resource as top level navigation', (done) => {
|
|
||||||
const w = createBrowserWindow({ plugins: true, preload: 'preload-pdf-loaded.js' })
|
|
||||||
ipcMain.once('pdf-loaded', (event, state) => {
|
|
||||||
expect(state).to.equal('success')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
w.webContents.on('page-title-updated', () => {
|
|
||||||
const parsedURL = url.parse(w.webContents.getURL(), true)
|
|
||||||
expect(parsedURL.protocol).to.equal('chrome:')
|
|
||||||
expect(parsedURL.hostname).to.equal('pdf-viewer')
|
|
||||||
expect(parsedURL.query.src).to.equal(pdfSource)
|
|
||||||
expect(w.webContents.getTitle()).to.equal('cat.pdf')
|
|
||||||
})
|
|
||||||
w.webContents.loadURL(pdfSource)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('opens a pdf link given params, the query string should be escaped', (done) => {
|
|
||||||
const w = createBrowserWindow({ plugins: true, preload: 'preload-pdf-loaded.js' })
|
|
||||||
ipcMain.once('pdf-loaded', (event, state) => {
|
|
||||||
expect(state).to.equal('success')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
w.webContents.on('page-title-updated', () => {
|
|
||||||
const parsedURL = url.parse(w.webContents.getURL(), true)
|
|
||||||
expect(parsedURL.protocol).to.equal('chrome:')
|
|
||||||
expect(parsedURL.hostname).to.equal('pdf-viewer')
|
|
||||||
expect(parsedURL.query.src).to.equal(pdfSourceWithParams)
|
|
||||||
expect(parsedURL.query.b).to.be.undefined()
|
|
||||||
expect(parsedURL.search!.endsWith('%3Fa%3D1%26b%3D2')).to.be.true()
|
|
||||||
expect(w.webContents.getTitle()).to.equal('cat.pdf')
|
|
||||||
})
|
|
||||||
w.webContents.loadURL(pdfSourceWithParams)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should download a pdf when plugins are disabled', async () => {
|
|
||||||
const w = createBrowserWindow({ plugins: false, preload: 'preload-pdf-loaded.js' })
|
|
||||||
w.webContents.loadURL(pdfSource)
|
|
||||||
const [state, filename, mimeType] = await new Promise(resolve => {
|
|
||||||
session.defaultSession.once('will-download', (event, item) => {
|
|
||||||
item.setSavePath(path.join(fixturesPath, 'mock.pdf'))
|
|
||||||
item.on('done', (e, state) => {
|
|
||||||
resolve([state, item.getFilename(), item.getMimeType()])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
expect(state).to.equal('completed')
|
|
||||||
expect(filename).to.equal('cat.pdf')
|
|
||||||
expect(mimeType).to.equal('application/pdf')
|
|
||||||
fs.unlinkSync(path.join(fixturesPath, 'mock.pdf'))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not open when pdf is requested as sub resource', async () => {
|
|
||||||
const w = new BrowserWindow({ show: false })
|
const w = new BrowserWindow({ show: false })
|
||||||
w.loadURL('about:blank')
|
w.loadURL(pdfSource)
|
||||||
const [status, title] = await w.webContents.executeJavaScript(`fetch(${JSON.stringify(pdfSource)}).then(res => [res.status, document.title])`)
|
const [, contents] = await emittedOnce(app, 'web-contents-created')
|
||||||
expect(status).to.equal(200)
|
expect(contents.getURL()).to.equal('chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html')
|
||||||
expect(title).to.not.equal('cat.pdf')
|
await emittedOnce(contents, 'did-finish-load')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('opens when loading a pdf resource in a iframe', (done) => {
|
it('opens when loading a pdf resource in a iframe', async () => {
|
||||||
testPDFIsLoadedInSubFrame('pdf-in-iframe.html', 'preload-pdf-loaded-in-subframe.js', done)
|
const w = new BrowserWindow({ show: false })
|
||||||
})
|
w.loadFile(path.join(__dirname, 'fixtures', 'pages', 'pdf-in-iframe.html'))
|
||||||
|
const [, contents] = await emittedOnce(app, 'web-contents-created')
|
||||||
it('opens when loading a pdf resource in a nested iframe', (done) => {
|
expect(contents.getURL()).to.equal('chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html')
|
||||||
testPDFIsLoadedInSubFrame('pdf-in-nested-iframe.html', 'preload-pdf-loaded-in-nested-subframe.js', done)
|
await emittedOnce(contents, 'did-finish-load')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
6
spec-main/fixtures/pages/pdf-in-iframe.html
Normal file
6
spec-main/fixtures/pages/pdf-in-iframe.html
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<iframe id="pdf-frame" src="../cat.pdf"/>
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
6
spec/fixtures/pages/pdf-in-iframe.html
vendored
6
spec/fixtures/pages/pdf-in-iframe.html
vendored
|
@ -1,6 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<iframe id="pdf-frame" src="../assets/cat.pdf"/>
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<iframe id="outer-frame" src="./pdf-in-iframe.html"/>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Loading…
Add table
Reference in a new issue