| 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/renderer_host/browser_render_process_host.h" | 8 #include "chrome/browser/renderer_host/browser_render_process_host.h" |
| 9 | 9 |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 | 121 |
| 122 const wchar_t* const kDesktopName = L"ChromeRendererDesktop"; | 122 const wchar_t* const kDesktopName = L"ChromeRendererDesktop"; |
| 123 | 123 |
| 124 BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile) | 124 BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile) |
| 125 : RenderProcessHost(profile), | 125 : RenderProcessHost(profile), |
| 126 visible_widgets_(0), | 126 visible_widgets_(0), |
| 127 backgrounded_(true), | 127 backgrounded_(true), |
| 128 ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_( | 128 ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_( |
| 129 base::TimeDelta::FromSeconds(5), | 129 base::TimeDelta::FromSeconds(5), |
| 130 this, &BrowserRenderProcessHost::ClearTransportDIBCache)) { | 130 this, &BrowserRenderProcessHost::ClearTransportDIBCache)) { |
| 131 DCHECK(host_id() >= 0); // We use a negative host_id_ in destruction. | 131 widget_helper_ = new RenderWidgetHelper(); |
| 132 widget_helper_ = new RenderWidgetHelper( | |
| 133 host_id(), g_browser_process->resource_dispatcher_host()); | |
| 134 | |
| 135 CacheManagerHost::GetInstance()->Add(host_id()); | |
| 136 RendererSecurityPolicy::GetInstance()->Add(host_id()); | |
| 137 | 132 |
| 138 PrefService* prefs = profile->GetPrefs(); | 133 PrefService* prefs = profile->GetPrefs(); |
| 139 prefs->AddPrefObserver(prefs::kBlockPopups, this); | 134 prefs->AddPrefObserver(prefs::kBlockPopups, this); |
| 140 widget_helper_->set_block_popups( | 135 widget_helper_->set_block_popups( |
| 141 profile->GetPrefs()->GetBoolean(prefs::kBlockPopups)); | 136 profile->GetPrefs()->GetBoolean(prefs::kBlockPopups)); |
| 142 | 137 |
| 143 NotificationService::current()->AddObserver(this, | 138 NotificationService::current()->AddObserver(this, |
| 144 NotificationType::USER_SCRIPTS_LOADED, | 139 NotificationType::USER_SCRIPTS_LOADED, |
| 145 NotificationService::AllSources()); | 140 NotificationService::AllSources()); |
| 146 | 141 |
| 147 // Note: When we create the BrowserRenderProcessHost, it's technically | 142 // Note: When we create the BrowserRenderProcessHost, it's technically |
| 148 // backgrounded, because it has no visible listeners. But the process | 143 // backgrounded, because it has no visible listeners. But the process |
| 149 // doesn't actually exist yet, so we'll Background it later, after | 144 // doesn't actually exist yet, so we'll Background it later, after |
| 150 // creation. | 145 // creation. |
| 151 } | 146 } |
| 152 | 147 |
| 153 BrowserRenderProcessHost::~BrowserRenderProcessHost() { | 148 BrowserRenderProcessHost::~BrowserRenderProcessHost() { |
| 154 // Some tests hold BrowserRenderProcessHost in a scoped_ptr, so we must call | 149 if (pid() >= 0) { |
| 155 // Unregister here as well as in response to Release(). | 150 CacheManagerHost::GetInstance()->Remove(pid()); |
| 156 Unregister(); | 151 RendererSecurityPolicy::GetInstance()->Remove(pid()); |
| 152 } |
| 157 | 153 |
| 158 // We may have some unsent messages at this point, but that's OK. | 154 // We may have some unsent messages at this point, but that's OK. |
| 159 channel_.reset(); | 155 channel_.reset(); |
| 160 | 156 |
| 161 // Destroy the AudioRendererHost properly. | 157 // Destroy the AudioRendererHost properly. |
| 162 if (audio_renderer_host_.get()) | 158 if (audio_renderer_host_.get()) |
| 163 audio_renderer_host_->Destroy(); | 159 audio_renderer_host_->Destroy(); |
| 164 | 160 |
| 165 if (process_.handle() && !run_renderer_in_process()) { | 161 if (process_.handle() && !run_renderer_in_process()) { |
| 166 ProcessWatcher::EnsureProcessTerminated(process_.handle()); | 162 ProcessWatcher::EnsureProcessTerminated(process_.handle()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 185 | 181 |
| 186 // Construct the AudioRendererHost with the IO thread. | 182 // Construct the AudioRendererHost with the IO thread. |
| 187 audio_renderer_host_ = | 183 audio_renderer_host_ = |
| 188 new AudioRendererHost(io_thread->message_loop()); | 184 new AudioRendererHost(io_thread->message_loop()); |
| 189 | 185 |
| 190 scoped_refptr<ResourceMessageFilter> resource_message_filter = | 186 scoped_refptr<ResourceMessageFilter> resource_message_filter = |
| 191 new ResourceMessageFilter(g_browser_process->resource_dispatcher_host(), | 187 new ResourceMessageFilter(g_browser_process->resource_dispatcher_host(), |
| 192 audio_renderer_host_.get(), | 188 audio_renderer_host_.get(), |
| 193 PluginService::GetInstance(), | 189 PluginService::GetInstance(), |
| 194 g_browser_process->print_job_manager(), | 190 g_browser_process->print_job_manager(), |
| 195 host_id(), | |
| 196 profile(), | 191 profile(), |
| 197 widget_helper_, | 192 widget_helper_, |
| 198 profile()->GetSpellChecker()); | 193 profile()->GetSpellChecker()); |
| 199 | 194 |
| 200 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); | 195 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); |
| 201 | 196 |
| 202 // setup IPC channel | 197 // setup IPC channel |
| 203 const std::wstring channel_id = | 198 const std::wstring channel_id = |
| 204 ChildProcessInfo::GenerateRandomChannelID(this); | 199 ChildProcessInfo::GenerateRandomChannelID(this); |
| 205 channel_.reset( | 200 channel_.reset( |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 | 294 |
| 300 cmd_line.AppendSwitchWithValue(switches::kProcessChannelID, | 295 cmd_line.AppendSwitchWithValue(switches::kProcessChannelID, |
| 301 channel_id); | 296 channel_id); |
| 302 | 297 |
| 303 const std::wstring& profile_path = | 298 const std::wstring& profile_path = |
| 304 browser_command_line.GetSwitchValue(switches::kUserDataDir); | 299 browser_command_line.GetSwitchValue(switches::kUserDataDir); |
| 305 if (!profile_path.empty()) | 300 if (!profile_path.empty()) |
| 306 cmd_line.AppendSwitchWithValue(switches::kUserDataDir, | 301 cmd_line.AppendSwitchWithValue(switches::kUserDataDir, |
| 307 profile_path); | 302 profile_path); |
| 308 | 303 |
| 304 int process_id; |
| 309 bool run_in_process = run_renderer_in_process(); | 305 bool run_in_process = run_renderer_in_process(); |
| 310 if (run_in_process) { | 306 if (run_in_process) { |
| 311 // Crank up a thread and run the initialization there. With the way that | 307 // Crank up a thread and run the initialization there. With the way that |
| 312 // messages flow between the browser and renderer, this thread is required | 308 // messages flow between the browser and renderer, this thread is required |
| 313 // to prevent a deadlock in single-process mode. When using multiple | 309 // to prevent a deadlock in single-process mode. When using multiple |
| 314 // processes, the primordial thread in the renderer process has a message | 310 // processes, the primordial thread in the renderer process has a message |
| 315 // loop which is used for sending messages asynchronously to the io thread | 311 // loop which is used for sending messages asynchronously to the io thread |
| 316 // in the browser process. If we don't create this thread, then the | 312 // in the browser process. If we don't create this thread, then the |
| 317 // RenderThread is both responsible for rendering and also for | 313 // RenderThread is both responsible for rendering and also for |
| 318 // communicating IO. This can lead to deadlocks where the RenderThread is | 314 // communicating IO. This can lead to deadlocks where the RenderThread is |
| 319 // waiting for the IO to complete, while the browsermain is trying to pass | 315 // waiting for the IO to complete, while the browsermain is trying to pass |
| 320 // an event to the RenderThread. | 316 // an event to the RenderThread. |
| 321 in_process_renderer_.reset(new RendererMainThread(channel_id)); | 317 in_process_renderer_.reset(new RendererMainThread(channel_id)); |
| 322 | 318 |
| 323 base::Thread::Options options; | 319 base::Thread::Options options; |
| 324 options.message_loop_type = MessageLoop::TYPE_IO; | 320 options.message_loop_type = MessageLoop::TYPE_IO; |
| 325 in_process_renderer_->StartWithOptions(options); | 321 in_process_renderer_->StartWithOptions(options); |
| 322 |
| 323 // We need a "renderer pid", but we don't have one when there's no renderer |
| 324 // process. So pick a value that won't clash with other child process pids. |
| 325 // Linux has PID_MAX_LIMIT which is 2^22. Windows always uses pids that are |
| 326 // divisible by 4. So... |
| 327 static int next_pid = 4 * 1024 * 1024; |
| 328 next_pid += 3; |
| 329 process_id = next_pid; |
| 326 } else { | 330 } else { |
| 327 #if defined(OS_WIN) | 331 #if defined(OS_WIN) |
| 328 if (in_sandbox) { | 332 if (in_sandbox) { |
| 329 // spawn the child process in the sandbox | 333 // spawn the child process in the sandbox |
| 330 sandbox::BrokerServices* broker_service = | 334 sandbox::BrokerServices* broker_service = |
| 331 g_browser_process->broker_services(); | 335 g_browser_process->broker_services(); |
| 332 | 336 |
| 333 sandbox::ResultCode result; | 337 sandbox::ResultCode result; |
| 334 PROCESS_INFORMATION target = {0}; | 338 PROCESS_INFORMATION target = {0}; |
| 335 sandbox::TargetPolicy* policy = broker_service->CreatePolicy(); | 339 sandbox::TargetPolicy* policy = broker_service->CreatePolicy(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 DebugUtil::SpawnDebuggerOnProcess(target.dwProcessId); | 402 DebugUtil::SpawnDebuggerOnProcess(target.dwProcessId); |
| 399 } else | 403 } else |
| 400 #endif // OS_WIN and sandbox | 404 #endif // OS_WIN and sandbox |
| 401 { | 405 { |
| 402 // spawn child process | 406 // spawn child process |
| 403 base::ProcessHandle process = 0; | 407 base::ProcessHandle process = 0; |
| 404 if (!SpawnChild(cmd_line, channel_.get(), &process)) | 408 if (!SpawnChild(cmd_line, channel_.get(), &process)) |
| 405 return false; | 409 return false; |
| 406 process_.set_handle(process); | 410 process_.set_handle(process); |
| 407 } | 411 } |
| 412 |
| 413 process_id = process_.pid(); |
| 408 } | 414 } |
| 409 | 415 |
| 416 SetProcessID(process_id); |
| 417 resource_message_filter->Init(pid()); |
| 418 CacheManagerHost::GetInstance()->Add(pid()); |
| 419 RendererSecurityPolicy::GetInstance()->Add(pid()); |
| 420 |
| 410 // Now that the process is created, set it's backgrounding accordingly. | 421 // Now that the process is created, set it's backgrounding accordingly. |
| 411 SetBackgrounded(backgrounded_); | 422 SetBackgrounded(backgrounded_); |
| 412 | 423 |
| 413 InitVisitedLinks(); | 424 InitVisitedLinks(); |
| 414 InitUserScripts(); | 425 InitUserScripts(); |
| 415 | 426 |
| 416 if (max_page_id_ != -1) | 427 if (max_page_id_ != -1) |
| 417 channel_->Send(new ViewMsg_SetNextPageID(max_page_id_ + 1)); | 428 channel_->Send(new ViewMsg_SetNextPageID(max_page_id_ + 1)); |
| 418 | 429 |
| 419 return true; | 430 return true; |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 i != local_listeners.end(); ++i) { | 775 i != local_listeners.end(); ++i) { |
| 765 i->second->OnMessageReceived(ViewHostMsg_RenderViewGone(i->first)); | 776 i->second->OnMessageReceived(ViewHostMsg_RenderViewGone(i->first)); |
| 766 } | 777 } |
| 767 | 778 |
| 768 ClearTransportDIBCache(); | 779 ClearTransportDIBCache(); |
| 769 | 780 |
| 770 // this object is not deleted at this point and may be reused later. | 781 // this object is not deleted at this point and may be reused later. |
| 771 // TODO(darin): clean this up | 782 // TODO(darin): clean this up |
| 772 } | 783 } |
| 773 | 784 |
| 774 void BrowserRenderProcessHost::Unregister() { | |
| 775 // RenderProcessHost::Unregister will clean up the host_id_, so we must | |
| 776 // do our cleanup that uses that variable before we call it. | |
| 777 if (host_id() >= 0) { | |
| 778 CacheManagerHost::GetInstance()->Remove(host_id()); | |
| 779 RendererSecurityPolicy::GetInstance()->Remove(host_id()); | |
| 780 } | |
| 781 | |
| 782 RenderProcessHost::Unregister(); | |
| 783 } | |
| 784 | |
| 785 void BrowserRenderProcessHost::OnPageContents(const GURL& url, | 785 void BrowserRenderProcessHost::OnPageContents(const GURL& url, |
| 786 int32 page_id, | 786 int32 page_id, |
| 787 const std::wstring& contents) { | 787 const std::wstring& contents) { |
| 788 Profile* p = profile(); | 788 Profile* p = profile(); |
| 789 if (!p || p->IsOffTheRecord()) | 789 if (!p || p->IsOffTheRecord()) |
| 790 return; | 790 return; |
| 791 | 791 |
| 792 HistoryService* hs = p->GetHistoryService(Profile::IMPLICIT_ACCESS); | 792 HistoryService* hs = p->GetHistoryService(Profile::IMPLICIT_ACCESS); |
| 793 if (hs) | 793 if (hs) |
| 794 hs->SetPageContents(url, contents); | 794 hs->SetPageContents(url, contents); |
| 795 } | 795 } |
| 796 | 796 |
| 797 void BrowserRenderProcessHost::OnUpdatedCacheStats( | 797 void BrowserRenderProcessHost::OnUpdatedCacheStats( |
| 798 const CacheManager::UsageStats& stats) { | 798 const CacheManager::UsageStats& stats) { |
| 799 CacheManagerHost::GetInstance()->ObserveStats(host_id(), stats); | 799 CacheManagerHost::GetInstance()->ObserveStats(pid(), stats); |
| 800 } | 800 } |
| 801 | 801 |
| 802 void BrowserRenderProcessHost::SetBackgrounded(bool backgrounded) { | 802 void BrowserRenderProcessHost::SetBackgrounded(bool backgrounded) { |
| 803 // If the process_ is NULL, the process hasn't been created yet. | 803 // If the process_ is NULL, the process hasn't been created yet. |
| 804 if (process_.handle()) { | 804 if (process_.handle()) { |
| 805 bool should_set_backgrounded = true; | 805 bool should_set_backgrounded = true; |
| 806 | 806 |
| 807 #if defined(OS_WIN) | 807 #if defined(OS_WIN) |
| 808 // The cbstext.dll loads as a global GetMessage hook in the browser process | 808 // The cbstext.dll loads as a global GetMessage hook in the browser process |
| 809 // and intercepts/unintercepts the kernel32 API SetPriorityClass in a | 809 // and intercepts/unintercepts the kernel32 API SetPriorityClass in a |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 SendUserScriptsUpdate(shared_memory); | 866 SendUserScriptsUpdate(shared_memory); |
| 867 } | 867 } |
| 868 break; | 868 break; |
| 869 } | 869 } |
| 870 default: { | 870 default: { |
| 871 NOTREACHED(); | 871 NOTREACHED(); |
| 872 break; | 872 break; |
| 873 } | 873 } |
| 874 } | 874 } |
| 875 } | 875 } |
| OLD | NEW |