• 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,scoped_refptr<net::HttpResponseHeaders> headers,mojo::PendingRemote<network::mojom::URLLoaderClient> client)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     scoped_refptr<net::HttpResponseHeaders> headers,
177     mojo::PendingRemote<network::mojom::URLLoaderClient> client) {
178   chrome_url_request_util::LoadResourceFromResourceBundle(
179       request, std::move(loader), resource_relative_path, resource_id,
180       std::move(headers), std::move(client));
181 }
182 
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)183 bool CefExtensionsBrowserClient::AllowCrossRendererResourceLoad(
184     const network::ResourceRequest& request,
185     network::mojom::RequestDestination destination,
186     ui::PageTransition page_transition,
187     int child_id,
188     bool is_incognito,
189     const Extension* extension,
190     const ExtensionSet& extensions,
191     const ProcessMap& process_map) {
192   bool allowed = false;
193   if (url_request_util::AllowCrossRendererResourceLoad(
194           request, destination, page_transition, child_id, is_incognito,
195           extension, extensions, process_map, &allowed)) {
196     return allowed;
197   }
198 
199   // Couldn't determine if resource is allowed. Block the load.
200   return false;
201 }
202 
GetPrefServiceForContext(BrowserContext * context)203 PrefService* CefExtensionsBrowserClient::GetPrefServiceForContext(
204     BrowserContext* context) {
205   return CefBrowserContext::FromBrowserContext(context)
206       ->AsProfile()
207       ->GetPrefs();
208 }
209 
GetEarlyExtensionPrefsObservers(content::BrowserContext * context,std::vector<EarlyExtensionPrefsObserver * > * observers) const210 void CefExtensionsBrowserClient::GetEarlyExtensionPrefsObservers(
211     content::BrowserContext* context,
212     std::vector<EarlyExtensionPrefsObserver*>* observers) const {}
213 
GetProcessManagerDelegate() const214 ProcessManagerDelegate* CefExtensionsBrowserClient::GetProcessManagerDelegate()
215     const {
216   return nullptr;
217 }
218 
219 std::unique_ptr<ExtensionHostDelegate>
CreateExtensionHostDelegate()220 CefExtensionsBrowserClient::CreateExtensionHostDelegate() {
221   // CEF does not use the ExtensionHost constructor that calls this method.
222   NOTREACHED();
223   return std::unique_ptr<ExtensionHostDelegate>();
224 }
225 
CreateBackgroundExtensionHost(const Extension * extension,content::BrowserContext * browser_context,const GURL & url,ExtensionHost ** host)226 bool CefExtensionsBrowserClient::CreateBackgroundExtensionHost(
227     const Extension* extension,
228     content::BrowserContext* browser_context,
229     const GURL& url,
230     ExtensionHost** host) {
231   auto cef_browser_context =
232       CefBrowserContext::FromBrowserContext(browser_context);
233 
234   // A CEF representation should always exist.
235   CefRefPtr<CefExtension> cef_extension =
236       cef_browser_context->GetExtension(extension->id());
237   DCHECK(cef_extension);
238   if (!cef_extension) {
239     // Cancel the background host creation.
240     return true;
241   }
242 
243   // Always use the same request context that the extension was registered with.
244   // GetLoaderContext() will return NULL for internal extensions.
245   CefRefPtr<CefRequestContext> request_context =
246       cef_extension->GetLoaderContext();
247   if (!request_context) {
248     // Cancel the background host creation.
249     return true;
250   }
251 
252   CefBrowserCreateParams create_params;
253   create_params.url = url.spec();
254   create_params.request_context = request_context;
255 
256   CefRefPtr<CefExtensionHandler> handler = cef_extension->GetHandler();
257   if (handler.get() && handler->OnBeforeBackgroundBrowser(
258                            cef_extension, create_params.url,
259                            create_params.client, create_params.settings)) {
260     // Cancel the background host creation.
261     return true;
262   }
263 
264   // This triggers creation of the background host.
265   create_params.extension = extension;
266   create_params.extension_host_type = mojom::ViewType::kExtensionBackgroundPage;
267 
268   // Browser creation may fail under certain rare circumstances. Fail the
269   // background host creation in that case.
270   CefRefPtr<AlloyBrowserHostImpl> browser =
271       AlloyBrowserHostImpl::Create(create_params);
272   if (browser) {
273     *host = browser->GetExtensionHost();
274     DCHECK(*host);
275   }
276   return true;
277 }
278 
DidVersionUpdate(BrowserContext * context)279 bool CefExtensionsBrowserClient::DidVersionUpdate(BrowserContext* context) {
280   // TODO(jamescook): We might want to tell extensions when app_shell updates.
281   return false;
282 }
283 
PermitExternalProtocolHandler()284 void CefExtensionsBrowserClient::PermitExternalProtocolHandler() {}
285 
IsInDemoMode()286 bool CefExtensionsBrowserClient::IsInDemoMode() {
287   return false;
288 }
289 
IsScreensaverInDemoMode(const std::string & app_id)290 bool CefExtensionsBrowserClient::IsScreensaverInDemoMode(
291     const std::string& app_id) {
292   return false;
293 }
294 
IsRunningInForcedAppMode()295 bool CefExtensionsBrowserClient::IsRunningInForcedAppMode() {
296   return false;
297 }
298 
IsAppModeForcedForApp(const ExtensionId & extension_id)299 bool CefExtensionsBrowserClient::IsAppModeForcedForApp(
300     const ExtensionId& extension_id) {
301   return false;
302 }
303 
IsLoggedInAsPublicAccount()304 bool CefExtensionsBrowserClient::IsLoggedInAsPublicAccount() {
305   return false;
306 }
307 
308 ExtensionSystemProvider*
GetExtensionSystemFactory()309 CefExtensionsBrowserClient::GetExtensionSystemFactory() {
310   return CefExtensionSystemFactory::GetInstance();
311 }
312 
RegisterBrowserInterfaceBindersForFrame(mojo::BinderMapWithContext<content::RenderFrameHost * > * map,content::RenderFrameHost * render_frame_host,const Extension * extension) const313 void CefExtensionsBrowserClient::RegisterBrowserInterfaceBindersForFrame(
314     mojo::BinderMapWithContext<content::RenderFrameHost*>* map,
315     content::RenderFrameHost* render_frame_host,
316     const Extension* extension) const {
317   PopulateExtensionFrameBinders(map, render_frame_host, extension);
318 
319   map->Add<extensions::mime_handler::MimeHandlerService>(
320       base::BindRepeating(&BindMimeHandlerService));
321   map->Add<extensions::mime_handler::BeforeUnloadControl>(
322       base::BindRepeating(&BindBeforeUnloadControl));
323 }
324 
325 std::unique_ptr<RuntimeAPIDelegate>
CreateRuntimeAPIDelegate(content::BrowserContext * context) const326 CefExtensionsBrowserClient::CreateRuntimeAPIDelegate(
327     content::BrowserContext* context) const {
328   // TODO(extensions): Implement to support Apps.
329   NOTREACHED();
330   return nullptr;
331 }
332 
333 const ComponentExtensionResourceManager*
GetComponentExtensionResourceManager()334 CefExtensionsBrowserClient::GetComponentExtensionResourceManager() {
335   return resource_manager_.get();
336 }
337 
BroadcastEventToRenderers(events::HistogramValue histogram_value,const std::string & event_name,std::unique_ptr<base::ListValue> args,bool dispatch_to_off_the_record_profiles)338 void CefExtensionsBrowserClient::BroadcastEventToRenderers(
339     events::HistogramValue histogram_value,
340     const std::string& event_name,
341     std::unique_ptr<base::ListValue> args,
342     bool dispatch_to_off_the_record_profiles) {
343   g_browser_process->extension_event_router_forwarder()
344       ->BroadcastEventToRenderers(histogram_value, event_name, std::move(args),
345                                   GURL(), dispatch_to_off_the_record_profiles);
346 }
347 
GetExtensionCache()348 ExtensionCache* CefExtensionsBrowserClient::GetExtensionCache() {
349   // Only used by Chrome via ExtensionService.
350   NOTREACHED();
351   return nullptr;
352 }
353 
IsBackgroundUpdateAllowed()354 bool CefExtensionsBrowserClient::IsBackgroundUpdateAllowed() {
355   return true;
356 }
357 
IsMinBrowserVersionSupported(const std::string & min_version)358 bool CefExtensionsBrowserClient::IsMinBrowserVersionSupported(
359     const std::string& min_version) {
360   return true;
361 }
362 
363 ExtensionWebContentsObserver*
GetExtensionWebContentsObserver(content::WebContents * web_contents)364 CefExtensionsBrowserClient::GetExtensionWebContentsObserver(
365     content::WebContents* web_contents) {
366   return CefExtensionWebContentsObserver::FromWebContents(web_contents);
367 }
368 
GetKioskDelegate()369 KioskDelegate* CefExtensionsBrowserClient::GetKioskDelegate() {
370   if (!kiosk_delegate_)
371     kiosk_delegate_.reset(new CefKioskDelegate());
372   return kiosk_delegate_.get();
373 }
374 
IsLockScreenContext(content::BrowserContext * context)375 bool CefExtensionsBrowserClient::IsLockScreenContext(
376     content::BrowserContext* context) {
377   return false;
378 }
379 
GetApplicationLocale()380 std::string CefExtensionsBrowserClient::GetApplicationLocale() {
381   return g_browser_process->GetApplicationLocale();
382 }
383 
384 }  // namespace extensions
385