| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // 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 | 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/render_process_host.h" | 8 #include "chrome/browser/render_process_host.h" |
| 9 | 9 |
| 10 #include <windows.h> | 10 #include <windows.h> |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 CloseHandle(target.hThread); | 415 CloseHandle(target.hThread); |
| 416 process_.set_handle(target.hProcess); | 416 process_.set_handle(target.hProcess); |
| 417 | 417 |
| 418 // Help the process a little. It can't start the debugger by itself if | 418 // Help the process a little. It can't start the debugger by itself if |
| 419 // the process is in a sandbox. | 419 // the process is in a sandbox. |
| 420 if (child_needs_help) | 420 if (child_needs_help) |
| 421 DebugUtil::SpawnDebuggerOnProcess(target.dwProcessId); | 421 DebugUtil::SpawnDebuggerOnProcess(target.dwProcessId); |
| 422 } else { | 422 } else { |
| 423 // spawn child process | 423 // spawn child process |
| 424 HANDLE process; | 424 HANDLE process; |
| 425 if (!process_util::LaunchApp(cmd_line, false, false, &process)) | 425 if (!base::LaunchApp(cmd_line, false, false, &process)) |
| 426 return false; | 426 return false; |
| 427 process_.set_handle(process); | 427 process_.set_handle(process); |
| 428 } | 428 } |
| 429 | 429 |
| 430 watcher_.StartWatching(process_.handle(), this); | 430 watcher_.StartWatching(process_.handle(), this); |
| 431 } | 431 } |
| 432 } | 432 } |
| 433 | 433 |
| 434 // Now that the process is created, set it's backgrounding accordingly. | 434 // Now that the process is created, set it's backgrounding accordingly. |
| 435 SetBackgrounded(backgrounded_); | 435 SetBackgrounded(backgrounded_); |
| 436 | 436 |
| 437 InitVisitedLinks(); | 437 InitVisitedLinks(); |
| 438 InitGreasemonkeyScripts(); | 438 InitGreasemonkeyScripts(); |
| 439 | 439 |
| 440 if (max_page_id_ != -1) | 440 if (max_page_id_ != -1) |
| 441 channel_->Send(new ViewMsg_SetNextPageID(max_page_id_ + 1)); | 441 channel_->Send(new ViewMsg_SetNextPageID(max_page_id_ + 1)); |
| 442 | 442 |
| 443 return true; | 443 return true; |
| 444 } | 444 } |
| 445 | 445 |
| 446 HANDLE RenderProcessHost::GetRendererProcessHandle() { | 446 base::ProcessHandle RenderProcessHost::GetRendererProcessHandle() { |
| 447 HANDLE result = process_.handle(); | 447 if (run_renderer_in_process_) |
| 448 if (!result) { | 448 return base::Process::Current().handle(); |
| 449 // Renderer process can be null if it's started with the --single-process | 449 return process_.handle(); |
| 450 // flag. | |
| 451 result = GetCurrentProcess(); | |
| 452 } | |
| 453 return result; | |
| 454 } | 450 } |
| 455 | 451 |
| 456 void RenderProcessHost::InitVisitedLinks() { | 452 void RenderProcessHost::InitVisitedLinks() { |
| 457 VisitedLinkMaster* visitedlink_master = profile_->GetVisitedLinkMaster(); | 453 VisitedLinkMaster* visitedlink_master = profile_->GetVisitedLinkMaster(); |
| 458 if (!visitedlink_master) { | 454 if (!visitedlink_master) { |
| 459 return; | 455 return; |
| 460 } | 456 } |
| 461 | 457 |
| 462 SharedMemoryHandle handle_for_process = NULL; | 458 base::SharedMemoryHandle handle_for_process = NULL; |
| 463 visitedlink_master->ShareToProcess(GetRendererProcessHandle(), | 459 visitedlink_master->ShareToProcess(GetRendererProcessHandle(), |
| 464 &handle_for_process); | 460 &handle_for_process); |
| 465 DCHECK(handle_for_process); | 461 DCHECK(handle_for_process); |
| 466 if (handle_for_process) { | 462 if (handle_for_process) { |
| 467 channel_->Send(new ViewMsg_VisitedLink_NewTable(handle_for_process)); | 463 channel_->Send(new ViewMsg_VisitedLink_NewTable(handle_for_process)); |
| 468 } | 464 } |
| 469 } | 465 } |
| 470 | 466 |
| 471 void RenderProcessHost::InitGreasemonkeyScripts() { | 467 void RenderProcessHost::InitGreasemonkeyScripts() { |
| 472 CommandLine command_line; | 468 CommandLine command_line; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 488 if (!greasemonkey_master->ScriptsReady()) { | 484 if (!greasemonkey_master->ScriptsReady()) { |
| 489 // No scripts ready. :( | 485 // No scripts ready. :( |
| 490 return; | 486 return; |
| 491 } | 487 } |
| 492 | 488 |
| 493 // Update the renderer process with the current scripts. | 489 // Update the renderer process with the current scripts. |
| 494 SendGreasemonkeyScriptsUpdate(greasemonkey_master->GetSharedMemory()); | 490 SendGreasemonkeyScriptsUpdate(greasemonkey_master->GetSharedMemory()); |
| 495 } | 491 } |
| 496 | 492 |
| 497 void RenderProcessHost::SendGreasemonkeyScriptsUpdate( | 493 void RenderProcessHost::SendGreasemonkeyScriptsUpdate( |
| 498 SharedMemory *shared_memory) { | 494 base::SharedMemory *shared_memory) { |
| 499 SharedMemoryHandle handle_for_process = NULL; | 495 base::SharedMemoryHandle handle_for_process = NULL; |
| 500 shared_memory->ShareToProcess(GetRendererProcessHandle(), | 496 shared_memory->ShareToProcess(GetRendererProcessHandle(), |
| 501 &handle_for_process); | 497 &handle_for_process); |
| 502 DCHECK(handle_for_process); | 498 DCHECK(handle_for_process); |
| 503 if (handle_for_process) { | 499 if (handle_for_process) { |
| 504 channel_->Send(new ViewMsg_Greasemonkey_NewScripts(handle_for_process)); | 500 channel_->Send(new ViewMsg_Greasemonkey_NewScripts(handle_for_process)); |
| 505 } | 501 } |
| 506 } | 502 } |
| 507 | 503 |
| 508 void RenderProcessHost::Attach(IPC::Channel::Listener* listener, | 504 void RenderProcessHost::Attach(IPC::Channel::Listener* listener, |
| 509 int routing_id) { | 505 int routing_id) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 529 Unregister(); | 525 Unregister(); |
| 530 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 526 MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 531 } | 527 } |
| 532 } | 528 } |
| 533 | 529 |
| 534 void RenderProcessHost::ReportExpectingClose(int32 listener_id) { | 530 void RenderProcessHost::ReportExpectingClose(int32 listener_id) { |
| 535 listeners_expecting_close_.insert(listener_id); | 531 listeners_expecting_close_.insert(listener_id); |
| 536 } | 532 } |
| 537 | 533 |
| 538 bool RenderProcessHost::FastShutdownIfPossible() { | 534 bool RenderProcessHost::FastShutdownIfPossible() { |
| 539 HANDLE proc = process().handle(); | 535 if (!process_.handle()) |
| 540 if (!proc) | 536 return false; // Render process is probably crashed. |
| 541 return false; | |
| 542 // If we're in single process mode, do nothing. | |
| 543 if (RenderProcessHost::run_renderer_in_process()) | 537 if (RenderProcessHost::run_renderer_in_process()) |
| 544 return false; | 538 return false; // Since process mode can't do fast shutdown. |
| 545 | 539 |
| 546 // Test if there's an unload listener | 540 // Test if there's an unload listener |
| 547 RenderProcessHost::listeners_iterator iter; | 541 RenderProcessHost::listeners_iterator iter; |
| 548 // NOTE: This is a bit dangerous. We know that for now, listeners are | 542 // NOTE: This is a bit dangerous. We know that for now, listeners are |
| 549 // always RenderWidgetHosts. But in theory, they don't have to be. | 543 // always RenderWidgetHosts. But in theory, they don't have to be. |
| 550 for (iter = listeners_begin(); iter != listeners_end(); ++iter) { | 544 for (iter = listeners_begin(); iter != listeners_end(); ++iter) { |
| 551 RenderWidgetHost* widget = static_cast<RenderWidgetHost*>(iter->second); | 545 RenderWidgetHost* widget = static_cast<RenderWidgetHost*>(iter->second); |
| 552 DCHECK(widget); | 546 DCHECK(widget); |
| 553 if (!widget || !widget->IsRenderView()) | 547 if (!widget || !widget->IsRenderView()) |
| 554 continue; | 548 continue; |
| 555 RenderViewHost* rvh = static_cast<RenderViewHost*>(widget); | 549 RenderViewHost* rvh = static_cast<RenderViewHost*>(widget); |
| 556 if (rvh->HasUnloadListener()) { | 550 if (rvh->HasUnloadListener()) { |
| 557 // NOTE: It's possible that an onunload listener may be installed | 551 // NOTE: It's possible that an onunload listener may be installed |
| 558 // while we're shutting down, so there's a small race here. Given that | 552 // while we're shutting down, so there's a small race here. Given that |
| 559 // the window is small, it's unlikely that the web page has much | 553 // the window is small, it's unlikely that the web page has much |
| 560 // state that will be lost by not calling its unload handlers properly. | 554 // state that will be lost by not calling its unload handlers properly. |
| 561 return false; | 555 return false; |
| 562 } | 556 } |
| 563 } | 557 } |
| 564 // Otherwise, call TerminateProcess. Using exit code 0 means that UMA won't | 558 |
| 565 // treat this as a renderer crash. | 559 // Otherwise, we're allowed to just terminate the process. Using exit code 0 |
| 566 ::TerminateProcess(proc, ResultCodes::NORMAL_EXIT); | 560 // means that UMA won't treat this as a renderer crash. |
| 561 process_.Terminate(ResultCodes::NORMAL_EXIT); |
| 567 return true; | 562 return true; |
| 568 } | 563 } |
| 569 | 564 |
| 570 // Static. This function can be called from the IO Thread or from the UI thread. | 565 // Static. This function can be called from the IO Thread or from the UI thread. |
| 571 void RenderProcessHost::BadMessageTerminateProcess(uint16 msg_type, | 566 void RenderProcessHost::BadMessageTerminateProcess(uint16 msg_type, |
| 572 HANDLE process) { | 567 HANDLE process) { |
| 573 LOG(ERROR) << "bad message " << msg_type << " terminating renderer."; | 568 LOG(ERROR) << "bad message " << msg_type << " terminating renderer."; |
| 574 if (RenderProcessHost::run_renderer_in_process()) { | 569 if (RenderProcessHost::run_renderer_in_process()) { |
| 575 // In single process mode it is better if we don't suicide but just crash. | 570 // In single process mode it is better if we don't suicide but just crash. |
| 576 CHECK(false); | 571 CHECK(false); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 CHECK(peer_pid == process_.pid()); | 639 CHECK(peer_pid == process_.pid()); |
| 645 } | 640 } |
| 646 } | 641 } |
| 647 | 642 |
| 648 // indicates the renderer process has exited | 643 // indicates the renderer process has exited |
| 649 void RenderProcessHost::OnObjectSignaled(HANDLE object) { | 644 void RenderProcessHost::OnObjectSignaled(HANDLE object) { |
| 650 DCHECK(process_.handle()); | 645 DCHECK(process_.handle()); |
| 651 DCHECK(channel_.get()); | 646 DCHECK(channel_.get()); |
| 652 DCHECK_EQ(object, process_.handle()); | 647 DCHECK_EQ(object, process_.handle()); |
| 653 | 648 |
| 654 bool clean_shutdown = !process_util::DidProcessCrash(object); | 649 bool clean_shutdown = !base::DidProcessCrash(object); |
| 655 | 650 |
| 656 process_.Close(); | 651 process_.Close(); |
| 657 | 652 |
| 658 channel_.reset(); | 653 channel_.reset(); |
| 659 | 654 |
| 660 if (!notified_termination_) { | 655 if (!notified_termination_) { |
| 661 // If |close_expected| is false, it means the renderer process went away | 656 // If |close_expected| is false, it means the renderer process went away |
| 662 // before the web views expected it; count it as a crash. | 657 // before the web views expected it; count it as a crash. |
| 663 NotificationService::current()->Notify(NOTIFY_RENDERER_PROCESS_TERMINATED, | 658 NotificationService::current()->Notify(NOTIFY_RENDERER_PROCESS_TERMINATED, |
| 664 Source<RenderProcessHost>(this), | 659 Source<RenderProcessHost>(this), |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 DCHECK(Source<PrefService>(source).ptr() == profile()->GetPrefs()); | 812 DCHECK(Source<PrefService>(source).ptr() == profile()->GetPrefs()); |
| 818 if (*pref_name_in == prefs::kBlockPopups) { | 813 if (*pref_name_in == prefs::kBlockPopups) { |
| 819 widget_helper_->set_block_popups( | 814 widget_helper_->set_block_popups( |
| 820 profile()->GetPrefs()->GetBoolean(prefs::kBlockPopups)); | 815 profile()->GetPrefs()->GetBoolean(prefs::kBlockPopups)); |
| 821 } else { | 816 } else { |
| 822 NOTREACHED() << "unexpected pref change notification" << *pref_name_in; | 817 NOTREACHED() << "unexpected pref change notification" << *pref_name_in; |
| 823 } | 818 } |
| 824 break; | 819 break; |
| 825 } | 820 } |
| 826 case NOTIFY_NEW_USER_SCRIPTS: { | 821 case NOTIFY_NEW_USER_SCRIPTS: { |
| 827 SharedMemory* shared_memory = Details<SharedMemory>(details).ptr(); | 822 base::SharedMemory* shared_memory = |
| 823 Details<base::SharedMemory>(details).ptr(); |
| 828 DCHECK(shared_memory); | 824 DCHECK(shared_memory); |
| 829 if (shared_memory) { | 825 if (shared_memory) { |
| 830 SendGreasemonkeyScriptsUpdate(shared_memory); | 826 SendGreasemonkeyScriptsUpdate(shared_memory); |
| 831 } | 827 } |
| 832 break; | 828 break; |
| 833 } | 829 } |
| 834 default: { | 830 default: { |
| 835 NOTREACHED(); | 831 NOTREACHED(); |
| 836 break; | 832 break; |
| 837 } | 833 } |
| 838 } | 834 } |
| 839 } | 835 } |
| 840 | 836 |
| 841 // static | 837 // static |
| 842 bool RenderProcessHost::ShouldTryToUseExistingProcessHost() { | 838 bool RenderProcessHost::ShouldTryToUseExistingProcessHost() { |
| 843 unsigned int renderer_process_count = | 839 unsigned int renderer_process_count = |
| 844 static_cast<unsigned int>(all_hosts.size()); | 840 static_cast<unsigned int>(all_hosts.size()); |
| 845 | 841 |
| 846 // NOTE: Sometimes it's necessary to create more render processes than | 842 // NOTE: Sometimes it's necessary to create more render processes than |
| 847 // GetMaxRendererProcessCount(), for instance when we want to create | 843 // GetMaxRendererProcessCount(), for instance when we want to create |
| 848 // a renderer process for a profile that has no existing renderers. | 844 // a renderer process for a profile that has no existing renderers. |
| 849 // This is OK in moderation, since the GetMaxRendererProcessCount() | 845 // This is OK in moderation, since the GetMaxRendererProcessCount() |
| 850 // is conservative. | 846 // is conservative. |
| 851 | 847 |
| 852 return run_renderer_in_process() || | 848 return run_renderer_in_process() || |
| 853 (renderer_process_count >= GetMaxRendererProcessCount()); | 849 (renderer_process_count >= GetMaxRendererProcessCount()); |
| 854 } | 850 } |
| 855 | 851 |
| OLD | NEW |