1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "extensions/shell/browser/shell_extensions_browser_client.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/task/post_task.h"
12 #include "build/build_config.h"
13 #include "components/version_info/version_info.h"
14 #include "content/public/browser/browser_context.h"
15 #include "content/public/browser/browser_task_traits.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/common/user_agent.h"
19 #include "extensions/browser/api/extensions_api_client.h"
20 #include "extensions/browser/core_extensions_browser_api_provider.h"
21 #include "extensions/browser/event_router.h"
22 #include "extensions/browser/extensions_browser_interface_binders.h"
23 #include "extensions/browser/null_app_sorting.h"
24 #include "extensions/browser/updater/null_extension_cache.h"
25 #include "extensions/browser/url_request_util.h"
26 #include "extensions/common/features/feature_channel.h"
27 #include "extensions/shell/browser/api/runtime/shell_runtime_api_delegate.h"
28 #include "extensions/shell/browser/delegates/shell_kiosk_delegate.h"
29 #include "extensions/shell/browser/shell_extension_host_delegate.h"
30 #include "extensions/shell/browser/shell_extension_system_factory.h"
31 #include "extensions/shell/browser/shell_extension_web_contents_observer.h"
32 #include "extensions/shell/browser/shell_extensions_api_client.h"
33 #include "extensions/shell/browser/shell_extensions_browser_api_provider.h"
34 #include "extensions/shell/browser/shell_navigation_ui_data.h"
35 #include "services/network/public/mojom/url_loader.mojom.h"
36 
37 #if defined(OS_CHROMEOS)
38 #include "chromeos/login/login_state/login_state.h"
39 #endif
40 
41 using content::BrowserContext;
42 using content::BrowserThread;
43 
44 namespace extensions {
45 
ShellExtensionsBrowserClient()46 ShellExtensionsBrowserClient::ShellExtensionsBrowserClient()
47     : api_client_(new ShellExtensionsAPIClient),
48       extension_cache_(new NullExtensionCache()) {
49   // app_shell does not have a concept of channel yet, so leave UNKNOWN to
50   // enable all channel-dependent extension APIs.
51   SetCurrentChannel(version_info::Channel::UNKNOWN);
52 
53   AddAPIProvider(std::make_unique<CoreExtensionsBrowserAPIProvider>());
54   AddAPIProvider(std::make_unique<ShellExtensionsBrowserAPIProvider>());
55 }
56 
~ShellExtensionsBrowserClient()57 ShellExtensionsBrowserClient::~ShellExtensionsBrowserClient() {
58 }
59 
IsShuttingDown()60 bool ShellExtensionsBrowserClient::IsShuttingDown() {
61   return false;
62 }
63 
AreExtensionsDisabled(const base::CommandLine & command_line,BrowserContext * context)64 bool ShellExtensionsBrowserClient::AreExtensionsDisabled(
65     const base::CommandLine& command_line,
66     BrowserContext* context) {
67   return false;
68 }
69 
IsValidContext(BrowserContext * context)70 bool ShellExtensionsBrowserClient::IsValidContext(BrowserContext* context) {
71   DCHECK(browser_context_);
72   return context == browser_context_;
73 }
74 
IsSameContext(BrowserContext * first,BrowserContext * second)75 bool ShellExtensionsBrowserClient::IsSameContext(BrowserContext* first,
76                                                  BrowserContext* second) {
77   return first == second;
78 }
79 
HasOffTheRecordContext(BrowserContext * context)80 bool ShellExtensionsBrowserClient::HasOffTheRecordContext(
81     BrowserContext* context) {
82   return false;
83 }
84 
GetOffTheRecordContext(BrowserContext * context)85 BrowserContext* ShellExtensionsBrowserClient::GetOffTheRecordContext(
86     BrowserContext* context) {
87   // app_shell only supports a single context.
88   return NULL;
89 }
90 
GetOriginalContext(BrowserContext * context)91 BrowserContext* ShellExtensionsBrowserClient::GetOriginalContext(
92     BrowserContext* context) {
93   return context;
94 }
95 
96 #if defined(OS_CHROMEOS)
GetUserIdHashFromContext(content::BrowserContext * context)97 std::string ShellExtensionsBrowserClient::GetUserIdHashFromContext(
98     content::BrowserContext* context) {
99   if (!chromeos::LoginState::IsInitialized())
100     return "";
101   return chromeos::LoginState::Get()->primary_user_hash();
102 }
103 #endif
104 
IsGuestSession(BrowserContext * context) const105 bool ShellExtensionsBrowserClient::IsGuestSession(
106     BrowserContext* context) const {
107   return false;
108 }
109 
IsExtensionIncognitoEnabled(const std::string & extension_id,content::BrowserContext * context) const110 bool ShellExtensionsBrowserClient::IsExtensionIncognitoEnabled(
111     const std::string& extension_id,
112     content::BrowserContext* context) const {
113   return false;
114 }
115 
CanExtensionCrossIncognito(const Extension * extension,content::BrowserContext * context) const116 bool ShellExtensionsBrowserClient::CanExtensionCrossIncognito(
117     const Extension* extension,
118     content::BrowserContext* context) const {
119   return false;
120 }
121 
GetBundleResourcePath(const network::ResourceRequest & request,const base::FilePath & extension_resources_path,int * resource_id) const122 base::FilePath ShellExtensionsBrowserClient::GetBundleResourcePath(
123     const network::ResourceRequest& request,
124     const base::FilePath& extension_resources_path,
125     int* resource_id) const {
126   *resource_id = 0;
127   return base::FilePath();
128 }
129 
LoadResourceFromResourceBundle(const network::ResourceRequest & request,mojo::PendingReceiver<network::mojom::URLLoader> loader,const base::FilePath & resource_relative_path,int resource_id,const std::string & content_security_policy,mojo::PendingRemote<network::mojom::URLLoaderClient> client,bool send_cors_header)130 void ShellExtensionsBrowserClient::LoadResourceFromResourceBundle(
131     const network::ResourceRequest& request,
132     mojo::PendingReceiver<network::mojom::URLLoader> loader,
133     const base::FilePath& resource_relative_path,
134     int resource_id,
135     const std::string& content_security_policy,
136     mojo::PendingRemote<network::mojom::URLLoaderClient> client,
137     bool send_cors_header) {
138   NOTREACHED() << "Load resources from bundles not supported.";
139 }
140 
AllowCrossRendererResourceLoad(const GURL & url,blink::mojom::ResourceType resource_type,ui::PageTransition page_transition,int child_id,bool is_incognito,const Extension * extension,const ExtensionSet & extensions,const ProcessMap & process_map)141 bool ShellExtensionsBrowserClient::AllowCrossRendererResourceLoad(
142     const GURL& url,
143     blink::mojom::ResourceType resource_type,
144     ui::PageTransition page_transition,
145     int child_id,
146     bool is_incognito,
147     const Extension* extension,
148     const ExtensionSet& extensions,
149     const ProcessMap& process_map) {
150   bool allowed = false;
151   if (url_request_util::AllowCrossRendererResourceLoad(
152           url, resource_type, page_transition, child_id, is_incognito,
153           extension, extensions, process_map, &allowed)) {
154     return allowed;
155   }
156 
157   // Couldn't determine if resource is allowed. Block the load.
158   return false;
159 }
160 
GetPrefServiceForContext(BrowserContext * context)161 PrefService* ShellExtensionsBrowserClient::GetPrefServiceForContext(
162     BrowserContext* context) {
163   DCHECK(pref_service_);
164   return pref_service_;
165 }
166 
GetEarlyExtensionPrefsObservers(content::BrowserContext * context,std::vector<EarlyExtensionPrefsObserver * > * observers) const167 void ShellExtensionsBrowserClient::GetEarlyExtensionPrefsObservers(
168     content::BrowserContext* context,
169     std::vector<EarlyExtensionPrefsObserver*>* observers) const {}
170 
171 ProcessManagerDelegate*
GetProcessManagerDelegate() const172 ShellExtensionsBrowserClient::GetProcessManagerDelegate() const {
173   return NULL;
174 }
175 
176 std::unique_ptr<ExtensionHostDelegate>
CreateExtensionHostDelegate()177 ShellExtensionsBrowserClient::CreateExtensionHostDelegate() {
178   return base::WrapUnique(new ShellExtensionHostDelegate);
179 }
180 
DidVersionUpdate(BrowserContext * context)181 bool ShellExtensionsBrowserClient::DidVersionUpdate(BrowserContext* context) {
182   // TODO(jamescook): We might want to tell extensions when app_shell updates.
183   return false;
184 }
185 
PermitExternalProtocolHandler()186 void ShellExtensionsBrowserClient::PermitExternalProtocolHandler() {
187 }
188 
IsInDemoMode()189 bool ShellExtensionsBrowserClient::IsInDemoMode() {
190   return false;
191 }
192 
IsScreensaverInDemoMode(const std::string & app_id)193 bool ShellExtensionsBrowserClient::IsScreensaverInDemoMode(
194     const std::string& app_id) {
195   return false;
196 }
197 
IsRunningInForcedAppMode()198 bool ShellExtensionsBrowserClient::IsRunningInForcedAppMode() {
199   return false;
200 }
201 
IsAppModeForcedForApp(const ExtensionId & extension_id)202 bool ShellExtensionsBrowserClient::IsAppModeForcedForApp(
203     const ExtensionId& extension_id) {
204   return false;
205 }
206 
IsLoggedInAsPublicAccount()207 bool ShellExtensionsBrowserClient::IsLoggedInAsPublicAccount() {
208   return false;
209 }
210 
211 ExtensionSystemProvider*
GetExtensionSystemFactory()212 ShellExtensionsBrowserClient::GetExtensionSystemFactory() {
213   return ShellExtensionSystemFactory::GetInstance();
214 }
215 
RegisterBrowserInterfaceBindersForFrame(service_manager::BinderMapWithContext<content::RenderFrameHost * > * binder_map,content::RenderFrameHost * render_frame_host,const Extension * extension) const216 void ShellExtensionsBrowserClient::RegisterBrowserInterfaceBindersForFrame(
217     service_manager::BinderMapWithContext<content::RenderFrameHost*>*
218         binder_map,
219     content::RenderFrameHost* render_frame_host,
220     const Extension* extension) const {
221   PopulateExtensionFrameBinders(binder_map, render_frame_host, extension);
222 }
223 
224 std::unique_ptr<RuntimeAPIDelegate>
CreateRuntimeAPIDelegate(content::BrowserContext * context) const225 ShellExtensionsBrowserClient::CreateRuntimeAPIDelegate(
226     content::BrowserContext* context) const {
227   return std::make_unique<ShellRuntimeAPIDelegate>(context);
228 }
229 
230 const ComponentExtensionResourceManager*
GetComponentExtensionResourceManager()231 ShellExtensionsBrowserClient::GetComponentExtensionResourceManager() {
232   return NULL;
233 }
234 
BroadcastEventToRenderers(events::HistogramValue histogram_value,const std::string & event_name,std::unique_ptr<base::ListValue> args,bool dispatch_to_off_the_record_profiles)235 void ShellExtensionsBrowserClient::BroadcastEventToRenderers(
236     events::HistogramValue histogram_value,
237     const std::string& event_name,
238     std::unique_ptr<base::ListValue> args,
239     bool dispatch_to_off_the_record_profiles) {
240   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
241     base::PostTask(
242         FROM_HERE, {BrowserThread::UI},
243         base::BindOnce(&ShellExtensionsBrowserClient::BroadcastEventToRenderers,
244                        base::Unretained(this), histogram_value, event_name,
245                        std::move(args), dispatch_to_off_the_record_profiles));
246     return;
247   }
248 
249   std::unique_ptr<Event> event(
250       new Event(histogram_value, event_name, std::move(args)));
251   EventRouter::Get(browser_context_)->BroadcastEvent(std::move(event));
252 }
253 
GetExtensionCache()254 ExtensionCache* ShellExtensionsBrowserClient::GetExtensionCache() {
255   return extension_cache_.get();
256 }
257 
IsBackgroundUpdateAllowed()258 bool ShellExtensionsBrowserClient::IsBackgroundUpdateAllowed() {
259   return true;
260 }
261 
IsMinBrowserVersionSupported(const std::string & min_version)262 bool ShellExtensionsBrowserClient::IsMinBrowserVersionSupported(
263     const std::string& min_version) {
264   return true;
265 }
266 
SetAPIClientForTest(ExtensionsAPIClient * api_client)267 void ShellExtensionsBrowserClient::SetAPIClientForTest(
268     ExtensionsAPIClient* api_client) {
269   api_client_.reset(api_client);
270 }
271 
272 ExtensionWebContentsObserver*
GetExtensionWebContentsObserver(content::WebContents * web_contents)273 ShellExtensionsBrowserClient::GetExtensionWebContentsObserver(
274     content::WebContents* web_contents) {
275   return ShellExtensionWebContentsObserver::FromWebContents(web_contents);
276 }
277 
GetKioskDelegate()278 KioskDelegate* ShellExtensionsBrowserClient::GetKioskDelegate() {
279   if (!kiosk_delegate_)
280     kiosk_delegate_.reset(new ShellKioskDelegate());
281   return kiosk_delegate_.get();
282 }
283 
IsLockScreenContext(content::BrowserContext * context)284 bool ShellExtensionsBrowserClient::IsLockScreenContext(
285     content::BrowserContext* context) {
286   return false;
287 }
288 
GetApplicationLocale()289 std::string ShellExtensionsBrowserClient::GetApplicationLocale() {
290   // TODO(michaelpg): Use system locale.
291   return "en-US";
292 }
293 
GetUserAgent() const294 std::string ShellExtensionsBrowserClient::GetUserAgent() const {
295   return content::BuildUserAgentFromProduct(
296       version_info::GetProductNameAndVersionForUserAgent());
297 }
298 
InitWithBrowserContext(content::BrowserContext * context,PrefService * pref_service)299 void ShellExtensionsBrowserClient::InitWithBrowserContext(
300     content::BrowserContext* context,
301     PrefService* pref_service) {
302   DCHECK(!browser_context_);
303   DCHECK(!pref_service_);
304   browser_context_ = context;
305   pref_service_ = pref_service;
306 }
307 
308 }  // namespace extensions
309