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