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.
5 #include "extensions/shell/browser/shell_browser_main_parts.h"
9 #include "base/command_line.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/run_loop.h"
12 #include "components/keyed_service/content/browser_context_dependency_manager.h"
13 #include "components/storage_monitor/storage_monitor.h"
14 #include "components/update_client/update_query_params.h"
15 #include "content/public/browser/child_process_security_policy.h"
16 #include "content/public/browser/context_factory.h"
17 #include "content/public/browser/devtools_http_handler.h"
18 #include "content/public/common/result_codes.h"
19 #include "content/shell/browser/shell_devtools_manager_delegate.h"
20 #include "extensions/browser/app_window/app_window_client.h"
21 #include "extensions/browser/browser_context_keyed_service_factories.h"
22 #include "extensions/browser/extension_system.h"
23 #include "extensions/browser/updater/update_service.h"
24 #include "extensions/common/constants.h"
25 #include "extensions/common/switches.h"
26 #include "extensions/shell/browser/shell_browser_context.h"
27 #include "extensions/shell/browser/shell_browser_context_keyed_service_factories.h"
28 #include "extensions/shell/browser/shell_browser_main_delegate.h"
29 #include "extensions/shell/browser/shell_desktop_controller_aura.h"
30 #include "extensions/shell/browser/shell_device_client.h"
31 #include "extensions/shell/browser/shell_extension_system.h"
32 #include "extensions/shell/browser/shell_extension_system_factory.h"
33 #include "extensions/shell/browser/shell_extensions_browser_client.h"
34 #include "extensions/shell/browser/shell_oauth2_token_service.h"
35 #include "extensions/shell/browser/shell_prefs.h"
36 #include "extensions/shell/browser/shell_update_query_params_delegate.h"
37 #include "extensions/shell/common/shell_extensions_client.h"
38 #include "extensions/shell/common/switches.h"
39 #include "ui/base/ime/input_method_initializer.h"
40 #include "ui/base/resource/resource_bundle.h"
43 #include "ui/aura/env.h"
46 #if defined(OS_CHROMEOS)
47 #include "chromeos/audio/audio_devices_pref_handler_impl.h"
48 #include "chromeos/audio/cras_audio_handler.h"
49 #include "chromeos/dbus/dbus_thread_manager.h"
50 #include "chromeos/disks/disk_mount_manager.h"
51 #include "chromeos/network/network_handler.h"
52 #include "extensions/shell/browser/shell_audio_controller_chromeos.h"
53 #include "extensions/shell/browser/shell_network_controller_chromeos.h"
56 #if defined(OS_MACOSX)
57 #include "extensions/shell/browser/shell_browser_main_parts_mac.h"
60 #if !defined(DISABLE_NACL)
61 #include "components/nacl/browser/nacl_browser.h"
62 #include "components/nacl/browser/nacl_process_host.h"
63 #include "content/public/browser/browser_thread.h"
64 #include "extensions/shell/browser/shell_nacl_browser_delegate.h"
67 using base::CommandLine
;
68 using content::BrowserContext
;
70 #if !defined(DISABLE_NACL)
71 using content::BrowserThread
;
74 namespace extensions
{
78 void CrxInstallComplete(bool success
) {
79 VLOG(1) << "CRX download complete. Success: " << success
;
83 ShellBrowserMainParts::ShellBrowserMainParts(
84 const content::MainFunctionParams
& parameters
,
85 ShellBrowserMainDelegate
* browser_main_delegate
)
86 : devtools_http_handler_(nullptr),
87 extension_system_(nullptr),
88 parameters_(parameters
),
89 run_message_loop_(true),
90 browser_main_delegate_(browser_main_delegate
) {
93 ShellBrowserMainParts::~ShellBrowserMainParts() {
94 DCHECK(!devtools_http_handler_
);
97 void ShellBrowserMainParts::PreMainMessageLoopStart() {
98 // TODO(jamescook): Initialize touch here?
99 #if defined(OS_MACOSX)
100 MainPartsPreMainMessageLoopStartMac();
104 void ShellBrowserMainParts::PostMainMessageLoopStart() {
105 #if defined(OS_CHROMEOS)
106 // Perform initialization of D-Bus objects here rather than in the below
107 // helper classes so those classes' tests can initialize stub versions of the
109 chromeos::DBusThreadManager::Initialize();
110 chromeos::disks::DiskMountManager::Initialize();
112 chromeos::NetworkHandler::Initialize();
113 network_controller_
.reset(new ShellNetworkController(
114 base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
115 switches::kAppShellPreferredNetwork
)));
117 // Non-Chrome OS platforms are for developer convenience, so use a test IME.
118 ui::InitializeInputMethodForTesting();
122 void ShellBrowserMainParts::PreEarlyInitialization() {
125 int ShellBrowserMainParts::PreCreateThreads() {
126 // TODO(jamescook): Initialize chromeos::CrosSettings here?
128 content::ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme(
130 content::ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme(
131 kExtensionResourceScheme
);
137 void ShellBrowserMainParts::PreMainMessageLoopRun() {
138 // Initialize our "profile" equivalent.
139 browser_context_
.reset(new ShellBrowserContext
);
141 // app_shell only supports a single user, so all preferences live in the user
142 // data directory, including the device-wide local state.
143 local_state_
= shell_prefs::CreateLocalState(browser_context_
->GetPath());
145 shell_prefs::CreateUserPrefService(browser_context_
.get());
147 #if defined(OS_CHROMEOS)
148 chromeos::CrasAudioHandler::Initialize(
149 new chromeos::AudioDevicesPrefHandlerImpl(local_state_
.get()));
150 audio_controller_
.reset(new ShellAudioController());
153 #if defined(USE_AURA)
154 aura::Env::GetInstance()->set_context_factory(content::GetContextFactory());
157 storage_monitor::StorageMonitor::Create();
159 desktop_controller_
.reset(browser_main_delegate_
->CreateDesktopController());
161 // TODO(jamescook): Initialize user_manager::UserManager.
163 device_client_
.reset(new ShellDeviceClient
);
165 extensions_client_
.reset(CreateExtensionsClient());
166 ExtensionsClient::Set(extensions_client_
.get());
168 extensions_browser_client_
.reset(CreateExtensionsBrowserClient(
169 browser_context_
.get(), user_pref_service_
.get()));
170 ExtensionsBrowserClient::Set(extensions_browser_client_
.get());
172 update_query_params_delegate_
.reset(new ShellUpdateQueryParamsDelegate
);
173 update_client::UpdateQueryParams::SetDelegate(
174 update_query_params_delegate_
.get());
176 // Create our custom ExtensionSystem first because other
177 // KeyedServices depend on it.
178 // TODO(yoz): Move this after EnsureBrowserContextKeyedServiceFactoriesBuilt.
179 CreateExtensionSystem();
181 // Register additional KeyedService factories here. See
182 // ChromeBrowserMainExtraPartsProfiles for details.
183 EnsureBrowserContextKeyedServiceFactoriesBuilt();
184 ShellExtensionSystemFactory::GetInstance();
186 BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
187 browser_context_
.get());
189 // Initialize OAuth2 support from command line.
190 base::CommandLine
* cmd
= base::CommandLine::ForCurrentProcess();
191 oauth2_token_service_
.reset(new ShellOAuth2TokenService(
192 browser_context_
.get(),
193 cmd
->GetSwitchValueASCII(switches::kAppShellUser
),
194 cmd
->GetSwitchValueASCII(switches::kAppShellRefreshToken
)));
196 #if !defined(DISABLE_NACL)
198 nacl::NaClBrowser::SetDelegate(
199 new ShellNaClBrowserDelegate(browser_context_
.get()));
200 // Track the task so it can be canceled if app_shell shuts down very quickly,
201 // such as in browser tests.
202 task_tracker_
.PostTask(
203 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
).get(),
205 base::Bind(nacl::NaClProcessHost::EarlyStartup
));
208 // TODO(rockot): Remove this temporary hack test.
209 std::string install_crx_id
=
210 cmd
->GetSwitchValueASCII(switches::kAppShellInstallCrx
);
211 if (install_crx_id
.size() != 0) {
212 CHECK(install_crx_id
.size() == 32)
213 << "Extension ID must be exactly 32 characters long.";
214 UpdateService
* update_service
= UpdateService::Get(browser_context_
.get());
215 update_service
->DownloadAndInstall(install_crx_id
,
216 base::Bind(CrxInstallComplete
));
219 devtools_http_handler_
.reset(
220 content::ShellDevToolsManagerDelegate::CreateHttpHandler(
221 browser_context_
.get()));
222 if (parameters_
.ui_task
) {
223 // For running browser tests.
224 parameters_
.ui_task
->Run();
225 delete parameters_
.ui_task
;
226 run_message_loop_
= false;
228 browser_main_delegate_
->Start(browser_context_
.get());
232 bool ShellBrowserMainParts::MainMessageLoopRun(int* result_code
) {
233 if (!run_message_loop_
)
235 // TODO(yoz): just return false here?
236 base::RunLoop run_loop
;
238 *result_code
= content::RESULT_CODE_NORMAL_EXIT
;
242 void ShellBrowserMainParts::PostMainMessageLoopRun() {
243 // NOTE: Please destroy objects in the reverse order of their creation.
244 browser_main_delegate_
->Shutdown();
245 devtools_http_handler_
.reset();
247 #if !defined(DISABLE_NACL)
248 task_tracker_
.TryCancelAll();
249 nacl::NaClBrowser::SetDelegate(nullptr);
252 oauth2_token_service_
.reset();
253 BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
254 browser_context_
.get());
255 extension_system_
= NULL
;
256 ExtensionsBrowserClient::Set(NULL
);
257 extensions_browser_client_
.reset();
259 desktop_controller_
.reset();
261 storage_monitor::StorageMonitor::Destroy();
263 #if defined(OS_CHROMEOS)
264 audio_controller_
.reset();
265 chromeos::CrasAudioHandler::Shutdown();
268 user_pref_service_
->CommitPendingWrite();
269 user_pref_service_
.reset();
270 local_state_
->CommitPendingWrite();
271 local_state_
.reset();
273 browser_context_
.reset();
276 void ShellBrowserMainParts::PostDestroyThreads() {
277 #if defined(OS_CHROMEOS)
278 network_controller_
.reset();
279 chromeos::NetworkHandler::Shutdown();
280 chromeos::disks::DiskMountManager::Shutdown();
281 chromeos::DBusThreadManager::Shutdown();
285 ExtensionsClient
* ShellBrowserMainParts::CreateExtensionsClient() {
286 return new ShellExtensionsClient();
289 ExtensionsBrowserClient
* ShellBrowserMainParts::CreateExtensionsBrowserClient(
290 content::BrowserContext
* context
,
291 PrefService
* service
) {
292 return new ShellExtensionsBrowserClient(context
, service
);
295 void ShellBrowserMainParts::CreateExtensionSystem() {
296 DCHECK(browser_context_
);
297 extension_system_
= static_cast<ShellExtensionSystem
*>(
298 ExtensionSystem::Get(browser_context_
.get()));
299 extension_system_
->InitForRegularProfile(true);
302 } // namespace extensions