Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: chrome/browser/renderer_host/browser_render_process_host.cc

Issue 397031: Launch processes asynchronously so as not to block the UI thread. For now, re... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: return 0 instead of -1 if zygote couldn't launch renderer Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Represents the browser side of the browser <--> renderer communication 5 // Represents the browser side of the browser <--> renderer communication
6 // channel. There will be one RenderProcessHost per renderer process. 6 // channel. There will be one RenderProcessHost per renderer process.
7 7
8 #include "chrome/browser/renderer_host/browser_render_process_host.h" 8 #include "chrome/browser/renderer_host/browser_render_process_host.h"
9 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <limits> 11 #include <limits>
12 #include <vector> 12 #include <vector>
13 13
14 #if defined(OS_POSIX) 14 #if defined(OS_POSIX)
15 #include <utility> // for pair<> 15 #include <utility> // for pair<>
16 #endif 16 #endif
17 17
18 #include "app/app_switches.h" 18 #include "app/app_switches.h"
19 #include "base/command_line.h" 19 #include "base/command_line.h"
20 #include "base/field_trial.h" 20 #include "base/field_trial.h"
21 #include "base/logging.h" 21 #include "base/logging.h"
22 #include "base/process_util.h" 22 #include "base/process_util.h"
23 #include "base/stl_util-inl.h"
23 #include "base/string_util.h" 24 #include "base/string_util.h"
24 #include "base/thread.h" 25 #include "base/thread.h"
25 #include "chrome/browser/browser_process.h" 26 #include "chrome/browser/browser_process.h"
26 #include "chrome/browser/child_process_security_policy.h" 27 #include "chrome/browser/child_process_security_policy.h"
27 #include "chrome/browser/extensions/extension_function_dispatcher.h" 28 #include "chrome/browser/extensions/extension_function_dispatcher.h"
28 #include "chrome/browser/extensions/extension_message_service.h" 29 #include "chrome/browser/extensions/extension_message_service.h"
29 #include "chrome/browser/extensions/extensions_service.h" 30 #include "chrome/browser/extensions/extensions_service.h"
30 #include "chrome/browser/extensions/user_script_master.h" 31 #include "chrome/browser/extensions/user_script_master.h"
31 #include "chrome/browser/history/history.h" 32 #include "chrome/browser/history/history.h"
32 #include "chrome/browser/net/url_request_context_getter.h" 33 #include "chrome/browser/net/url_request_context_getter.h"
33 #include "chrome/browser/plugin_service.h" 34 #include "chrome/browser/plugin_service.h"
34 #include "chrome/browser/profile.h" 35 #include "chrome/browser/profile.h"
35 #include "chrome/browser/renderer_host/audio_renderer_host.h" 36 #include "chrome/browser/renderer_host/audio_renderer_host.h"
36 #include "chrome/browser/renderer_host/render_view_host.h" 37 #include "chrome/browser/renderer_host/render_view_host.h"
37 #include "chrome/browser/renderer_host/render_view_host_delegate.h" 38 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
38 #include "chrome/browser/renderer_host/render_widget_helper.h" 39 #include "chrome/browser/renderer_host/render_widget_helper.h"
39 #include "chrome/browser/renderer_host/render_widget_host.h" 40 #include "chrome/browser/renderer_host/render_widget_host.h"
40 #include "chrome/browser/renderer_host/resource_message_filter.h" 41 #include "chrome/browser/renderer_host/resource_message_filter.h"
41 #include "chrome/browser/renderer_host/web_cache_manager.h" 42 #include "chrome/browser/renderer_host/web_cache_manager.h"
42 #if defined(SPELLCHECKER_IN_RENDERER) 43 #if defined(SPELLCHECKER_IN_RENDERER)
43 #include "chrome/browser/spellcheck_host.h" 44 #include "chrome/browser/spellcheck_host.h"
44 #endif 45 #endif
45 #include "chrome/browser/spellchecker.h" 46 #include "chrome/browser/spellchecker.h"
46 #include "chrome/browser/visitedlink_master.h" 47 #include "chrome/browser/visitedlink_master.h"
47 #include "chrome/common/chrome_switches.h" 48 #include "chrome/common/chrome_switches.h"
48 #include "chrome/common/child_process_info.h" 49 #include "chrome/common/child_process_info.h"
49 #include "chrome/common/child_process_host.h" 50 #include "chrome/common/child_process_host.h"
50 #include "chrome/common/chrome_descriptors.h"
51 #include "chrome/common/logging_chrome.h" 51 #include "chrome/common/logging_chrome.h"
52 #include "chrome/common/notification_service.h" 52 #include "chrome/common/notification_service.h"
53 #include "chrome/common/process_watcher.h"
54 #include "chrome/common/render_messages.h" 53 #include "chrome/common/render_messages.h"
55 #include "chrome/common/result_codes.h" 54 #include "chrome/common/result_codes.h"
56 #include "chrome/renderer/render_process.h" 55 #include "chrome/renderer/render_process.h"
57 #include "chrome/renderer/render_thread.h" 56 #include "chrome/renderer/render_thread.h"
58 #include "grit/generated_resources.h" 57 #include "grit/generated_resources.h"
59 #include "ipc/ipc_logging.h" 58 #include "ipc/ipc_logging.h"
60 #include "ipc/ipc_message.h" 59 #include "ipc/ipc_message.h"
61 #include "ipc/ipc_platform_file.h" 60 #include "ipc/ipc_platform_file.h"
62 #include "ipc/ipc_switches.h" 61 #include "ipc/ipc_switches.h"
63 62
64 #if defined(OS_WIN) 63 #if defined(OS_WIN)
65 #include "app/win_util.h" 64 #include "app/win_util.h"
66 #include "chrome/browser/sandbox_policy.h"
67 #elif defined(OS_LINUX)
68 #include "base/singleton.h"
69 #include "chrome/browser/crash_handler_host_linux.h"
70 #include "chrome/browser/zygote_host_linux.h"
71 #include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
72 #endif 65 #endif
73 66
74 using WebKit::WebCache; 67 using WebKit::WebCache;
75 68
76 #include "third_party/skia/include/core/SkBitmap.h" 69 #include "third_party/skia/include/core/SkBitmap.h"
77 70
78 71
79 // This class creates the IO thread for the renderer when running in 72 // This class creates the IO thread for the renderer when running in
80 // single-process mode. It's not used in multi-process mode. 73 // single-process mode. It's not used in multi-process mode.
81 class RendererMainThread : public base::Thread { 74 class RendererMainThread : public base::Thread {
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 VisitedLinkCommon::Fingerprints pending_; 187 VisitedLinkCommon::Fingerprints pending_;
195 }; 188 };
196 189
197 BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile) 190 BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile)
198 : RenderProcessHost(profile), 191 : RenderProcessHost(profile),
199 visible_widgets_(0), 192 visible_widgets_(0),
200 backgrounded_(true), 193 backgrounded_(true),
201 ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_( 194 ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_(
202 base::TimeDelta::FromSeconds(5), 195 base::TimeDelta::FromSeconds(5),
203 this, &BrowserRenderProcessHost::ClearTransportDIBCache)), 196 this, &BrowserRenderProcessHost::ClearTransportDIBCache)),
204 zygote_child_(false),
205 extension_process_(false) { 197 extension_process_(false) {
206 widget_helper_ = new RenderWidgetHelper(); 198 widget_helper_ = new RenderWidgetHelper();
207 199
208 registrar_.Add(this, NotificationType::USER_SCRIPTS_UPDATED, 200 registrar_.Add(this, NotificationType::USER_SCRIPTS_UPDATED,
209 NotificationService::AllSources()); 201 NotificationService::AllSources());
210 #if defined(SPELLCHECKER_IN_RENDERER) 202 #if defined(SPELLCHECKER_IN_RENDERER)
211 registrar_.Add(this, NotificationType::SPELLCHECK_HOST_REINITIALIZED, 203 registrar_.Add(this, NotificationType::SPELLCHECK_HOST_REINITIALIZED,
212 NotificationService::AllSources()); 204 NotificationService::AllSources());
213 registrar_.Add(this, NotificationType::SPELLCHECK_WORD_ADDED, 205 registrar_.Add(this, NotificationType::SPELLCHECK_WORD_ADDED,
214 NotificationService::AllSources()); 206 NotificationService::AllSources());
(...skipping 17 matching lines...) Expand all
232 #if defined(SPELLCHECKER_IN_RENDERER) 224 #if defined(SPELLCHECKER_IN_RENDERER)
233 PrefService* prefs = profile()->GetPrefs(); 225 PrefService* prefs = profile()->GetPrefs();
234 prefs->RemovePrefObserver(prefs::kEnableAutoSpellCorrect, this); 226 prefs->RemovePrefObserver(prefs::kEnableAutoSpellCorrect, this);
235 #endif 227 #endif
236 228
237 WebCacheManager::GetInstance()->Remove(id()); 229 WebCacheManager::GetInstance()->Remove(id());
238 ChildProcessSecurityPolicy::GetInstance()->Remove(id()); 230 ChildProcessSecurityPolicy::GetInstance()->Remove(id());
239 231
240 // We may have some unsent messages at this point, but that's OK. 232 // We may have some unsent messages at this point, but that's OK.
241 channel_.reset(); 233 channel_.reset();
234 while (!queued_messages_.empty()) {
235 delete queued_messages_.front();
236 queued_messages_.pop();
237 }
242 238
243 // Destroy the AudioRendererHost properly. 239 // Destroy the AudioRendererHost properly.
244 if (audio_renderer_host_.get()) 240 if (audio_renderer_host_.get())
245 audio_renderer_host_->Destroy(); 241 audio_renderer_host_->Destroy();
246 242
247 if (process_.handle() && !run_renderer_in_process()) {
248 if (zygote_child_) {
249 #if defined(OS_LINUX)
250 Singleton<ZygoteHost>()->EnsureProcessTerminated(process_.handle());
251 #endif
252 } else {
253 ProcessWatcher::EnsureProcessTerminated(process_.handle());
254 }
255 }
256
257 ClearTransportDIBCache(); 243 ClearTransportDIBCache();
258 244
259 NotificationService::current()->Notify( 245 NotificationService::current()->Notify(
260 NotificationType::EXTENSION_PORT_DELETED_DEBUG, 246 NotificationType::EXTENSION_PORT_DELETED_DEBUG,
261 Source<IPC::Message::Sender>(this), 247 Source<IPC::Message::Sender>(this),
262 NotificationService::NoDetails()); 248 NotificationService::NoDetails());
263 } 249 }
264 250
265 bool BrowserRenderProcessHost::Init(bool is_extensions_process, 251 bool BrowserRenderProcessHost::Init(bool is_extensions_process,
266 URLRequestContextGetter* request_context) { 252 URLRequestContextGetter* request_context) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 channel_.reset( 292 channel_.reset(
307 new IPC::SyncChannel(channel_id, IPC::Channel::MODE_SERVER, this, 293 new IPC::SyncChannel(channel_id, IPC::Channel::MODE_SERVER, this,
308 resource_message_filter, 294 resource_message_filter,
309 io_thread->message_loop(), true, 295 io_thread->message_loop(), true,
310 g_browser_process->shutdown_event())); 296 g_browser_process->shutdown_event()));
311 // As a preventive mesure, we DCHECK if someone sends a synchronous message 297 // As a preventive mesure, we DCHECK if someone sends a synchronous message
312 // with no time-out, which in the context of the browser process we should not 298 // with no time-out, which in the context of the browser process we should not
313 // be doing. 299 // be doing.
314 channel_->set_sync_messages_with_no_timeout_allowed(false); 300 channel_->set_sync_messages_with_no_timeout_allowed(false);
315 301
316 // Build command line for renderer, we have to quote the executable name to
317 // deal with spaces.
318 CommandLine cmd_line(renderer_path);
319 cmd_line.AppendSwitchWithValue(switches::kProcessChannelID,
320 ASCIIToWide(channel_id));
321 if (is_extensions_process)
322 cmd_line.AppendSwitch(switches::kEnableDatabases);
323 bool has_cmd_prefix;
324 AppendRendererCommandLine(&cmd_line, &has_cmd_prefix);
325
326 if (run_renderer_in_process()) { 302 if (run_renderer_in_process()) {
327 // Crank up a thread and run the initialization there. With the way that 303 // Crank up a thread and run the initialization there. With the way that
328 // messages flow between the browser and renderer, this thread is required 304 // messages flow between the browser and renderer, this thread is required
329 // to prevent a deadlock in single-process mode. Since the primordial 305 // to prevent a deadlock in single-process mode. Since the primordial
330 // thread in the renderer process runs the WebKit code and can sometimes 306 // thread in the renderer process runs the WebKit code and can sometimes
331 // make blocking calls to the UI thread (i.e. this thread), they need to run 307 // make blocking calls to the UI thread (i.e. this thread), they need to run
332 // on separate threads. 308 // on separate threads.
333 in_process_renderer_.reset(new RendererMainThread(channel_id)); 309 in_process_renderer_.reset(new RendererMainThread(channel_id));
334 310
335 base::Thread::Options options; 311 base::Thread::Options options;
336 #if !defined(OS_LINUX) 312 #if !defined(OS_LINUX)
337 // In-process plugins require this to be a UI message loop. 313 // In-process plugins require this to be a UI message loop.
338 options.message_loop_type = MessageLoop::TYPE_UI; 314 options.message_loop_type = MessageLoop::TYPE_UI;
339 #else 315 #else
340 // We can't have multiple UI loops on Linux, so we don't support 316 // We can't have multiple UI loops on Linux, so we don't support
341 // in-process plugins. 317 // in-process plugins.
342 options.message_loop_type = MessageLoop::TYPE_DEFAULT; 318 options.message_loop_type = MessageLoop::TYPE_DEFAULT;
343 #endif 319 #endif
344 in_process_renderer_->StartWithOptions(options); 320 in_process_renderer_->StartWithOptions(options);
321
322 OnProcessLaunched(); // Fake a callback that the process is ready.
345 } else { 323 } else {
346 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); 324 // Build command line for renderer, we have to quote the executable name to
325 // deal with spaces.
326 scoped_ptr<CommandLine> cmd_line(new CommandLine(renderer_path));
327 cmd_line->AppendSwitchWithValue(switches::kProcessChannelID,
328 ASCIIToWide(channel_id));
329 if (is_extensions_process)
330 cmd_line->AppendSwitch(switches::kEnableDatabases);
331 AppendRendererCommandLine(cmd_line.get());
347 332
348 // Actually spawn the child process. 333 // Spawn the child process asynchronously to avoid blocking the UI thread.
349 base::ProcessHandle process = ExecuteRenderer(&cmd_line, has_cmd_prefix); 334 child_process_.reset(new ChildProcessLauncher(
350 if (!process) { 335 cmd_line.release(), channel_.get(), this));
351 channel_.reset(); 336
352 return false;
353 }
354 process_.set_handle(process);
355 fast_shutdown_started_ = false; 337 fast_shutdown_started_ = false;
356
357 // Log the launch time, separating out the first one (which will likely be
358 // slower due to the rest of the browser initializing at the same time).
359 static bool done_first_launch = false;
360 if (done_first_launch) {
361 UMA_HISTOGRAM_TIMES("MPArch.RendererLaunchSubsequent",
362 base::TimeTicks::Now() - begin_launch_time);
363 } else {
364 UMA_HISTOGRAM_TIMES("MPArch.RendererLaunchFirst",
365 base::TimeTicks::Now() - begin_launch_time);
366 done_first_launch = true;
367 }
368 } 338 }
369 339
370 // Now that the process is created, set its backgrounding accordingly.
371 SetBackgrounded(backgrounded_);
372
373 InitVisitedLinks();
374 InitUserScripts();
375 InitExtensions();
376 #if defined(SPELLCHECKER_IN_RENDERER)
377 // We don't want to initialize the spellchecker unless SpellCheckHost has been
378 // created. In InitSpellChecker(), we know if GetSpellCheckHost() is NULL
379 // then the spellchecker has been turned off, but here, we don't know if
380 // it's been turned off or just not loaded yet.
381 if (profile()->GetSpellCheckHost())
382 InitSpellChecker();
383 #endif
384
385 if (max_page_id_ != -1)
386 Send(new ViewMsg_SetNextPageID(max_page_id_ + 1));
387
388 return true; 340 return true;
389 } 341 }
390 342
391 int BrowserRenderProcessHost::GetNextRoutingID() { 343 int BrowserRenderProcessHost::GetNextRoutingID() {
392 return widget_helper_->GetNextRoutingID(); 344 return widget_helper_->GetNextRoutingID();
393 } 345 }
394 346
395 void BrowserRenderProcessHost::CancelResourceRequests(int render_widget_id) { 347 void BrowserRenderProcessHost::CancelResourceRequests(int render_widget_id) {
396 widget_helper_->CancelResourceRequests(render_widget_id); 348 widget_helper_->CancelResourceRequests(render_widget_id);
397 } 349 }
398 350
399 void BrowserRenderProcessHost::CrossSiteClosePageACK( 351 void BrowserRenderProcessHost::CrossSiteClosePageACK(
400 const ViewMsg_ClosePage_Params& params) { 352 const ViewMsg_ClosePage_Params& params) {
401 widget_helper_->CrossSiteClosePageACK(params); 353 widget_helper_->CrossSiteClosePageACK(params);
402 } 354 }
403 355
404 bool BrowserRenderProcessHost::WaitForPaintMsg(int render_widget_id, 356 bool BrowserRenderProcessHost::WaitForPaintMsg(int render_widget_id,
405 const base::TimeDelta& max_delay, 357 const base::TimeDelta& max_delay,
406 IPC::Message* msg) { 358 IPC::Message* msg) {
359 // The post task to this thread with the process id could be in queue, and we
360 // don't want to dispatch a message before then since it will need the handle.
361 if (child_process_.get() && child_process_->IsStarting())
362 return false;
363
407 return widget_helper_->WaitForPaintMsg(render_widget_id, max_delay, msg); 364 return widget_helper_->WaitForPaintMsg(render_widget_id, max_delay, msg);
408 } 365 }
409 366
410 void BrowserRenderProcessHost::ReceivedBadMessage(uint16 msg_type) { 367 void BrowserRenderProcessHost::ReceivedBadMessage(uint16 msg_type) {
411 BadMessageTerminateProcess(msg_type, process_.handle()); 368 BadMessageTerminateProcess(msg_type, GetHandle());
412 } 369 }
413 370
414 void BrowserRenderProcessHost::ViewCreated() { 371 void BrowserRenderProcessHost::ViewCreated() {
415 visited_link_updater_->ReceiverReady(this); 372 visited_link_updater_->ReceiverReady(this);
416 } 373 }
417 374
418 void BrowserRenderProcessHost::WidgetRestored() { 375 void BrowserRenderProcessHost::WidgetRestored() {
419 // Verify we were properly backgrounded. 376 // Verify we were properly backgrounded.
420 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0)); 377 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
421 visible_widgets_++; 378 visible_widgets_++;
(...skipping 17 matching lines...) Expand all
439 396
440 void BrowserRenderProcessHost::AddWord(const string16& word) { 397 void BrowserRenderProcessHost::AddWord(const string16& word) {
441 SpellChecker* spellchecker = profile()->GetSpellChecker(); 398 SpellChecker* spellchecker = profile()->GetSpellChecker();
442 if (spellchecker) { 399 if (spellchecker) {
443 ChromeThread::PostTask( 400 ChromeThread::PostTask(
444 ChromeThread::IO, FROM_HERE, 401 ChromeThread::IO, FROM_HERE,
445 NewRunnableMethod(spellchecker, &SpellChecker::AddWord, word)); 402 NewRunnableMethod(spellchecker, &SpellChecker::AddWord, word));
446 } 403 }
447 } 404 }
448 405
406 void BrowserRenderProcessHost::SendVisitedLinkTable(
407 base::SharedMemory* table_memory) {
408 // Check if the process is still starting and we don't have a handle for it
409 // yet, in which case this will happen later when InitVisitedLinks is called.
410 if (!run_renderer_in_process() &&
411 (!child_process_.get() || child_process_->IsStarting())) {
412 return;
413 }
414
415 base::SharedMemoryHandle handle_for_process;
416 table_memory->ShareToProcess(GetHandle(), &handle_for_process);
417 if (base::SharedMemory::IsHandleValid(handle_for_process))
418 Send(new ViewMsg_VisitedLink_NewTable(handle_for_process));
419 }
420
449 void BrowserRenderProcessHost::AddVisitedLinks( 421 void BrowserRenderProcessHost::AddVisitedLinks(
450 const VisitedLinkCommon::Fingerprints& links) { 422 const VisitedLinkCommon::Fingerprints& links) {
451 visited_link_updater_->AddLinks(links); 423 visited_link_updater_->AddLinks(links);
452 if (visible_widgets_ == 0) 424 if (visible_widgets_ == 0)
453 return; 425 return;
454 426
455 visited_link_updater_->Update(this); 427 visited_link_updater_->Update(this);
456 } 428 }
457 429
458 void BrowserRenderProcessHost::ResetVisitedLinks() { 430 void BrowserRenderProcessHost::ResetVisitedLinks() {
459 visited_link_updater_->AddReset(); 431 visited_link_updater_->AddReset();
460 if (visible_widgets_ == 0) 432 if (visible_widgets_ == 0)
461 return; 433 return;
462 434
463 visited_link_updater_->Update(this); 435 visited_link_updater_->Update(this);
464 } 436 }
465 437
466 void BrowserRenderProcessHost::AppendRendererCommandLine( 438 void BrowserRenderProcessHost::AppendRendererCommandLine(
467 CommandLine* command_line, 439 CommandLine* command_line) const {
468 bool* has_cmd_prefix) const {
469 if (logging::DialogsAreSuppressed()) 440 if (logging::DialogsAreSuppressed())
470 command_line->AppendSwitch(switches::kNoErrorDialogs); 441 command_line->AppendSwitch(switches::kNoErrorDialogs);
471 442
472 // Pass the process type first, so it shows first in process listings. 443 // Pass the process type first, so it shows first in process listings.
473 // Extensions use a special pseudo-process type to make them distinguishable, 444 // Extensions use a special pseudo-process type to make them distinguishable,
474 // even though they're just renderers. 445 // even though they're just renderers.
475 command_line->AppendSwitchWithValue(switches::kProcessType, 446 command_line->AppendSwitchWithValue(switches::kProcessType,
476 extension_process_ ? switches::kExtensionProcess : 447 extension_process_ ? switches::kExtensionProcess :
477 switches::kRendererProcess); 448 switches::kRendererProcess);
478 449
(...skipping 11 matching lines...) Expand all
490 std::string field_trial_states; 461 std::string field_trial_states;
491 FieldTrialList::StatesToString(&field_trial_states); 462 FieldTrialList::StatesToString(&field_trial_states);
492 if (!field_trial_states.empty()) { 463 if (!field_trial_states.empty()) {
493 command_line->AppendSwitchWithValue(switches::kForceFieldTestNameAndValue, 464 command_line->AppendSwitchWithValue(switches::kForceFieldTestNameAndValue,
494 field_trial_states); 465 field_trial_states);
495 } 466 }
496 467
497 // A command prefix is something prepended to the command line of the spawned 468 // A command prefix is something prepended to the command line of the spawned
498 // process. It is supported only on POSIX systems. 469 // process. It is supported only on POSIX systems.
499 #if defined(OS_POSIX) 470 #if defined(OS_POSIX)
500 *has_cmd_prefix = 471 if (browser_command_line.HasSwitch(switches::kRendererCmdPrefix)) {
501 browser_command_line.HasSwitch(switches::kRendererCmdPrefix);
502 if (*has_cmd_prefix) {
503 // launch the renderer child with some prefix (usually "gdb --args") 472 // launch the renderer child with some prefix (usually "gdb --args")
504 const std::wstring prefix = 473 const std::wstring prefix =
505 browser_command_line.GetSwitchValue(switches::kRendererCmdPrefix); 474 browser_command_line.GetSwitchValue(switches::kRendererCmdPrefix);
506 command_line->PrependWrapper(prefix); 475 command_line->PrependWrapper(prefix);
507 } 476 }
508 #else
509 *has_cmd_prefix = false;
510 #endif // defined(OS_POSIX) 477 #endif // defined(OS_POSIX)
511 478
512 ChildProcessHost::SetCrashReporterCommandLine(command_line); 479 ChildProcessHost::SetCrashReporterCommandLine(command_line);
513 480
514 const std::string& profile_path = 481 const std::string& profile_path =
515 browser_command_line.GetSwitchValueASCII(switches::kUserDataDir); 482 browser_command_line.GetSwitchValueASCII(switches::kUserDataDir);
516 if (!profile_path.empty()) 483 if (!profile_path.empty())
517 command_line->AppendSwitchWithValue(switches::kUserDataDir, profile_path); 484 command_line->AppendSwitchWithValue(switches::kUserDataDir, profile_path);
518 } 485 }
519 486
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 if (!profile()->IsOffTheRecord()) { 558 if (!profile()->IsOffTheRecord()) {
592 for (size_t i = 0; i < arraysize(not_otr_switch_names); ++i) { 559 for (size_t i = 0; i < arraysize(not_otr_switch_names); ++i) {
593 if (browser_cmd.HasSwitch(not_otr_switch_names[i])) { 560 if (browser_cmd.HasSwitch(not_otr_switch_names[i])) {
594 renderer_cmd->AppendSwitchWithValue(not_otr_switch_names[i], 561 renderer_cmd->AppendSwitchWithValue(not_otr_switch_names[i],
595 browser_cmd.GetSwitchValueASCII(not_otr_switch_names[i])); 562 browser_cmd.GetSwitchValueASCII(not_otr_switch_names[i]));
596 } 563 }
597 } 564 }
598 } 565 }
599 } 566 }
600 567
601 #if defined(OS_WIN)
602
603 base::ProcessHandle BrowserRenderProcessHost::ExecuteRenderer(
604 CommandLine* cmd_line,
605 bool has_cmd_prefix) {
606 return sandbox::StartProcess(cmd_line);
607 }
608
609 #elif defined(OS_POSIX)
610
611 base::ProcessHandle BrowserRenderProcessHost::ExecuteRenderer(
612 CommandLine* cmd_line,
613 bool has_cmd_prefix) {
614 #if defined(OS_LINUX)
615 // On Linux, normally spawn processes with zygotes. We can't do this when
616 // we're spawning child processes through an external program (i.e. there is a
617 // command prefix) like GDB so fall through to the POSIX case then.
618 if (!has_cmd_prefix) {
619 base::GlobalDescriptors::Mapping mapping;
620 const int ipcfd = channel_->GetClientFileDescriptor();
621 mapping.push_back(std::pair<uint32_t, int>(kPrimaryIPCChannel, ipcfd));
622 const int crash_signal_fd =
623 Singleton<RendererCrashHandlerHostLinux>()->GetDeathSignalSocket();
624 if (crash_signal_fd >= 0) {
625 mapping.push_back(std::pair<uint32_t, int>(kCrashDumpSignal,
626 crash_signal_fd));
627 }
628 zygote_child_ = true;
629 return Singleton<ZygoteHost>()->ForkRenderer(cmd_line->argv(), mapping);
630 }
631 #endif // defined(OS_LINUX)
632
633 // NOTE: This code is duplicated with plugin_process_host.cc, but
634 // there's not a good place to de-duplicate it.
635 base::file_handle_mapping_vector fds_to_map;
636 const int ipcfd = channel_->GetClientFileDescriptor();
637 fds_to_map.push_back(std::make_pair(ipcfd, kPrimaryIPCChannel + 3));
638
639 #if defined(OS_LINUX)
640 // On Linux, we need to add some extra file descriptors for crash handling and
641 // the sandbox.
642 const int crash_signal_fd =
643 Singleton<RendererCrashHandlerHostLinux>()->GetDeathSignalSocket();
644 if (crash_signal_fd >= 0) {
645 fds_to_map.push_back(std::make_pair(crash_signal_fd,
646 kCrashDumpSignal + 3));
647 }
648 const int sandbox_fd =
649 Singleton<RenderSandboxHostLinux>()->GetRendererSocket();
650 fds_to_map.push_back(std::make_pair(sandbox_fd, kSandboxIPCChannel + 3));
651 #endif // defined(OS_LINUX)
652
653 // Actually launch the app.
654 zygote_child_ = false;
655 base::ProcessHandle process_handle;
656 if (!base::LaunchApp(cmd_line->argv(), fds_to_map, false, &process_handle))
657 return 0;
658 return process_handle;
659 }
660
661 #endif // defined(OS_POSIX)
662
663 base::ProcessHandle BrowserRenderProcessHost::GetHandle() { 568 base::ProcessHandle BrowserRenderProcessHost::GetHandle() {
664 if (run_renderer_in_process()) 569 // child_process_ is null either because we're in single process mode, we have
570 // done fast termination, or the process has crashed.
571 if (run_renderer_in_process() || !child_process_.get())
665 return base::Process::Current().handle(); 572 return base::Process::Current().handle();
666 573
667 return process_.handle(); 574 if (child_process_->IsStarting()) {
575 NOTREACHED() << "BrowserRenderProcessHost::GetHandle() called early!";
576 return base::kNullProcessHandle;
577 }
578
579 return child_process_->GetHandle();
668 } 580 }
669 581
670 void BrowserRenderProcessHost::InitVisitedLinks() { 582 void BrowserRenderProcessHost::InitVisitedLinks() {
671 VisitedLinkMaster* visitedlink_master = profile()->GetVisitedLinkMaster(); 583 VisitedLinkMaster* visitedlink_master = profile()->GetVisitedLinkMaster();
672 if (!visitedlink_master) { 584 if (!visitedlink_master)
673 return; 585 return;
674 }
675 586
676 base::SharedMemoryHandle handle_for_process; 587 SendVisitedLinkTable(visitedlink_master->shared_memory());
677 bool r = visitedlink_master->ShareToProcess(GetHandle(), &handle_for_process);
678 DCHECK(r);
679
680 if (base::SharedMemory::IsHandleValid(handle_for_process)) {
681 Send(new ViewMsg_VisitedLink_NewTable(handle_for_process));
682 }
683 } 588 }
684 589
685 void BrowserRenderProcessHost::InitUserScripts() { 590 void BrowserRenderProcessHost::InitUserScripts() {
686 UserScriptMaster* user_script_master = profile()->GetUserScriptMaster(); 591 UserScriptMaster* user_script_master = profile()->GetUserScriptMaster();
687 DCHECK(user_script_master); 592 DCHECK(user_script_master);
688 593
689 if (!user_script_master->ScriptsReady()) { 594 if (!user_script_master->ScriptsReady()) {
690 // No scripts ready. :( 595 // No scripts ready. :(
691 return; 596 return;
692 } 597 }
693 598
694 // Update the renderer process with the current scripts. 599 // Update the renderer process with the current scripts.
695 SendUserScriptsUpdate(user_script_master->GetSharedMemory()); 600 SendUserScriptsUpdate(user_script_master->GetSharedMemory());
696 } 601 }
697 602
698 void BrowserRenderProcessHost::InitExtensions() { 603 void BrowserRenderProcessHost::InitExtensions() {
699 // TODO(aa): Should only bother sending these function names if this is an 604 // TODO(aa): Should only bother sending these function names if this is an
700 // extension process. 605 // extension process.
701 std::vector<std::string> function_names; 606 std::vector<std::string> function_names;
702 ExtensionFunctionDispatcher::GetAllFunctionNames(&function_names); 607 ExtensionFunctionDispatcher::GetAllFunctionNames(&function_names);
703 Send(new ViewMsg_Extension_SetFunctionNames(function_names)); 608 Send(new ViewMsg_Extension_SetFunctionNames(function_names));
704 } 609 }
705 610
706 void BrowserRenderProcessHost::SendUserScriptsUpdate( 611 void BrowserRenderProcessHost::SendUserScriptsUpdate(
707 base::SharedMemory *shared_memory) { 612 base::SharedMemory *shared_memory) {
613 // Process is being started asynchronously. We'll end up calling
614 // InitUserScripts when it's created which will call this again.
615 if (child_process_.get() && child_process_->IsStarting())
616 return;
617
708 base::SharedMemoryHandle handle_for_process; 618 base::SharedMemoryHandle handle_for_process;
709 if (!shared_memory->ShareToProcess(GetHandle(), &handle_for_process)) { 619 if (!shared_memory->ShareToProcess(GetHandle(), &handle_for_process)) {
710 // This can legitimately fail if the renderer asserts at startup. 620 // This can legitimately fail if the renderer asserts at startup.
711 return; 621 return;
712 } 622 }
713 623
714 if (base::SharedMemory::IsHandleValid(handle_for_process)) { 624 if (base::SharedMemory::IsHandleValid(handle_for_process)) {
715 Send(new ViewMsg_UserScripts_UpdatedScripts(handle_for_process)); 625 Send(new ViewMsg_UserScripts_UpdatedScripts(handle_for_process));
716 } 626 }
717 } 627 }
718 628
719 bool BrowserRenderProcessHost::FastShutdownIfPossible() { 629 bool BrowserRenderProcessHost::FastShutdownIfPossible() {
720 if (!process_.handle())
721 return false; // Render process is probably crashed.
722 if (run_renderer_in_process()) 630 if (run_renderer_in_process())
723 return false; // Single process mode can't do fast shutdown. 631 return false; // Single process mode can't do fast shutdown.
724 632
633 if (!child_process_.get() || child_process_->IsStarting() || !GetHandle())
634 return false; // Render process hasn't started or is probably crashed.
635
725 // Test if there's an unload listener. 636 // Test if there's an unload listener.
726 // NOTE: It's possible that an onunload listener may be installed 637 // NOTE: It's possible that an onunload listener may be installed
727 // while we're shutting down, so there's a small race here. Given that 638 // while we're shutting down, so there's a small race here. Given that
728 // the window is small, it's unlikely that the web page has much 639 // the window is small, it's unlikely that the web page has much
729 // state that will be lost by not calling its unload handlers properly. 640 // state that will be lost by not calling its unload handlers properly.
730 if (!sudden_termination_allowed()) 641 if (!sudden_termination_allowed())
731 return false; 642 return false;
732 643
733 // Check for any external tab containers, since they may still be running even 644 // Check for any external tab containers, since they may still be running even
734 // though this window closed. 645 // though this window closed.
735 listeners_iterator iter(ListenersIterator()); 646 listeners_iterator iter(ListenersIterator());
736 while (!iter.IsAtEnd()) { 647 while (!iter.IsAtEnd()) {
737 // NOTE: This is a bit dangerous. We know that for now, listeners are 648 // NOTE: This is a bit dangerous. We know that for now, listeners are
738 // always RenderWidgetHosts. But in theory, they don't have to be. 649 // always RenderWidgetHosts. But in theory, they don't have to be.
739 const RenderWidgetHost* widget = 650 const RenderWidgetHost* widget =
740 static_cast<const RenderWidgetHost*>(iter.GetCurrentValue()); 651 static_cast<const RenderWidgetHost*>(iter.GetCurrentValue());
741 DCHECK(widget); 652 DCHECK(widget);
742 if (widget && widget->IsRenderView()) { 653 if (widget && widget->IsRenderView()) {
743 const RenderViewHost* rvh = static_cast<const RenderViewHost*>(widget); 654 const RenderViewHost* rvh = static_cast<const RenderViewHost*>(widget);
744 if (rvh->delegate()->IsExternalTabContainer()) 655 if (rvh->delegate()->IsExternalTabContainer())
745 return false; 656 return false;
746 } 657 }
747 658
748 iter.Advance(); 659 iter.Advance();
749 } 660 }
750 661
751 // Otherwise, we're allowed to just terminate the process. Using exit code 0 662 child_process_.reset();
752 // means that UMA won't treat this as a renderer crash.
753 process_.Terminate(ResultCodes::NORMAL_EXIT);
754 // On POSIX, we must additionally reap the child.
755 #if defined(OS_POSIX)
756 if (zygote_child_) {
757 #if defined(OS_LINUX)
758 // If the renderer was created via a zygote, we have to proxy the reaping
759 // through the zygote process.
760 Singleton<ZygoteHost>()->EnsureProcessTerminated(process_.handle());
761 #endif // defined(OS_LINUX)
762 } else {
763 ProcessWatcher::EnsureProcessGetsReaped(process_.handle());
764 }
765 #endif // defined(OS_POSIX)
766 process_.Close();
767
768 fast_shutdown_started_ = true; 663 fast_shutdown_started_ = true;
769 return true; 664 return true;
770 } 665 }
771 666
772 bool BrowserRenderProcessHost::SendWithTimeout(IPC::Message* msg, 667 bool BrowserRenderProcessHost::SendWithTimeout(IPC::Message* msg,
773 int timeout_ms) { 668 int timeout_ms) {
774 if (!channel_.get()) { 669 if (!channel_.get()) {
775 delete msg; 670 delete msg;
776 return false; 671 return false;
777 } 672 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 delete smallest_iterator->second; 719 delete smallest_iterator->second;
825 cached_dibs_.erase(smallest_iterator); 720 cached_dibs_.erase(smallest_iterator);
826 } 721 }
827 722
828 cached_dibs_[dib_id] = dib; 723 cached_dibs_[dib_id] = dib;
829 cached_dibs_cleaner_.Reset(); 724 cached_dibs_cleaner_.Reset();
830 return dib; 725 return dib;
831 } 726 }
832 727
833 void BrowserRenderProcessHost::ClearTransportDIBCache() { 728 void BrowserRenderProcessHost::ClearTransportDIBCache() {
834 for (std::map<TransportDIB::Id, TransportDIB*>::iterator 729 STLDeleteContainerPairSecondPointers(
835 i = cached_dibs_.begin(); i != cached_dibs_.end(); ++i) { 730 cached_dibs_.begin(), cached_dibs_.end());
836 delete i->second;
837 }
838
839 cached_dibs_.clear(); 731 cached_dibs_.clear();
840 } 732 }
841 733
842 bool BrowserRenderProcessHost::Send(IPC::Message* msg) { 734 bool BrowserRenderProcessHost::Send(IPC::Message* msg) {
843 if (!channel_.get()) { 735 if (!channel_.get()) {
844 delete msg; 736 delete msg;
845 return false; 737 return false;
846 } 738 }
739
740 if (child_process_.get() && child_process_->IsStarting()) {
741 queued_messages_.push(msg);
742 return true;
743 }
744
847 return channel_->Send(msg); 745 return channel_->Send(msg);
848 } 746 }
849 747
850 void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) { 748 void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) {
851 mark_child_process_activity_time(); 749 mark_child_process_activity_time();
852 if (msg.routing_id() == MSG_ROUTING_CONTROL) { 750 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
853 // dispatch control messages 751 // dispatch control messages
854 bool msg_is_ok = true; 752 bool msg_is_ok = true;
855 IPC_BEGIN_MESSAGE_MAP_EX(BrowserRenderProcessHost, msg, msg_is_ok) 753 IPC_BEGIN_MESSAGE_MAP_EX(BrowserRenderProcessHost, msg, msg_is_ok)
856 IPC_MESSAGE_HANDLER(ViewHostMsg_PageContents, OnPageContents) 754 IPC_MESSAGE_HANDLER(ViewHostMsg_PageContents, OnPageContents)
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg); 786 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
889 reply->set_reply_error(); 787 reply->set_reply_error();
890 Send(reply); 788 Send(reply);
891 } 789 }
892 return; 790 return;
893 } 791 }
894 listener->OnMessageReceived(msg); 792 listener->OnMessageReceived(msg);
895 } 793 }
896 794
897 void BrowserRenderProcessHost::OnChannelConnected(int32 peer_pid) { 795 void BrowserRenderProcessHost::OnChannelConnected(int32 peer_pid) {
898 // process_ is not NULL if we created the renderer process
899 if (!process_.handle()) {
900 if (fast_shutdown_started_) {
901 // We terminated the process, but the ChannelConnected task was still
902 // in the queue. We can safely ignore it.
903 return;
904 } else if (base::GetCurrentProcId() == peer_pid) {
905 // We are in single-process mode. In theory we should have access to
906 // ourself but it may happen that we don't.
907 process_.set_handle(base::GetCurrentProcessHandle());
908 } else {
909 #if defined(OS_WIN)
910 // Request MAXIMUM_ALLOWED to match the access a handle
911 // returned by CreateProcess() has to the process object.
912 process_.set_handle(OpenProcess(MAXIMUM_ALLOWED, FALSE, peer_pid));
913 #else
914 NOTREACHED();
915 #endif
916 DCHECK(process_.handle());
917 }
918 } else {
919 // Need to verify that the peer_pid is actually the process we know, if
920 // it is not, we need to panic now. See bug 1002150.
921 if (peer_pid != process_.pid()) {
922 // This check is invalid on Linux for two reasons:
923 // a) If we are running the renderer in a wrapper (with
924 // --renderer-cmd-prefix) then the we'll see the PID of the wrapper
925 // process, not the renderer itself.
926 // b) If we are using the SUID sandbox with CLONE_NEWPID, then the
927 // renderer will be in a new PID namespace and will believe that
928 // it's PID is 2 or 3.
929 // Additionally, this check isn't a security problem on Linux since we
930 // don't use the PID as reported by the renderer.
931 #if !defined(OS_LINUX)
932 CHECK(peer_pid == process_.pid()) << peer_pid << " " << process_.pid();
933 #endif
934 }
935 mark_child_process_activity_time();
936 }
937
938 #if defined(IPC_MESSAGE_LOG_ENABLED) 796 #if defined(IPC_MESSAGE_LOG_ENABLED)
939 bool enabled = IPC::Logging::current()->Enabled(); 797 Send(new ViewMsg_SetIPCLoggingEnabled(IPC::Logging::current()->Enabled()));
940 Send(new ViewMsg_SetIPCLoggingEnabled(enabled));
941 #endif 798 #endif
942 } 799 }
943 800
944 // Static. This function can be called from any thread. 801 // Static. This function can be called from any thread.
945 void BrowserRenderProcessHost::BadMessageTerminateProcess( 802 void BrowserRenderProcessHost::BadMessageTerminateProcess(
946 uint16 msg_type, base::ProcessHandle process) { 803 uint16 msg_type, base::ProcessHandle process) {
947 LOG(ERROR) << "bad message " << msg_type << " terminating renderer."; 804 LOG(ERROR) << "bad message " << msg_type << " terminating renderer.";
948 if (BrowserRenderProcessHost::run_renderer_in_process()) { 805 if (run_renderer_in_process()) {
949 // In single process mode it is better if we don't suicide but just crash. 806 // In single process mode it is better if we don't suicide but just crash.
950 CHECK(false); 807 CHECK(false);
951 } 808 }
952 NOTREACHED(); 809 NOTREACHED();
953 base::KillProcess(process, ResultCodes::KILLED_BAD_MESSAGE, false); 810 base::KillProcess(process, ResultCodes::KILLED_BAD_MESSAGE, false);
954 } 811 }
955 812
956 void BrowserRenderProcessHost::OnChannelError() { 813 void BrowserRenderProcessHost::OnChannelError() {
957 // Our child process has died. If we didn't expect it, it's a crash. 814 // Our child process has died. If we didn't expect it, it's a crash.
958 // In any case, we need to let everyone know it's gone. 815 // In any case, we need to let everyone know it's gone.
959 // The OnChannelError notification can fire multiple times due to nested sync 816 // The OnChannelError notification can fire multiple times due to nested sync
960 // calls to a renderer. If we don't have a valid channel here it means we 817 // calls to a renderer. If we don't have a valid channel here it means we
961 // already handled the error. 818 // already handled the error.
962 if (!channel_.get()) 819 if (!channel_.get())
963 return; 820 return;
964 821
965 bool child_exited; 822 // NULL in single process mode or if fast termination happened.
966 bool did_crash; 823 bool did_crash =
967 if (!process_.handle()) { 824 child_process_.get() ? child_process_->DidProcessCrash() : false;
968 // The process has been terminated (likely FastShutdownIfPossible).
969 did_crash = false;
970 child_exited = true;
971 } else if (zygote_child_) {
972 #if defined(OS_LINUX)
973 did_crash = Singleton<ZygoteHost>()->DidProcessCrash(
974 process_.handle(), &child_exited);
975 #else
976 NOTREACHED();
977 did_crash = true;
978 #endif
979 } else {
980 did_crash = base::DidProcessCrash(&child_exited, process_.handle());
981 }
982 825
983 NotificationService::current()->Notify( 826 NotificationService::current()->Notify(
984 NotificationType::RENDERER_PROCESS_CLOSED, 827 NotificationType::RENDERER_PROCESS_CLOSED,
985 Source<RenderProcessHost>(this), 828 Source<RenderProcessHost>(this),
986 Details<bool>(&did_crash)); 829 Details<bool>(&did_crash));
987 830
988 // POSIX: If the process crashed, then the kernel closed the socket for it
989 // and so the child has already died by the time we get here. Since
990 // DidProcessCrash called waitpid with WNOHANG, it'll reap the process.
991 // However, if DidProcessCrash didn't reap the child, we'll need to in
992 // ~BrowserRenderProcessHost via ProcessWatcher. So we can't close the handle
993 // here.
994 //
995 // This is moot on Windows where |child_exited| will always be true.
996 if (child_exited)
997 process_.Close();
998
999 WebCacheManager::GetInstance()->Remove(id()); 831 WebCacheManager::GetInstance()->Remove(id());
1000 832 child_process_.reset();
1001 channel_.reset(); 833 channel_.reset();
1002 834
1003 IDMap<IPC::Channel::Listener>::iterator iter(&listeners_); 835 IDMap<IPC::Channel::Listener>::iterator iter(&listeners_);
1004 while (!iter.IsAtEnd()) { 836 while (!iter.IsAtEnd()) {
1005 iter.GetCurrentValue()->OnMessageReceived( 837 iter.GetCurrentValue()->OnMessageReceived(
1006 ViewHostMsg_RenderViewGone(iter.GetCurrentKey())); 838 ViewHostMsg_RenderViewGone(iter.GetCurrentKey()));
1007 iter.Advance(); 839 iter.Advance();
1008 } 840 }
1009 841
1010 ClearTransportDIBCache(); 842 ClearTransportDIBCache();
(...skipping 17 matching lines...) Expand all
1028 void BrowserRenderProcessHost::OnUpdatedCacheStats( 860 void BrowserRenderProcessHost::OnUpdatedCacheStats(
1029 const WebCache::UsageStats& stats) { 861 const WebCache::UsageStats& stats) {
1030 WebCacheManager::GetInstance()->ObserveStats(id(), stats); 862 WebCacheManager::GetInstance()->ObserveStats(id(), stats);
1031 } 863 }
1032 864
1033 void BrowserRenderProcessHost::SuddenTerminationChanged(bool enabled) { 865 void BrowserRenderProcessHost::SuddenTerminationChanged(bool enabled) {
1034 set_sudden_termination_allowed(enabled); 866 set_sudden_termination_allowed(enabled);
1035 } 867 }
1036 868
1037 void BrowserRenderProcessHost::SetBackgrounded(bool backgrounded) { 869 void BrowserRenderProcessHost::SetBackgrounded(bool backgrounded) {
1038 // If the process_ is NULL, the process hasn't been created yet.
1039 if (process_.handle()) {
1040 bool should_set_backgrounded = true;
1041
1042 #if defined(OS_WIN)
1043 // The cbstext.dll loads as a global GetMessage hook in the browser process
1044 // and intercepts/unintercepts the kernel32 API SetPriorityClass in a
1045 // background thread. If the UI thread invokes this API just when it is
1046 // intercepted the stack is messed up on return from the interceptor
1047 // which causes random crashes in the browser process. Our hack for now
1048 // is to not invoke the SetPriorityClass API if the dll is loaded.
1049 should_set_backgrounded = (GetModuleHandle(L"cbstext.dll") == NULL);
1050 #endif // OS_WIN
1051
1052 if (should_set_backgrounded) {
1053 process_.SetProcessBackgrounded(backgrounded);
1054 }
1055 }
1056
1057 // Note: we always set the backgrounded_ value. If the process is NULL 870 // Note: we always set the backgrounded_ value. If the process is NULL
1058 // (and hence hasn't been created yet), we will set the process priority 871 // (and hence hasn't been created yet), we will set the process priority
1059 // later when we create the process. 872 // later when we create the process.
1060 backgrounded_ = backgrounded; 873 backgrounded_ = backgrounded;
874 if (!child_process_.get() || child_process_->IsStarting())
875 return;
876
877 #if defined(OS_WIN)
878 // The cbstext.dll loads as a global GetMessage hook in the browser process
879 // and intercepts/unintercepts the kernel32 API SetPriorityClass in a
880 // background thread. If the UI thread invokes this API just when it is
881 // intercepted the stack is messed up on return from the interceptor
882 // which causes random crashes in the browser process. Our hack for now
883 // is to not invoke the SetPriorityClass API if the dll is loaded.
884 if (GetModuleHandle(L"cbstext.dll"))
885 return;
886 #endif // OS_WIN
887
888 child_process_->SetProcessBackgrounded(backgrounded);
1061 } 889 }
1062 890
1063 // NotificationObserver implementation.
1064 void BrowserRenderProcessHost::Observe(NotificationType type, 891 void BrowserRenderProcessHost::Observe(NotificationType type,
1065 const NotificationSource& source, 892 const NotificationSource& source,
1066 const NotificationDetails& details) { 893 const NotificationDetails& details) {
1067 switch (type.value) { 894 switch (type.value) {
1068 case NotificationType::USER_SCRIPTS_UPDATED: { 895 case NotificationType::USER_SCRIPTS_UPDATED: {
1069 base::SharedMemory* shared_memory = 896 base::SharedMemory* shared_memory =
1070 Details<base::SharedMemory>(details).ptr(); 897 Details<base::SharedMemory>(details).ptr();
1071 if (shared_memory) { 898 if (shared_memory) {
1072 SendUserScriptsUpdate(shared_memory); 899 SendUserScriptsUpdate(shared_memory);
1073 } 900 }
(...skipping 22 matching lines...) Expand all
1096 // Fall through. 923 // Fall through.
1097 } 924 }
1098 #endif 925 #endif
1099 default: { 926 default: {
1100 NOTREACHED(); 927 NOTREACHED();
1101 break; 928 break;
1102 } 929 }
1103 } 930 }
1104 } 931 }
1105 932
933 void BrowserRenderProcessHost::OnProcessLaunched() {
934 // Now that the process is created, set its backgrounding accordingly.
935 SetBackgrounded(backgrounded_);
936
937 InitVisitedLinks();
938 InitUserScripts();
939 InitExtensions();
940 #if defined(SPELLCHECKER_IN_RENDERER)
941 // We don't want to initialize the spellchecker unless SpellCheckHost has been
942 // created. In InitSpellChecker(), we know if GetSpellCheckHost() is NULL
943 // then the spellchecker has been turned off, but here, we don't know if
944 // it's been turned off or just not loaded yet.
945 if (profile()->GetSpellCheckHost())
946 InitSpellChecker();
947 #endif
948
949 if (max_page_id_ != -1)
950 Send(new ViewMsg_SetNextPageID(max_page_id_ + 1));
951
952 while (!queued_messages_.empty()) {
953 Send(queued_messages_.front());
954 queued_messages_.pop();
955 }
956
957 NotificationService::current()->Notify(
958 NotificationType::RENDERER_PROCESS_CREATED,
959 Source<RenderProcessHost>(this), NotificationService::NoDetails());
960 }
961
1106 void BrowserRenderProcessHost::OnExtensionAddListener( 962 void BrowserRenderProcessHost::OnExtensionAddListener(
1107 const std::string& event_name) { 963 const std::string& event_name) {
1108 if (profile()->GetExtensionMessageService()) { 964 if (profile()->GetExtensionMessageService()) {
1109 profile()->GetExtensionMessageService()->AddEventListener( 965 profile()->GetExtensionMessageService()->AddEventListener(
1110 event_name, id()); 966 event_name, id());
1111 } 967 }
1112 } 968 }
1113 969
1114 void BrowserRenderProcessHost::OnExtensionRemoveListener( 970 void BrowserRenderProcessHost::OnExtensionRemoveListener(
1115 const std::string& event_name) { 971 const std::string& event_name) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 std::vector<std::string>(), 1014 std::vector<std::string>(),
1159 std::string(), 1015 std::string(),
1160 false)); 1016 false));
1161 } 1017 }
1162 } 1018 }
1163 1019
1164 void BrowserRenderProcessHost::EnableAutoSpellCorrect(bool enable) { 1020 void BrowserRenderProcessHost::EnableAutoSpellCorrect(bool enable) {
1165 Send(new ViewMsg_SpellChecker_EnableAutoSpellCorrect(enable)); 1021 Send(new ViewMsg_SpellChecker_EnableAutoSpellCorrect(enable));
1166 } 1022 }
1167 #endif 1023 #endif
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/browser_render_process_host.h ('k') | chrome/browser/renderer_host/mock_render_process_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698