• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Embedded Framework Authors.
2 // Portions copyright 2014 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 
6 #include "libcef/browser/extensions/extensions_browser_client.h"
7 
8 #include <utility>
9 
10 #include "libcef/browser/alloy/alloy_browser_host_impl.h"
11 #include "libcef/browser/browser_context.h"
12 #include "libcef/browser/extensions/component_extension_resource_manager.h"
13 #include "libcef/browser/extensions/extension_system.h"
14 #include "libcef/browser/extensions/extension_system_factory.h"
15 #include "libcef/browser/extensions/extension_web_contents_observer.h"
16 #include "libcef/browser/extensions/extensions_api_client.h"
17 #include "libcef/browser/extensions/extensions_browser_api_provider.h"
18 #include "libcef/browser/request_context_impl.h"
19 
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/extensions/chrome_url_request_util.h"
22 #include "chrome/browser/extensions/event_router_forwarder.h"
23 #include "content/public/browser/browser_context.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/render_frame_host.h"
26 #include "extensions/browser/api/extensions_api_client.h"
27 #include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
28 #include "extensions/browser/api/runtime/runtime_api_delegate.h"
29 #include "extensions/browser/app_sorting.h"
30 #include "extensions/browser/core_extensions_browser_api_provider.h"
31 #include "extensions/browser/event_router.h"
32 #include "extensions/browser/extension_host_delegate.h"
33 #include "extensions/browser/extensions_browser_interface_binders.h"
34 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
35 #include "extensions/browser/kiosk/kiosk_delegate.h"
36 #include "extensions/browser/url_request_util.h"
37 #include "extensions/common/api/mime_handler.mojom.h"
38 #include "extensions/common/constants.h"
39 
40 using content::BrowserContext;
41 using content::BrowserThread;
42 
43 namespace extensions {
44 
45 namespace {
46 
BindMimeHandlerService(content::RenderFrameHost * frame_host,mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService> receiver)47 void BindMimeHandlerService(
48     content::RenderFrameHost* frame_host,
49     mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService>
50         receiver) {
51   auto* web_contents = content::WebContents::FromRenderFrameHost(frame_host);
52   if (!web_contents)
53     return;
54 
55   auto* guest_view =
56       extensions::MimeHandlerViewGuest::FromWebContents(web_contents);
57   if (!guest_view)
58     return;
59   extensions::MimeHandlerServiceImpl::Create(guest_view->GetStreamWeakPtr(),
60                                              std::move(receiver));
61 }
62 
BindBeforeUnloadControl(content::RenderFrameHost * frame_host,mojo::PendingReceiver<extensions::mime_handler::BeforeUnloadControl> receiver)63 void BindBeforeUnloadControl(
64     content::RenderFrameHost* frame_host,
65     mojo::PendingReceiver<extensions::mime_handler::BeforeUnloadControl>
66         receiver) {
67   auto* web_contents = content::WebContents::FromRenderFrameHost(frame_host);
68   if (!web_contents)
69     return;
70 
71   auto* guest_view =
72       extensions::MimeHandlerViewGuest::FromWebContents(web_contents);
73   if (!guest_view)
74     return;
75   guest_view->FuseBeforeUnloadControl(std::move(receiver));
76 }
77 
78 // Dummy KiosDelegate that always returns false
79 class CefKioskDelegate : public extensions::KioskDelegate {
80  public:
81   CefKioskDelegate() = default;
82   ~CefKioskDelegate() override = default;
83 
84   // KioskDelegate overrides:
IsAutoLaunchedKioskApp(const ExtensionId & id) const85   bool IsAutoLaunchedKioskApp(const ExtensionId& id) const override {
86     return false;
87   }
88 };
89 
90 }  // namespace
91 
CefExtensionsBrowserClient()92 CefExtensionsBrowserClient::CefExtensionsBrowserClient()
93     : api_client_(new CefExtensionsAPIClient),
94       resource_manager_(new CefComponentExtensionResourceManager) {
95   AddAPIProvider(std::make_unique<CoreExtensionsBrowserAPIProvider>());
96   AddAPIProvider(std::make_unique<CefExtensionsBrowserAPIProvider>());
97 }
98 
~CefExtensionsBrowserClient()99 CefExtensionsBrowserClient::~CefExtensionsBrowserClient() {}
100 
101 // static
Get()102 CefExtensionsBrowserClient* CefExtensionsBrowserClient::Get() {
103   return static_cast<CefExtensionsBrowserClient*>(
104       ExtensionsBrowserClient::Get());
105 }
106 
IsShuttingDown()107 bool CefExtensionsBrowserClient::IsShuttingDown() {
108   return false;
109 }
110 
AreExtensionsDisabled(const base::CommandLine & command_line,BrowserContext * context)111 bool CefExtensionsBrowserClient::AreExtensionsDisabled(
112     const base::CommandLine& command_line,
113     BrowserContext* context) {
114   return false;
115 }
116 
IsValidContext(BrowserContext * context)117 bool CefExtensionsBrowserClient::IsValidContext(BrowserContext* context) {
118   return GetOriginalContext(context) != nullptr;
119 }
120 
IsSameContext(BrowserContext * first,BrowserContext * second)121 bool CefExtensionsBrowserClient::IsSameContext(BrowserContext* first,
122                                                BrowserContext* second) {
123   // Returns true if |first| and |second| share the same underlying
124   // CefBrowserContext.
125   return GetOriginalContext(first) == GetOriginalContext(second);
126 }
127 
HasOffTheRecordContext(BrowserContext * context)128 bool CefExtensionsBrowserClient::HasOffTheRecordContext(
129     BrowserContext* context) {
130   // CEF doesn't use incognito contexts.
131   return false;
132 }
133 
GetOffTheRecordContext(BrowserContext * context)134 BrowserContext* CefExtensionsBrowserClient::GetOffTheRecordContext(
135     BrowserContext* context) {
136   return nullptr;
137 }
138 
GetOriginalContext(BrowserContext * context)139 BrowserContext* CefExtensionsBrowserClient::GetOriginalContext(
140     BrowserContext* context) {
141   auto cef_browser_context = CefBrowserContext::FromBrowserContext(context);
142   if (cef_browser_context)
143     return cef_browser_context->AsBrowserContext();
144   return nullptr;
145 }
146 
IsGuestSession(BrowserContext * context) const147 bool CefExtensionsBrowserClient::IsGuestSession(BrowserContext* context) const {
148   return false;
149 }
150 
IsExtensionIncognitoEnabled(const std::string & extension_id,content::BrowserContext * context) const151 bool CefExtensionsBrowserClient::IsExtensionIncognitoEnabled(
152     const std::string& extension_id,
153     content::BrowserContext* context) const {
154   return false;
155 }
156 
CanExtensionCrossIncognito(const Extension * extension,content::BrowserContext * context) const157 bool CefExtensionsBrowserClient::CanExtensionCrossIncognito(
158     const Extension* extension,
159     content::BrowserContext* context) const {
160   return false;
161 }
162 
GetBundleResourcePath(const network::ResourceRequest & request,const base::FilePath & extension_resources_path,int * resource_id) const163 base::FilePath CefExtensionsBrowserClient::GetBundleResourcePath(
164     const network::ResourceRequest& request,
165     const base::FilePath& extension_resources_path,
166     int* resource_id) const {
167   return chrome_url_request_util::GetBundleResourcePath(
168       request, extension_resources_path, resource_id);
169 }
170 
LoadResourceFromResourceBundle(const network::ResourceRequest & request,mojo::PendingReceiver<network::mojom::URLLoader> loader,const base::FilePath & resource_relative_path,const int resource_id,const std::string & content_security_policy,mojo::PendingRemote<network::mojom::URLLoaderClient> client,bool send_cors_header)171 void CefExtensionsBrowserClient::LoadResourceFromResourceBundle(
172     const network::ResourceRequest& request,
173     mojo::PendingReceiver<network::mojom::URLLoader> loader,
174     const base::FilePath& resource_relative_path,
175     const int resource_id,
176     const std::string& content_security_policy,
177     mojo::PendingRemote<network::mojom::URLLoaderClient> client,
178     bool send_cors_header) {
179   chrome_url_request_util::LoadResourceFromResourceBundle(
180       request, std::move(loader), resource_relative_path, resource_id,
181       content_security_policy, std::move(client), send_cors_header);
182 }
183 
AllowCrossRendererResourceLoad(const network::ResourceRequest & request,network::mojom::RequestDestination destination,ui::PageTransition page_transition,int child_id,bool is_incognito,const Extension * extension,const ExtensionSet & extensions,const ProcessMap & process_map)184 bool CefExtensionsBrowserClient::AllowCrossRendererResourceLoad(
185     const network::ResourceRequest& request,
186     network::mojom::RequestDestination destination,
187     ui::PageTransition page_transition,
188     int child_id,
189     bool is_incognito,
190     const Extension* extension,
191     const ExtensionSet& extensions,
192     const ProcessMap& process_map) {
193   bool allowed = false;
194   if (url_request_util::AllowCrossRendererResourceLoad(
195           request, destination, page_transition, child_id, is_incognito,
196           extension, extensions, process_map, &allowed)) {
197     return allowed;
198   }
199 
200   // Couldn't determine if resource is allowed. Block the load.
201   return false;
202 }
203 
GetPrefServiceForContext(BrowserContext * context)204 PrefService* CefExtensionsBrowserClient::GetPrefServiceForContext(
205     BrowserContext* context) {
206   return CefBrowserContext::FromBrowserContext(context)
207       ->AsProfile()
208       ->GetPrefs();
209 }
210 
GetEarlyExtensionPrefsObservers(content::BrowserContext * context,std::vector<EarlyExtensionPrefsObserver * > * observers) const211 void CefExtensionsBrowserClient::GetEarlyExtensionPrefsObservers(
212     content::BrowserContext* context,
213     std::vector<EarlyExtensionPrefsObserver*>* observers) const {}
214 
GetProcessManagerDelegate() const215 ProcessManagerDelegate* CefExtensionsBrowserClient::GetProcessManagerDelegate()
216     const {
217   return nullptr;
218 }
219 
220 std::unique_ptr<ExtensionHostDelegate>
CreateExtensionHostDelegate()221 CefExtensionsBrowserClient::CreateExtensionHostDelegate() {
222   // CEF does not use the ExtensionHost constructor that calls this method.
223   NOTREACHED();
224   return std::unique_ptr<ExtensionHostDelegate>();
225 }
226 
CreateBackgroundExtensionHost(const Extension * extension,content::BrowserContext * browser_context,const GURL & url,ExtensionHost ** host)227 bool CefExtensionsBrowserClient::CreateBackgroundExtensionHost(
228     const Extension* extension,
229     content::BrowserContext* browser_context,
230     const GURL& url,
231     ExtensionHost** host) {
232   auto cef_browser_context =
233       CefBrowserContext::FromBrowserContext(browser_context);
234 
235   // A CEF representation should always exist.
236   CefRefPtr<CefExtension> cef_extension =
237       cef_browser_context->GetExtension(extension->id());
238   DCHECK(cef_extension);
239   if (!cef_extension) {
240     // Cancel the background host creation.
241     return true;
242   }
243 
244   // Always use the same request context that the extension was registered with.
245   // GetLoaderContext() will return NULL for internal extensions.
246   CefRefPtr<CefRequestContext> request_context =
247       cef_extension->GetLoaderContext();
248   if (!request_context) {
249     // Cancel the background host creation.
250     return true;
251   }
252 
253   CefBrowserCreateParams create_params;
254   create_params.url = url.spec();
255   create_params.request_context = request_context;
256 
257   CefRefPtr<CefExtensionHandler> handler = cef_extension->GetHandler();
258   if (handler.get() && handler->OnBeforeBackgroundBrowser(
259                            cef_extension, create_params.url,
260                            create_params.client, create_params.settings)) {
261     // Cancel the background host creation.
262     return true;
263   }
264 
265   // This triggers creation of the background host.
266   create_params.extension = extension;
267   create_params.extension_host_type = mojom::ViewType::kExtensionBackgroundPage;
268 
269   // Browser creation may fail under certain rare circumstances. Fail the
270   // background host creation in that case.
271   CefRefPtr<AlloyBrowserHostImpl> browser =
272       AlloyBrowserHostImpl::Create(create_params);
273   if (browser) {
274     *host = browser->GetExtensionHost();
275     DCHECK(*host);
276   }
277   return true;
278 }
279 
DidVersionUpdate(BrowserContext * context)280 bool CefExtensionsBrowserClient::DidVersionUpdate(BrowserContext* context) {
281   // TODO(jamescook): We might want to tell extensions when app_shell updates.
282   return false;
283 }
284 
PermitExternalProtocolHandler()285 void CefExtensionsBrowserClient::PermitExternalProtocolHandler() {}
286 
IsInDemoMode()287 bool CefExtensionsBrowserClient::IsInDemoMode() {
288   return false;
289 }
290 
IsScreensaverInDemoMode(const std::string & app_id)291 bool CefExtensionsBrowserClient::IsScreensaverInDemoMode(
292     const std::string& app_id) {
293   return false;
294 }
295 
IsRunningInForcedAppMode()296 bool CefExtensionsBrowserClient::IsRunningInForcedAppMode() {
297   return false;
298 }
299 
IsAppModeForcedForApp(const ExtensionId & extension_id)300 bool CefExtensionsBrowserClient::IsAppModeForcedForApp(
301     const ExtensionId& extension_id) {
302   return false;
303 }
304 
IsLoggedInAsPublicAccount()305 bool CefExtensionsBrowserClient::IsLoggedInAsPublicAccount() {
306   return false;
307 }
308 
309 ExtensionSystemProvider*
GetExtensionSystemFactory()310 CefExtensionsBrowserClient::GetExtensionSystemFactory() {
311   return CefExtensionSystemFactory::GetInstance();
312 }
313 
RegisterBrowserInterfaceBindersForFrame(mojo::BinderMapWithContext<content::RenderFrameHost * > * map,content::RenderFrameHost * render_frame_host,const Extension * extension) const314 void CefExtensionsBrowserClient::RegisterBrowserInterfaceBindersForFrame(
315     mojo::BinderMapWithContext<content::RenderFrameHost*>* map,
316     content::RenderFrameHost* render_frame_host,
317     const Extension* extension) const {
318   PopulateExtensionFrameBinders(map, render_frame_host, extension);
319 
320   map->Add<extensions::mime_handler::MimeHandlerService>(
321       base::BindRepeating(&BindMimeHandlerService));
322   map->Add<extensions::mime_handler::BeforeUnloadControl>(
323       base::BindRepeating(&BindBeforeUnloadControl));
324 }
325 
326 std::unique_ptr<RuntimeAPIDelegate>
CreateRuntimeAPIDelegate(content::BrowserContext * context) const327 CefExtensionsBrowserClient::CreateRuntimeAPIDelegate(
328     content::BrowserContext* context) const {
329   // TODO(extensions): Implement to support Apps.
330   NOTREACHED();
331   return nullptr;
332 }
333 
334 const ComponentExtensionResourceManager*
GetComponentExtensionResourceManager()335 CefExtensionsBrowserClient::GetComponentExtensionResourceManager() {
336   return resource_manager_.get();
337 }
338 
BroadcastEventToRenderers(events::HistogramValue histogram_value,const std::string & event_name,std::unique_ptr<base::ListValue> args,bool dispatch_to_off_the_record_profiles)339 void CefExtensionsBrowserClient::BroadcastEventToRenderers(
340     events::HistogramValue histogram_value,
341     const std::string& event_name,
342     std::unique_ptr<base::ListValue> args,
343     bool dispatch_to_off_the_record_profiles) {
344   g_browser_process->extension_event_router_forwarder()
345       ->BroadcastEventToRenderers(histogram_value, event_name, std::move(args),
346                                   GURL(), dispatch_to_off_the_record_profiles);
347 }
348 
GetExtensionCache()349 ExtensionCache* CefExtensionsBrowserClient::GetExtensionCache() {
350   // Only used by Chrome via ExtensionService.
351   NOTREACHED();
352   return nullptr;
353 }
354 
IsBackgroundUpdateAllowed()355 bool CefExtensionsBrowserClient::IsBackgroundUpdateAllowed() {
356   return true;
357 }
358 
IsMinBrowserVersionSupported(const std::string & min_version)359 bool CefExtensionsBrowserClient::IsMinBrowserVersionSupported(
360     const std::string& min_version) {
361   return true;
362 }
363 
364 ExtensionWebContentsObserver*
GetExtensionWebContentsObserver(content::WebContents * web_contents)365 CefExtensionsBrowserClient::GetExtensionWebContentsObserver(
366     content::WebContents* web_contents) {
367   return CefExtensionWebContentsObserver::FromWebContents(web_contents);
368 }
369 
GetKioskDelegate()370 KioskDelegate* CefExtensionsBrowserClient::GetKioskDelegate() {
371   if (!kiosk_delegate_)
372     kiosk_delegate_.reset(new CefKioskDelegate());
373   return kiosk_delegate_.get();
374 }
375 
IsLockScreenContext(content::BrowserContext * context)376 bool CefExtensionsBrowserClient::IsLockScreenContext(
377     content::BrowserContext* context) {
378   return false;
379 }
380 
GetApplicationLocale()381 std::string CefExtensionsBrowserClient::GetApplicationLocale() {
382   return g_browser_process->GetApplicationLocale();
383 }
384 
385 }  // namespace extensions
386