blob: 550254cd9898e1fa0d5f1a80bc2af4938390170c [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commit09911bf2008-07-26 23:55:294
5#include "chrome/browser/browser_process_impl.h"
6
7#include "base/command_line.h"
initial.commit09911bf2008-07-26 23:55:298#include "base/path_service.h"
[email protected]ac262c9f2008-10-19 17:45:219#include "base/thread.h"
[email protected]1c4947f2009-01-15 22:25:1110#include "base/waitable_event.h"
initial.commit09911bf2008-07-26 23:55:2911#include "chrome/browser/automation/automation_provider_list.h"
[email protected]ac262c9f2008-10-19 17:45:2112#include "chrome/browser/browser_trial.h"
initial.commit09911bf2008-07-26 23:55:2913#include "chrome/browser/chrome_thread.h"
[email protected]cdaa8652008-09-13 02:48:5914#include "chrome/browser/download/download_file.h"
[email protected]c0264d42008-09-14 01:43:2415#include "chrome/browser/download/save_file_manager.h"
initial.commit09911bf2008-07-26 23:55:2916#include "chrome/browser/google_url_tracker.h"
17#include "chrome/browser/icon_manager.h"
[email protected]cd1adc22009-01-16 01:29:2218#include "chrome/browser/metrics/metrics_service.h"
initial.commit09911bf2008-07-26 23:55:2919#include "chrome/browser/plugin_service.h"
20#include "chrome/browser/printing/print_job_manager.h"
21#include "chrome/browser/profile_manager.h"
[email protected]8c8657d62009-01-16 18:31:2622#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]e3c404b2008-12-23 01:07:3223#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
initial.commit09911bf2008-07-26 23:55:2924#include "chrome/browser/safe_browsing/safe_browsing_service.h"
initial.commit09911bf2008-07-26 23:55:2925#include "chrome/browser/debugger/debugger_wrapper.h"
initial.commit09911bf2008-07-26 23:55:2926#include "chrome/common/chrome_paths.h"
27#include "chrome/common/chrome_switches.h"
28#include "chrome/common/clipboard_service.h"
29#include "chrome/common/l10n_util.h"
30#include "chrome/common/notification_service.h"
31#include "chrome/common/pref_names.h"
32#include "chrome/common/pref_service.h"
33#include "chrome/views/accelerator_handler.h"
34#include "chrome/views/view_storage.h"
35
36namespace {
37
38// ----------------------------------------------------------------------------
39// BrowserProcessSubThread
40//
41// This simple thread object is used for the specialized threads that the
42// BrowserProcess spins up.
43//
44// Applications must initialize the COM library before they can call
45// COM library functions other than CoGetMalloc and memory allocation
46// functions, so this class initializes COM for those users.
47class BrowserProcessSubThread : public ChromeThread {
48 public:
49 explicit BrowserProcessSubThread(ChromeThread::ID identifier)
50 : ChromeThread(identifier) {
51 }
52
53 ~BrowserProcessSubThread() {
54 // We cannot rely on our base class to stop the thread since we want our
55 // CleanUp function to run.
56 Stop();
57 }
58
59 protected:
60 virtual void Init() {
61 // Initializes the COM library on the current thread.
62 CoInitialize(NULL);
63
64 notification_service_ = new NotificationService;
65 }
66
67 virtual void CleanUp() {
68 delete notification_service_;
69 notification_service_ = NULL;
70
71 // Closes the COM library on the current thread. CoInitialize must
72 // be balanced by a corresponding call to CoUninitialize.
73 CoUninitialize();
74 }
75
76 private:
77 // Each specialized thread has its own notification service.
78 // Note: We don't use scoped_ptr because the destructor runs on the wrong
79 // thread.
80 NotificationService* notification_service_;
81};
82
83} // namespace
84
[email protected]bb975362009-01-21 01:00:2285BrowserProcessImpl::BrowserProcessImpl(const CommandLine& command_line)
initial.commit09911bf2008-07-26 23:55:2986 : created_resource_dispatcher_host_(false),
87 created_metrics_service_(false),
88 created_io_thread_(false),
89 created_file_thread_(false),
90 created_db_thread_(false),
91 created_profile_manager_(false),
92 created_local_state_(false),
93 created_icon_manager_(false),
94 initialized_broker_services_(false),
95 created_debugger_wrapper_(false),
96 broker_services_(NULL),
97 module_ref_count_(0),
[email protected]1b2db1a2008-08-08 17:46:1398 memory_model_(MEDIUM_MEMORY_MODEL),
99 checked_for_new_frames_(false),
100 using_new_frames_(false) {
initial.commit09911bf2008-07-26 23:55:29101 g_browser_process = this;
102 clipboard_service_.reset(new ClipboardService);
103 main_notification_service_.reset(new NotificationService);
104
105 // Must be created after the NotificationService.
106 print_job_manager_.reset(new printing::PrintJobManager);
107
108 // Configure the browser memory model.
109 if (command_line.HasSwitch(switches::kMemoryModel)) {
110 std::wstring model = command_line.GetSwitchValue(switches::kMemoryModel);
111 if (!model.empty()) {
112 if (model == L"high")
113 memory_model_ = HIGH_MEMORY_MODEL;
114 else if (model == L"low")
115 memory_model_ = LOW_MEMORY_MODEL;
116 else if (model == L"medium")
117 memory_model_ = MEDIUM_MEMORY_MODEL;
118 }
[email protected]ac262c9f2008-10-19 17:45:21119 } else {
120 // Randomly choose what memory model to use.
121 const double probability = 0.5;
122 FieldTrial* trial(new FieldTrial(BrowserTrial::kMemoryModelFieldTrial,
123 probability));
124 DCHECK(FieldTrialList::Find(BrowserTrial::kMemoryModelFieldTrial) == trial);
125 if (trial->boolean_value())
126 memory_model_ = HIGH_MEMORY_MODEL;
127 else
128 memory_model_ = MEDIUM_MEMORY_MODEL;
initial.commit09911bf2008-07-26 23:55:29129 }
130
[email protected]b797e152009-01-23 16:06:14131 shutdown_event_.reset(new base::WaitableEvent(true, false));
initial.commit09911bf2008-07-26 23:55:29132}
133
134BrowserProcessImpl::~BrowserProcessImpl() {
135 // Delete the AutomationProviderList before NotificationService,
136 // since it may try to unregister notifications
137 // Both NotificationService and AutomationProvider are singleton instances in
138 // the BrowserProcess. Since AutomationProvider may have some active
139 // notification observers, it is essential that it gets destroyed before the
140 // NotificationService. NotificationService won't be destroyed until after
141 // this destructor is run.
142 automation_provider_list_.reset();
143
144 // We need to destroy the MetricsService and GoogleURLTracker before the
145 // io_thread_ gets destroyed, since both destructors can call the URLFetcher
146 // destructor, which does an InvokeLater operation on the IO thread. (The IO
147 // thread will handle that URLFetcher operation before going away.)
148 metrics_service_.reset();
149 google_url_tracker_.reset();
150
151 // Need to clear profiles (download managers) before the io_thread_.
152 profile_manager_.reset();
153
154 // Debugger must be cleaned up before IO thread and NotificationService.
155 debugger_wrapper_ = NULL;
156
157 if (resource_dispatcher_host_.get()) {
158 // Need to tell Safe Browsing Service that the IO thread is going away
159 // since it cached a pointer to it.
160 if (resource_dispatcher_host()->safe_browsing_service())
161 resource_dispatcher_host()->safe_browsing_service()->ShutDown();
162
163 // Cancel pending requests and prevent new requests.
164 resource_dispatcher_host()->Shutdown();
165 }
166
167 // Need to stop io_thread_ before resource_dispatcher_host_, since
168 // io_thread_ may still deref ResourceDispatcherHost and handle resource
169 // request before going away.
170 io_thread_.reset();
171
172 // Clean up state that lives on the file_thread_ before it goes away.
173 if (resource_dispatcher_host_.get()) {
174 resource_dispatcher_host()->download_file_manager()->Shutdown();
175 resource_dispatcher_host()->save_file_manager()->Shutdown();
176 }
177
178 // Need to stop the file_thread_ here to force it to process messages in its
179 // message loop from the previous call to shutdown the DownloadFileManager,
180 // SaveFileManager and SessionService.
181 file_thread_.reset();
182
183 // With the file_thread_ flushed, we can release any icon resources.
184 icon_manager_.reset();
185
186 // Need to destroy ResourceDispatcherHost before PluginService and
187 // SafeBrowsingService, since it caches a pointer to it.
188 resource_dispatcher_host_.reset();
189
190 // Wait for the pending print jobs to finish.
191 print_job_manager_->OnQuit();
192 print_job_manager_.reset();
193
194 // The ViewStorage needs to go before the NotificationService.
[email protected]c2dacc92008-10-16 23:51:38195 views::ViewStorage::DeleteSharedInstance();
initial.commit09911bf2008-07-26 23:55:29196
197 // Now OK to destroy NotificationService.
198 main_notification_service_.reset();
199
200 g_browser_process = NULL;
201}
202
[email protected]295039bd2008-08-15 04:32:57203// Send a QuitTask to the given MessageLoop.
204static void PostQuit(MessageLoop* message_loop) {
205 message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask());
206}
initial.commit09911bf2008-07-26 23:55:29207
208void BrowserProcessImpl::EndSession() {
[email protected]d65cab7a2008-08-12 01:25:41209 // Notify we are going away.
[email protected]b797e152009-01-23 16:06:14210 ::SetEvent(shutdown_event_->handle());
[email protected]d65cab7a2008-08-12 01:25:41211
initial.commit09911bf2008-07-26 23:55:29212 // Mark all the profiles as clean.
213 ProfileManager* pm = profile_manager();
214 for (ProfileManager::const_iterator i = pm->begin(); i != pm->end(); ++i)
215 (*i)->MarkAsCleanShutdown();
216
217 // Tell the metrics service it was cleanly shutdown.
218 MetricsService* metrics = g_browser_process->metrics_service();
219 if (metrics && local_state()) {
220 metrics->RecordCleanShutdown();
221
222 metrics->RecordStartOfSessionEnd();
223
224 // MetricsService lazily writes to prefs, force it to write now.
225 local_state()->SavePersistentPrefs(file_thread());
226 }
227
228 // We must write that the profile and metrics service shutdown cleanly,
229 // otherwise on startup we'll think we crashed. So we block until done and
230 // then proceed with normal shutdown.
231 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
[email protected]295039bd2008-08-15 04:32:57232 NewRunnableFunction(PostQuit, MessageLoop::current()));
initial.commit09911bf2008-07-26 23:55:29233 MessageLoop::current()->Run();
234}
235
236printing::PrintJobManager* BrowserProcessImpl::print_job_manager() {
237 // TODO(abarth): DCHECK(CalledOnValidThread());
238 // See <http://b/1287209>.
239 // print_job_manager_ is initialized in the constructor and destroyed in the
240 // destructor, so it should always be valid.
241 DCHECK(print_job_manager_.get());
242 return print_job_manager_.get();
243}
244
245const std::wstring& BrowserProcessImpl::GetApplicationLocale() {
246 DCHECK(CalledOnValidThread());
247 if (locale_.empty()) {
248 locale_ = l10n_util::GetApplicationLocale(local_state()->GetString(
249 prefs::kApplicationLocale));
250 }
251 return locale_;
252}
253
254void BrowserProcessImpl::CreateResourceDispatcherHost() {
255 DCHECK(!created_resource_dispatcher_host_ &&
256 resource_dispatcher_host_.get() == NULL);
257 created_resource_dispatcher_host_ = true;
258
259 resource_dispatcher_host_.reset(
260 new ResourceDispatcherHost(io_thread()->message_loop()));
261 resource_dispatcher_host_->Initialize();
262}
263
264void BrowserProcessImpl::CreateMetricsService() {
265 DCHECK(!created_metrics_service_ && metrics_service_.get() == NULL);
266 created_metrics_service_ = true;
267
268 metrics_service_.reset(new MetricsService);
269}
270
271void BrowserProcessImpl::CreateIOThread() {
272 DCHECK(!created_io_thread_ && io_thread_.get() == NULL);
273 created_io_thread_ = true;
274
275 // Prior to starting the io thread, we create the plugin service as
276 // it is predominantly used from the io thread, but must be created
277 // on the main thread. The service ctor is inexpensive and does not
278 // invoke the io_thread() accessor.
279 PluginService::GetInstance();
280
[email protected]ab820df2008-08-26 05:55:10281 scoped_ptr<base::Thread> thread(
282 new BrowserProcessSubThread(ChromeThread::IO));
283 base::Thread::Options options;
284 options.message_loop_type = MessageLoop::TYPE_IO;
285 if (!thread->StartWithOptions(options))
initial.commit09911bf2008-07-26 23:55:29286 return;
287 io_thread_.swap(thread);
288}
289
290void BrowserProcessImpl::CreateFileThread() {
291 DCHECK(!created_file_thread_ && file_thread_.get() == NULL);
292 created_file_thread_ = true;
293
[email protected]ab820df2008-08-26 05:55:10294 scoped_ptr<base::Thread> thread(
295 new BrowserProcessSubThread(ChromeThread::FILE));
[email protected]a1db3842008-09-17 22:04:06296 base::Thread::Options options;
297 options.message_loop_type = MessageLoop::TYPE_UI;
298 if (!thread->StartWithOptions(options))
initial.commit09911bf2008-07-26 23:55:29299 return;
300 file_thread_.swap(thread);
301}
302
303void BrowserProcessImpl::CreateDBThread() {
304 DCHECK(!created_db_thread_ && db_thread_.get() == NULL);
305 created_db_thread_ = true;
306
[email protected]ab820df2008-08-26 05:55:10307 scoped_ptr<base::Thread> thread(
308 new BrowserProcessSubThread(ChromeThread::DB));
initial.commit09911bf2008-07-26 23:55:29309 if (!thread->Start())
310 return;
311 db_thread_.swap(thread);
312}
313
314void BrowserProcessImpl::CreateProfileManager() {
315 DCHECK(!created_profile_manager_ && profile_manager_.get() == NULL);
316 created_profile_manager_ = true;
317
318 profile_manager_.reset(new ProfileManager());
319}
320
321void BrowserProcessImpl::CreateLocalState() {
322 DCHECK(!created_local_state_ && local_state_.get() == NULL);
323 created_local_state_ = true;
324
325 std::wstring local_state_path;
326 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
327 local_state_.reset(new PrefService(local_state_path));
328}
329
330void BrowserProcessImpl::InitBrokerServices(
331 sandbox::BrokerServices* broker_services) {
332 DCHECK(!initialized_broker_services_ && broker_services_ == NULL);
333 broker_services->Init();
334 initialized_broker_services_ = true;
335 broker_services_ = broker_services;
336}
337
338void BrowserProcessImpl::CreateIconManager() {
339 DCHECK(!created_icon_manager_ && icon_manager_.get() == NULL);
340 created_icon_manager_ = true;
341 icon_manager_.reset(new IconManager);
342}
343
344void BrowserProcessImpl::CreateDebuggerWrapper(int port) {
345 DCHECK(debugger_wrapper_.get() == NULL);
346 created_debugger_wrapper_ = true;
347
348 debugger_wrapper_ = new DebuggerWrapper(port);
349}
350
351void BrowserProcessImpl::CreateAcceleratorHandler() {
352 DCHECK(accelerator_handler_.get() == NULL);
[email protected]c2dacc92008-10-16 23:51:38353 scoped_ptr<views::AcceleratorHandler> accelerator_handler(
354 new views::AcceleratorHandler);
initial.commit09911bf2008-07-26 23:55:29355 accelerator_handler_.swap(accelerator_handler);
356}
357
358void BrowserProcessImpl::CreateGoogleURLTracker() {
359 DCHECK(google_url_tracker_.get() == NULL);
360 scoped_ptr<GoogleURLTracker> google_url_tracker(new GoogleURLTracker);
361 google_url_tracker_.swap(google_url_tracker);
362}
license.botbf09a502008-08-24 00:55:55363