| // Copyright 2014 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "chrome/browser/extensions/api/chrome_extensions_api_client.h" | 
 |  | 
 | #include <memory> | 
 | #include <utility> | 
 |  | 
 | #include "base/check.h" | 
 | #include "base/files/file_path.h" | 
 | #include "base/functional/bind.h" | 
 | #include "base/memory/raw_ptr.h" | 
 | #include "base/memory/scoped_refptr.h" | 
 | #include "base/strings/string_util.h" | 
 | #include "base/task/single_thread_task_runner.h" | 
 | #include "build/build_config.h" | 
 | #include "build/chromeos_buildflags.h" | 
 | #include "chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h" | 
 | #include "chrome/browser/extensions/api/management/chrome_management_api_delegate.h" | 
 | #include "chrome/browser/extensions/api/metrics_private/chrome_metrics_private_delegate.h" | 
 | #include "chrome/browser/extensions/api/storage/managed_value_store_cache.h" | 
 | #include "chrome/browser/extensions/api/storage/sync_value_store_cache.h" | 
 | #include "chrome/browser/favicon/favicon_utils.h" | 
 | #include "chrome/browser/ui/webui/devtools/devtools_ui.h" | 
 | #include "chrome/common/buildflags.h" | 
 | #include "chrome/common/url_constants.h" | 
 | #include "chrome/common/webui_url_constants.h" | 
 | #include "components/signin/core/browser/signin_header_helper.h" | 
 | #include "components/value_store/value_store_factory.h" | 
 | #include "content/public/browser/browser_context.h" | 
 | #include "content/public/browser/browser_task_traits.h" | 
 | #include "content/public/browser/browser_thread.h" | 
 | #include "content/public/browser/render_frame_host.h" | 
 | #include "extensions/browser/api/messaging/messaging_delegate.h" | 
 | #include "extensions/browser/api/messaging/native_message_host.h" | 
 | #include "extensions/browser/api/messaging/native_message_port.h" | 
 | #include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h" | 
 | #include "extensions/browser/api/web_request/web_request_info.h" | 
 | #include "extensions/browser/extension_registry.h" | 
 | #include "extensions/browser/supervised_user_extensions_delegate.h" | 
 | #include "google_apis/gaia/gaia_urls.h" | 
 | #include "pdf/buildflags.h" | 
 | #include "printing/buildflags/buildflags.h" | 
 | #include "services/network/public/mojom/fetch_api.mojom-shared.h" | 
 | #include "ui/base/page_transition_types.h" | 
 | #include "ui/base/window_open_disposition.h" | 
 | #include "url/gurl.h" | 
 |  | 
 | #if BUILDFLAG(ENABLE_GUEST_VIEW) | 
 | #include "chrome/browser/guest_view/app_view/chrome_app_view_guest_delegate.h" | 
 | #include "chrome/browser/guest_view/chrome_guest_view_manager_delegate.h" | 
 | #include "chrome/browser/guest_view/extension_options/chrome_extension_options_guest_delegate.h" | 
 | #include "chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_guest_delegate.h" | 
 | #include "chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h" | 
 | #include "chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h" | 
 | #include "extensions/browser/guest_view/web_view/web_view_guest.h" | 
 | #include "extensions/browser/guest_view/web_view/web_view_permission_helper.h" | 
 | #endif | 
 |  | 
 | #if !BUILDFLAG(IS_ANDROID) | 
 | #include "chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.h" | 
 | #include "chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h" | 
 | #include "chrome/browser/search/instant_service.h" | 
 | #include "chrome/browser/search/instant_service_factory.h" | 
 | #endif | 
 |  | 
 | #if BUILDFLAG(IS_CHROMEOS) | 
 | #include "chrome/browser/extensions/api/file_handlers/non_native_file_system_delegate_chromeos.h" | 
 | #include "chrome/browser/extensions/api/file_system/chrome_file_system_delegate_ash.h" | 
 | #include "chrome/browser/extensions/api/file_system/consent_provider_impl.h" | 
 | #include "chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.h" | 
 | #include "chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.h" | 
 | #include "chrome/browser/extensions/clipboard_extension_helper_chromeos.h" | 
 | #include "chromeos/ash/components/settings/cros_settings.h" | 
 | #endif | 
 |  | 
 | #if BUILDFLAG(ENABLE_PRINTING) | 
 | #include "chrome/browser/printing/printing_init.h" | 
 | #endif | 
 |  | 
 | namespace extensions { | 
 |  | 
 | ChromeExtensionsAPIClient::ChromeExtensionsAPIClient() = default; | 
 |  | 
 | ChromeExtensionsAPIClient::~ChromeExtensionsAPIClient() = default; | 
 |  | 
 | void ChromeExtensionsAPIClient::AddAdditionalValueStoreCaches( | 
 |     content::BrowserContext* context, | 
 |     const scoped_refptr<value_store::ValueStoreFactory>& factory, | 
 |     SettingsChangedCallback observer, | 
 |     std::map<settings_namespace::Namespace, | 
 |              raw_ptr<ValueStoreCache, CtnExperimental>>* caches) { | 
 |   // Add support for chrome.storage.sync. | 
 |   (*caches)[settings_namespace::SYNC] = | 
 |       new SyncValueStoreCache(factory, observer, context->GetPath()); | 
 |  | 
 |   // Add support for chrome.storage.managed. | 
 |   (*caches)[settings_namespace::MANAGED] = new ManagedValueStoreCache( | 
 |       *Profile::FromBrowserContext(context), factory, observer); | 
 | } | 
 |  | 
 | void ChromeExtensionsAPIClient::AttachWebContentsHelpers( | 
 |     content::WebContents* web_contents) const { | 
 |   favicon::CreateContentFaviconDriverForWebContents(web_contents); | 
 | #if BUILDFLAG(ENABLE_PRINTING) | 
 |   printing::InitializePrintingForWebContents(web_contents); | 
 | #endif | 
 | } | 
 |  | 
 | bool ChromeExtensionsAPIClient::ShouldHideResponseHeader( | 
 |     const GURL& url, | 
 |     const std::string& header_name) const { | 
 |   // Gaia may send a OAUth2 authorization code in the Dice response header, | 
 |   // which could allow an extension to generate a refresh token for the account. | 
 |   return url.host_piece() == GaiaUrls::GetInstance()->gaia_url().host_piece() && | 
 |          base::CompareCaseInsensitiveASCII(header_name, | 
 |                                            signin::kDiceResponseHeader) == 0; | 
 | } | 
 |  | 
 | bool ChromeExtensionsAPIClient::ShouldHideBrowserNetworkRequest( | 
 |     content::BrowserContext* context, | 
 |     const WebRequestInfo& request) const { | 
 |   DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 
 |  | 
 |   // Note: browser initiated non-navigation requests are hidden from extensions. | 
 |   // But we do still need to protect some sensitive sub-frame navigation | 
 |   // requests. | 
 |   // Exclude main frame navigation requests. | 
 |   bool is_browser_request = | 
 |       request.render_process_id == -1 && | 
 |       request.web_request_type != WebRequestResourceType::MAIN_FRAME; | 
 |  | 
 |   // Hide requests made by the Devtools frontend. | 
 |   bool is_sensitive_request = | 
 |       is_browser_request && DevToolsUI::IsFrontendResourceURL(request.url); | 
 |  | 
 |   // Hide requests made by the browser on behalf of the NTP. | 
 |   is_sensitive_request |= | 
 |       is_browser_request && | 
 |       request.initiator == | 
 |           url::Origin::Create(GURL(chrome::kChromeUINewTabURL)); | 
 |  | 
 |   // Hide requests made by the browser on behalf of the 1P WebUI NTP. | 
 |   is_sensitive_request |= | 
 |       is_browser_request && | 
 |       request.initiator == | 
 |           url::Origin::Create(GURL(chrome::kChromeUINewTabPageURL)); | 
 |  | 
 |   // Android does not support instant. | 
 | #if !BUILDFLAG(IS_ANDROID) | 
 |   // Hide requests made by the NTP Instant renderer. | 
 |   auto* instant_service = | 
 |       context | 
 |           ? InstantServiceFactory::GetForProfile(static_cast<Profile*>(context)) | 
 |           : nullptr; | 
 |   if (instant_service) { | 
 |     is_sensitive_request |= | 
 |         instant_service->IsInstantProcess(request.render_process_id); | 
 |   } | 
 | #endif  // !BUILDFLAG(IS_ANDROID) | 
 |  | 
 |   return is_sensitive_request; | 
 | } | 
 |  | 
 | #if BUILDFLAG(ENABLE_GUEST_VIEW) | 
 | std::unique_ptr<AppViewGuestDelegate> | 
 | ChromeExtensionsAPIClient::CreateAppViewGuestDelegate() const { | 
 |   return std::make_unique<ChromeAppViewGuestDelegate>(); | 
 | } | 
 |  | 
 | std::unique_ptr<ExtensionOptionsGuestDelegate> | 
 | ChromeExtensionsAPIClient::CreateExtensionOptionsGuestDelegate( | 
 |     ExtensionOptionsGuest* guest) const { | 
 |   return std::make_unique<ChromeExtensionOptionsGuestDelegate>(guest); | 
 | } | 
 |  | 
 | std::unique_ptr<guest_view::GuestViewManagerDelegate> | 
 | ChromeExtensionsAPIClient::CreateGuestViewManagerDelegate() const { | 
 |   return std::make_unique<ChromeGuestViewManagerDelegate>(); | 
 | } | 
 |  | 
 | std::unique_ptr<MimeHandlerViewGuestDelegate> | 
 | ChromeExtensionsAPIClient::CreateMimeHandlerViewGuestDelegate( | 
 |     MimeHandlerViewGuest* guest) const { | 
 |   return std::make_unique<ChromeMimeHandlerViewGuestDelegate>(); | 
 | } | 
 |  | 
 | std::unique_ptr<WebViewGuestDelegate> | 
 | ChromeExtensionsAPIClient::CreateWebViewGuestDelegate( | 
 |     WebViewGuest* web_view_guest) const { | 
 |   return std::make_unique<ChromeWebViewGuestDelegate>(web_view_guest); | 
 | } | 
 |  | 
 | std::unique_ptr<WebViewPermissionHelperDelegate> | 
 | ChromeExtensionsAPIClient::CreateWebViewPermissionHelperDelegate( | 
 |     WebViewPermissionHelper* web_view_permission_helper) const { | 
 |   return std::make_unique<ChromeWebViewPermissionHelperDelegate>( | 
 |       web_view_permission_helper); | 
 | } | 
 | #endif  // BUILDFLAG(ENABLE_GUEST_VIEW) | 
 |  | 
 | #if BUILDFLAG(IS_CHROMEOS) | 
 | std::unique_ptr<ConsentProvider> | 
 | ChromeExtensionsAPIClient::CreateConsentProvider( | 
 |     content::BrowserContext* browser_context) const { | 
 |   auto consent_provider_delegate = | 
 |       std::make_unique<file_system_api::ConsentProviderDelegate>( | 
 |           Profile::FromBrowserContext(browser_context)); | 
 |   return std::make_unique<file_system_api::ConsentProviderImpl>( | 
 |       std::move(consent_provider_delegate)); | 
 | } | 
 | #endif  // BUILDFLAG(IS_CHROMEOS) | 
 |  | 
 | #if BUILDFLAG(IS_CHROMEOS) | 
 | bool ChromeExtensionsAPIClient::ShouldAllowDetachingUsb(int vid, | 
 |                                                         int pid) const { | 
 |   const base::Value::List* policy_list; | 
 |   if (ash::CrosSettings::Get()->GetList(ash::kUsbDetachableAllowlist, | 
 |                                         &policy_list)) { | 
 |     for (const auto& entry : *policy_list) { | 
 |       const base::Value::Dict* entry_dict = entry.GetIfDict(); | 
 |       if (entry_dict && | 
 |           entry_dict->FindInt(ash::kUsbDetachableAllowlistKeyVid) == vid && | 
 |           entry_dict->FindInt(ash::kUsbDetachableAllowlistKeyPid) == pid) { | 
 |         return true; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   return false; | 
 | } | 
 | #endif  // BUILDFLAG(IS_CHROMEOS) | 
 |  | 
 | std::unique_ptr<VirtualKeyboardDelegate> | 
 | ChromeExtensionsAPIClient::CreateVirtualKeyboardDelegate( | 
 |     content::BrowserContext* browser_context) const { | 
 | #if BUILDFLAG(IS_CHROMEOS) | 
 |   return std::make_unique<ChromeVirtualKeyboardDelegate>(browser_context); | 
 | #else | 
 |   return nullptr; | 
 | #endif | 
 | } | 
 |  | 
 | ManagementAPIDelegate* ChromeExtensionsAPIClient::CreateManagementAPIDelegate() | 
 |     const { | 
 |   return new ChromeManagementAPIDelegate; | 
 | } | 
 |  | 
 | MetricsPrivateDelegate* ChromeExtensionsAPIClient::GetMetricsPrivateDelegate() { | 
 |   if (!metrics_private_delegate_) { | 
 |     metrics_private_delegate_ = | 
 |         std::make_unique<ChromeMetricsPrivateDelegate>(); | 
 |   } | 
 |   return metrics_private_delegate_.get(); | 
 | } | 
 |  | 
 | // The APIs that require these methods are not supported on Android. | 
 | #if !BUILDFLAG(IS_ANDROID) | 
 | FileSystemDelegate* ChromeExtensionsAPIClient::GetFileSystemDelegate() { | 
 |   if (!file_system_delegate_) { | 
 | #if BUILDFLAG(IS_CHROMEOS) | 
 |     file_system_delegate_ = std::make_unique<ChromeFileSystemDelegateAsh>(); | 
 | #else | 
 |     file_system_delegate_ = std::make_unique<ChromeFileSystemDelegate>(); | 
 | #endif | 
 |   } | 
 |   return file_system_delegate_.get(); | 
 | } | 
 |  | 
 | FeedbackPrivateDelegate* | 
 | ChromeExtensionsAPIClient::GetFeedbackPrivateDelegate() { | 
 |   if (!feedback_private_delegate_) { | 
 |     feedback_private_delegate_ = | 
 |         std::make_unique<ChromeFeedbackPrivateDelegate>(); | 
 |   } | 
 |   return feedback_private_delegate_.get(); | 
 | } | 
 |  | 
 | AutomationInternalApiDelegate* | 
 | ChromeExtensionsAPIClient::GetAutomationInternalApiDelegate() { | 
 |   if (!extensions_automation_api_delegate_) { | 
 |     extensions_automation_api_delegate_ = | 
 |         std::make_unique<ChromeAutomationInternalApiDelegate>(); | 
 |   } | 
 |   return extensions_automation_api_delegate_.get(); | 
 | } | 
 | #endif  // !BUILDFLAG(IS_ANDROID) | 
 |  | 
 | #if BUILDFLAG(IS_CHROMEOS) | 
 | MediaPerceptionAPIDelegate* | 
 | ChromeExtensionsAPIClient::GetMediaPerceptionAPIDelegate() { | 
 |   if (!media_perception_api_delegate_) { | 
 |     media_perception_api_delegate_ = | 
 |         std::make_unique<MediaPerceptionAPIDelegateChromeOS>(); | 
 |   } | 
 |   return media_perception_api_delegate_.get(); | 
 | } | 
 |  | 
 | NonNativeFileSystemDelegate* | 
 | ChromeExtensionsAPIClient::GetNonNativeFileSystemDelegate() { | 
 |   if (!non_native_file_system_delegate_) { | 
 |     non_native_file_system_delegate_ = | 
 |         std::make_unique<NonNativeFileSystemDelegateChromeOS>(); | 
 |   } | 
 |   return non_native_file_system_delegate_.get(); | 
 | } | 
 |  | 
 | void ChromeExtensionsAPIClient::SaveImageDataToClipboard( | 
 |     std::vector<uint8_t> image_data, | 
 |     api::clipboard::ImageType type, | 
 |     AdditionalDataItemList additional_items, | 
 |     base::OnceClosure success_callback, | 
 |     base::OnceCallback<void(const std::string&)> error_callback) { | 
 |   if (!clipboard_extension_helper_) { | 
 |     clipboard_extension_helper_ = std::make_unique<ClipboardExtensionHelper>(); | 
 |   } | 
 |   clipboard_extension_helper_->DecodeAndSaveImageData( | 
 |       std::move(image_data), type, std::move(additional_items), | 
 |       std::move(success_callback), std::move(error_callback)); | 
 | } | 
 | #endif  // BUILDFLAG(IS_CHROMEOS) | 
 |  | 
 | }  // namespace extensions |