Turning WebGL and the accelerated compositor on by default (linux and windows only...
[chromium-blink-merge.git] / chrome / browser / renderer_host / browser_render_process_host.cc
blobf7a9b1788c2a20601f0ca4f24fb4372d8614d6d6
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Represents the browser side of the browser <--> renderer communication
6 // channel. There will be one RenderProcessHost per renderer process.
8 #include "chrome/browser/renderer_host/browser_render_process_host.h"
10 #include <algorithm>
11 #include <limits>
12 #include <vector>
14 #if defined(OS_POSIX)
15 #include <utility> // for pair<>
16 #endif
18 #include "app/app_switches.h"
19 #include "base/command_line.h"
20 #include "base/field_trial.h"
21 #include "base/histogram.h"
22 #include "base/logging.h"
23 #include "base/stl_util-inl.h"
24 #include "base/string_util.h"
25 #include "base/thread.h"
26 #include "chrome/browser/browser_child_process_host.h"
27 #include "chrome/browser/browser_process.h"
28 #include "chrome/browser/child_process_security_policy.h"
29 #include "chrome/browser/extensions/extension_function_dispatcher.h"
30 #include "chrome/browser/extensions/extension_message_service.h"
31 #include "chrome/browser/extensions/extensions_service.h"
32 #include "chrome/browser/extensions/user_script_master.h"
33 #include "chrome/browser/gpu_process_host.h"
34 #include "chrome/browser/history/history.h"
35 #include "chrome/browser/io_thread.h"
36 #include "chrome/browser/plugin_service.h"
37 #include "chrome/browser/profile.h"
38 #include "chrome/browser/renderer_host/audio_renderer_host.h"
39 #include "chrome/browser/renderer_host/render_view_host.h"
40 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
41 #include "chrome/browser/renderer_host/render_widget_helper.h"
42 #include "chrome/browser/renderer_host/render_widget_host.h"
43 #include "chrome/browser/renderer_host/resource_message_filter.h"
44 #include "chrome/browser/renderer_host/web_cache_manager.h"
45 #include "chrome/browser/spellcheck_host.h"
46 #include "chrome/browser/visitedlink_master.h"
47 #include "chrome/common/chrome_switches.h"
48 #include "chrome/common/child_process_info.h"
49 #include "chrome/common/gpu_messages.h"
50 #include "chrome/common/logging_chrome.h"
51 #include "chrome/common/net/url_request_context_getter.h"
52 #include "chrome/common/notification_service.h"
53 #include "chrome/common/pref_names.h"
54 #include "chrome/common/process_watcher.h"
55 #include "chrome/common/render_messages.h"
56 #include "chrome/common/render_messages_params.h"
57 #include "chrome/common/result_codes.h"
58 #include "chrome/renderer/render_process_impl.h"
59 #include "chrome/renderer/render_thread.h"
60 #include "grit/generated_resources.h"
61 #include "ipc/ipc_logging.h"
62 #include "ipc/ipc_message.h"
63 #include "ipc/ipc_platform_file.h"
64 #include "ipc/ipc_switches.h"
65 #include "media/base/media_switches.h"
66 #include "webkit/glue/plugins/plugin_switches.h"
68 #if defined(OS_WIN)
69 #include "app/win_util.h"
70 #endif
72 using WebKit::WebCache;
74 #include "third_party/skia/include/core/SkBitmap.h"
77 // This class creates the IO thread for the renderer when running in
78 // single-process mode. It's not used in multi-process mode.
79 class RendererMainThread : public base::Thread {
80 public:
81 explicit RendererMainThread(const std::string& channel_id)
82 : base::Thread("Chrome_InProcRendererThread"),
83 channel_id_(channel_id),
84 render_process_(NULL) {
87 ~RendererMainThread() {
88 Stop();
91 protected:
92 virtual void Init() {
93 #if defined(OS_WIN)
94 CoInitialize(NULL);
95 #endif
97 render_process_ = new RenderProcessImpl();
98 render_process_->set_main_thread(new RenderThread(channel_id_));
99 // It's a little lame to manually set this flag. But the single process
100 // RendererThread will receive the WM_QUIT. We don't need to assert on
101 // this thread, so just force the flag manually.
102 // If we want to avoid this, we could create the InProcRendererThread
103 // directly with _beginthreadex() rather than using the Thread class.
104 base::Thread::SetThreadWasQuitProperly(true);
107 virtual void CleanUp() {
108 delete render_process_;
110 #if defined(OS_WIN)
111 CoUninitialize();
112 #endif
115 private:
116 std::string channel_id_;
117 // Deleted in CleanUp() on the renderer thread, so don't use a smart pointer.
118 RenderProcess* render_process_;
122 // Size of the buffer after which individual link updates deemed not warranted
123 // and the overall update should be used instead.
124 static const unsigned kVisitedLinkBufferThreshold = 50;
126 // This class manages buffering and sending visited link hashes (fingerprints)
127 // to renderer based on widget visibility.
128 // As opposed to the VisitedLinkEventListener in profile.cc, which coalesces to
129 // reduce the rate of messages being sent to render processes, this class
130 // ensures that the updates occur only when explicitly requested. This is
131 // used by BrowserRenderProcessHost to only send Add/Reset link events to the
132 // renderers when their tabs are visible and the corresponding RenderViews are
133 // created.
134 class VisitedLinkUpdater {
135 public:
136 VisitedLinkUpdater() : reset_needed_(false), has_receiver_(false) {}
138 // Buffers |links| to update, but doesn't actually relay them.
139 void AddLinks(const VisitedLinkCommon::Fingerprints& links) {
140 if (reset_needed_)
141 return;
143 if (pending_.size() + links.size() > kVisitedLinkBufferThreshold) {
144 // Once the threshold is reached, there's no need to store pending visited
145 // link updates -- we opt for resetting the state for all links.
146 AddReset();
147 return;
150 pending_.insert(pending_.end(), links.begin(), links.end());
153 // Tells the updater that sending individual link updates is no longer
154 // necessary and the visited state for all links should be reset.
155 void AddReset() {
156 reset_needed_ = true;
157 pending_.clear();
160 // Sends visited link update messages: a list of links whose visited state
161 // changed or reset of visited state for all links.
162 void Update(IPC::Channel::Sender* sender) {
163 DCHECK(sender);
165 if (!has_receiver_)
166 return;
168 if (reset_needed_) {
169 sender->Send(new ViewMsg_VisitedLink_Reset());
170 reset_needed_ = false;
171 return;
174 if (pending_.size() == 0)
175 return;
177 sender->Send(new ViewMsg_VisitedLink_Add(pending_));
179 pending_.clear();
182 // Notifies the updater that it is now safe to send visited state updates.
183 void ReceiverReady(IPC::Channel::Sender* sender) {
184 has_receiver_ = true;
185 // Go ahead and send whatever we already have buffered up.
186 Update(sender);
189 private:
190 bool reset_needed_;
191 bool has_receiver_;
192 VisitedLinkCommon::Fingerprints pending_;
195 BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile)
196 : RenderProcessHost(profile),
197 visible_widgets_(0),
198 backgrounded_(true),
199 ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_(
200 base::TimeDelta::FromSeconds(5),
201 this, &BrowserRenderProcessHost::ClearTransportDIBCache)),
202 extension_process_(false) {
203 widget_helper_ = new RenderWidgetHelper();
205 registrar_.Add(this, NotificationType::USER_SCRIPTS_UPDATED,
206 Source<Profile>(profile->GetOriginalProfile()));
207 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
208 Source<Profile>(profile->GetOriginalProfile()));
209 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
210 Source<Profile>(profile->GetOriginalProfile()));
211 registrar_.Add(this, NotificationType::SPELLCHECK_HOST_REINITIALIZED,
212 NotificationService::AllSources());
213 registrar_.Add(this, NotificationType::SPELLCHECK_WORD_ADDED,
214 NotificationService::AllSources());
215 registrar_.Add(this, NotificationType::SPELLCHECK_AUTOSPELL_TOGGLED,
216 NotificationService::AllSources());
218 visited_link_updater_.reset(new VisitedLinkUpdater());
220 WebCacheManager::GetInstance()->Add(id());
221 ChildProcessSecurityPolicy::GetInstance()->Add(id());
223 // Note: When we create the BrowserRenderProcessHost, it's technically
224 // backgrounded, because it has no visible listeners. But the process
225 // doesn't actually exist yet, so we'll Background it later, after
226 // creation.
229 BrowserRenderProcessHost::~BrowserRenderProcessHost() {
230 WebCacheManager::GetInstance()->Remove(id());
231 ChildProcessSecurityPolicy::GetInstance()->Remove(id());
233 // We may have some unsent messages at this point, but that's OK.
234 channel_.reset();
235 while (!queued_messages_.empty()) {
236 delete queued_messages_.front();
237 queued_messages_.pop();
240 // Destroy the AudioRendererHost properly.
241 if (audio_renderer_host_.get())
242 audio_renderer_host_->Destroy();
244 ClearTransportDIBCache();
247 bool BrowserRenderProcessHost::Init(bool is_extensions_process) {
248 // calling Init() more than once does nothing, this makes it more convenient
249 // for the view host which may not be sure in some cases
250 if (channel_.get())
251 return true;
253 // It is possible for an extension process to be reused for non-extension
254 // content, e.g. if an extension calls window.open.
255 extension_process_ = extension_process_ || is_extensions_process;
257 // run the IPC channel on the shared IO thread.
258 base::Thread* io_thread = g_browser_process->io_thread();
260 // Construct the AudioRendererHost with the IO thread.
261 audio_renderer_host_ = new AudioRendererHost();
263 scoped_refptr<ResourceMessageFilter> resource_message_filter =
264 new ResourceMessageFilter(g_browser_process->resource_dispatcher_host(),
265 id(),
266 audio_renderer_host_.get(),
267 PluginService::GetInstance(),
268 g_browser_process->print_job_manager(),
269 profile(),
270 widget_helper_);
272 CommandLine::StringType renderer_prefix;
273 #if defined(OS_POSIX)
274 // A command prefix is something prepended to the command line of the spawned
275 // process. It is supported only on POSIX systems.
276 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
277 renderer_prefix =
278 browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
279 #endif // defined(OS_POSIX)
281 // Find the renderer before creating the channel so if this fails early we
282 // return without creating the channel.
283 FilePath renderer_path =
284 ChildProcessHost::GetChildPath(renderer_prefix.empty());
285 if (renderer_path.empty())
286 return false;
288 // Setup the IPC channel.
289 const std::string channel_id =
290 ChildProcessInfo::GenerateRandomChannelID(this);
291 channel_.reset(
292 new IPC::SyncChannel(channel_id, IPC::Channel::MODE_SERVER, this,
293 resource_message_filter,
294 io_thread->message_loop(), true,
295 g_browser_process->shutdown_event()));
296 // As a preventive mesure, we DCHECK if someone sends a synchronous message
297 // with no time-out, which in the context of the browser process we should not
298 // be doing.
299 channel_->set_sync_messages_with_no_timeout_allowed(false);
301 if (run_renderer_in_process()) {
302 // Crank up a thread and run the initialization there. With the way that
303 // messages flow between the browser and renderer, this thread is required
304 // to prevent a deadlock in single-process mode. Since the primordial
305 // thread in the renderer process runs the WebKit code and can sometimes
306 // make blocking calls to the UI thread (i.e. this thread), they need to run
307 // on separate threads.
308 in_process_renderer_.reset(new RendererMainThread(channel_id));
310 base::Thread::Options options;
311 #if !defined(TOOLKIT_USES_GTK)
312 // In-process plugins require this to be a UI message loop.
313 options.message_loop_type = MessageLoop::TYPE_UI;
314 #else
315 // We can't have multiple UI loops on GTK, so we don't support
316 // in-process plugins.
317 options.message_loop_type = MessageLoop::TYPE_DEFAULT;
318 #endif
319 in_process_renderer_->StartWithOptions(options);
321 OnProcessLaunched(); // Fake a callback that the process is ready.
322 } else {
323 // Build command line for renderer. We call AppendRendererCommandLine()
324 // first so the process type argument will appear first.
325 CommandLine* cmd_line = new CommandLine(renderer_path);
326 if (!renderer_prefix.empty())
327 cmd_line->PrependWrapper(renderer_prefix);
328 AppendRendererCommandLine(cmd_line);
329 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
331 // Spawn the child process asynchronously to avoid blocking the UI thread.
332 // As long as there's no renderer prefix, we can use the zygote process
333 // at this stage.
334 child_process_.reset(new ChildProcessLauncher(
335 #if defined(OS_WIN)
336 FilePath(),
337 #elif defined(POSIX)
338 renderer_prefix.empty(),
339 base::environment_vector(),
340 channel_->GetClientFileDescriptor(),
341 #endif
342 cmd_line,
343 this));
345 fast_shutdown_started_ = false;
348 return true;
351 int BrowserRenderProcessHost::GetNextRoutingID() {
352 return widget_helper_->GetNextRoutingID();
355 void BrowserRenderProcessHost::CancelResourceRequests(int render_widget_id) {
356 widget_helper_->CancelResourceRequests(render_widget_id);
359 void BrowserRenderProcessHost::CrossSiteClosePageACK(
360 const ViewMsg_ClosePage_Params& params) {
361 widget_helper_->CrossSiteClosePageACK(params);
364 bool BrowserRenderProcessHost::WaitForUpdateMsg(
365 int render_widget_id,
366 const base::TimeDelta& max_delay,
367 IPC::Message* msg) {
368 // The post task to this thread with the process id could be in queue, and we
369 // don't want to dispatch a message before then since it will need the handle.
370 if (child_process_.get() && child_process_->IsStarting())
371 return false;
373 return widget_helper_->WaitForUpdateMsg(render_widget_id, max_delay, msg);
376 void BrowserRenderProcessHost::ReceivedBadMessage(uint32 msg_type) {
377 BadMessageTerminateProcess(msg_type, GetHandle());
380 void BrowserRenderProcessHost::ViewCreated() {
381 visited_link_updater_->ReceiverReady(this);
384 void BrowserRenderProcessHost::WidgetRestored() {
385 // Verify we were properly backgrounded.
386 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
387 visible_widgets_++;
388 visited_link_updater_->Update(this);
389 SetBackgrounded(false);
392 void BrowserRenderProcessHost::WidgetHidden() {
393 // On startup, the browser will call Hide
394 if (backgrounded_)
395 return;
397 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
398 visible_widgets_--;
399 DCHECK_GE(visible_widgets_, 0);
400 if (visible_widgets_ == 0) {
401 DCHECK(!backgrounded_);
402 SetBackgrounded(true);
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;
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));
421 void BrowserRenderProcessHost::AddVisitedLinks(
422 const VisitedLinkCommon::Fingerprints& links) {
423 visited_link_updater_->AddLinks(links);
424 if (visible_widgets_ == 0)
425 return;
427 visited_link_updater_->Update(this);
430 void BrowserRenderProcessHost::ResetVisitedLinks() {
431 visited_link_updater_->AddReset();
432 if (visible_widgets_ == 0)
433 return;
435 visited_link_updater_->Update(this);
438 void BrowserRenderProcessHost::AppendRendererCommandLine(
439 CommandLine* command_line) const {
440 // Pass the process type first, so it shows first in process listings.
441 // Extensions use a special pseudo-process type to make them distinguishable,
442 // even though they're just renderers.
443 command_line->AppendSwitchASCII(switches::kProcessType,
444 extension_process_ ? switches::kExtensionProcess :
445 switches::kRendererProcess);
447 if (logging::DialogsAreSuppressed())
448 command_line->AppendSwitch(switches::kNoErrorDialogs);
450 // Now send any options from our own command line we want to propogate.
451 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
452 PropagateBrowserCommandLineToRenderer(browser_command_line, command_line);
454 // Pass on the browser locale.
455 const std::string locale = g_browser_process->GetApplicationLocale();
456 command_line->AppendSwitchASCII(switches::kLang, locale);
458 // If we run FieldTrials, we want to pass to their state to the renderer so
459 // that it can act in accordance with each state, or record histograms
460 // relating to the FieldTrial states.
461 std::string field_trial_states;
462 FieldTrialList::StatesToString(&field_trial_states);
463 if (!field_trial_states.empty()) {
464 command_line->AppendSwitchASCII(switches::kForceFieldTestNameAndValue,
465 field_trial_states);
468 BrowserChildProcessHost::SetCrashReporterCommandLine(command_line);
470 FilePath user_data_dir =
471 browser_command_line.GetSwitchValuePath(switches::kUserDataDir);
472 if (!user_data_dir.empty())
473 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
474 #if defined(OS_CHROMEOS)
475 const std::string& profile =
476 browser_command_line.GetSwitchValueASCII(switches::kLoginProfile);
477 if (!profile.empty())
478 command_line->AppendSwitchASCII(switches::kLoginProfile, profile);
479 #endif
482 void BrowserRenderProcessHost::PropagateBrowserCommandLineToRenderer(
483 const CommandLine& browser_cmd,
484 CommandLine* renderer_cmd) const {
485 // Propagate the following switches to the renderer command line (along
486 // with any associated values) if present in the browser command line.
487 static const char* const kSwitchNames[] = {
488 switches::kRendererAssertTest,
489 #if !defined(OFFICIAL_BUILD)
490 switches::kRendererCheckFalseTest,
491 #endif // !defined(OFFICIAL_BUILD)
492 switches::kRendererCrashTest,
493 switches::kRendererStartupDialog,
494 switches::kNoSandbox,
495 switches::kTestSandbox,
496 #if defined(USE_SECCOMP_SANDBOX)
497 switches::kDisableSeccompSandbox,
498 #else
499 switches::kEnableSeccompSandbox,
500 #endif
501 #if !defined (GOOGLE_CHROME_BUILD)
502 // These are unsupported and not fully tested modes, so don't enable them
503 // for official Google Chrome builds.
504 switches::kInProcessPlugins,
505 #endif // GOOGLE_CHROME_BUILD
506 switches::kAllowScriptingGallery,
507 switches::kDomAutomationController,
508 switches::kUserAgent,
509 switches::kNoReferrers,
510 switches::kJavaScriptFlags,
511 switches::kRecordMode,
512 switches::kPlaybackMode,
513 switches::kNoJsRandomness,
514 switches::kDisableBreakpad,
515 switches::kFullMemoryCrashReport,
516 switches::kEnableLogging,
517 switches::kDumpHistogramsOnExit,
518 switches::kDisableLogging,
519 switches::kLoggingLevel,
520 switches::kDebugPrint,
521 switches::kMemoryProfiling,
522 switches::kEnableWatchdog,
523 switches::kMessageLoopHistogrammer,
524 switches::kEnableDCHECK,
525 switches::kSilentDumpOnDCHECK,
526 switches::kUseLowFragHeapCrt,
527 switches::kEnableSearchProviderApiV2,
528 switches::kEnableStatsTable,
529 switches::kExperimentalSpellcheckerFeatures,
530 switches::kDisableAudio,
531 switches::kSimpleDataSource,
532 switches::kEnableBenchmarking,
533 switches::kInternalNaCl,
534 switches::kInternalPepper,
535 switches::kRegisterPepperPlugins,
536 switches::kDisableByteRangeSupport,
537 switches::kDisableDatabases,
538 switches::kDisableDesktopNotifications,
539 switches::kDisableWebSockets,
540 switches::kDisableLocalStorage,
541 switches::kDisableSessionStorage,
542 switches::kDisableSharedWorkers,
543 switches::kDisableApplicationCache,
544 switches::kDisableDeviceOrientation,
545 switches::kEnableIndexedDatabase,
546 switches::kDisableSpeechInput,
547 switches::kEnableSpeechInput,
548 switches::kDisableGeolocation,
549 switches::kShowPaintRects,
550 switches::kEnableOpenMax,
551 switches::kVideoThreads,
552 switches::kEnableVideoFullscreen,
553 switches::kEnableVideoLayering,
554 switches::kEnableVideoLogging,
555 switches::kEnableTouch,
556 // We propagate the Chrome Frame command line here as well in case the
557 // renderer is not run in the sandbox.
558 switches::kChromeFrame,
559 // We need to propagate this flag to determine whether to make the
560 // WebGLArray constructors on the DOMWindow visible. This
561 // information is needed very early during bringup. We prefer to
562 // use the WebPreferences to set this flag on a page-by-page basis.
563 switches::kDisableExperimentalWebGL,
564 switches::kDisableGLSLTranslator,
565 switches::kInProcessWebGL,
566 switches::kDisableAcceleratedCompositing,
567 #if defined(OS_MACOSX)
568 // Allow this to be set when invoking the browser and relayed along.
569 switches::kEnableSandboxLogging,
570 switches::kDisableFlashCoreAnimation,
571 #endif
572 switches::kRemoteShellPort,
573 switches::kEnablePepperTesting,
574 switches::kBlockNonSandboxedPlugins,
575 switches::kDisableOutdatedPlugins,
576 switches::kEnableRemoting,
577 switches::kDisableClickToPlay,
578 switches::kEnableResourceContentSettings,
579 switches::kPrelaunchGpuProcess,
580 switches::kEnableAcceleratedDecoding,
581 switches::kEnableFileSystem,
583 renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
584 arraysize(kSwitchNames));
586 // Disable databases in incognito mode.
587 if (profile()->IsOffTheRecord() &&
588 !browser_cmd.HasSwitch(switches::kDisableDatabases)) {
589 renderer_cmd->AppendSwitch(switches::kDisableDatabases);
593 base::ProcessHandle BrowserRenderProcessHost::GetHandle() {
594 // child_process_ is null either because we're in single process mode, we have
595 // done fast termination, or the process has crashed.
596 if (run_renderer_in_process() || !child_process_.get())
597 return base::Process::Current().handle();
599 if (child_process_->IsStarting())
600 return base::kNullProcessHandle;
602 return child_process_->GetHandle();
605 void BrowserRenderProcessHost::InitVisitedLinks() {
606 VisitedLinkMaster* visitedlink_master = profile()->GetVisitedLinkMaster();
607 if (!visitedlink_master)
608 return;
610 SendVisitedLinkTable(visitedlink_master->shared_memory());
613 void BrowserRenderProcessHost::InitUserScripts() {
614 UserScriptMaster* user_script_master = profile()->GetUserScriptMaster();
616 // Incognito profiles won't have user scripts.
617 if (!user_script_master)
618 return;
620 if (!user_script_master->ScriptsReady()) {
621 // No scripts ready. :(
622 return;
625 // Update the renderer process with the current scripts.
626 SendUserScriptsUpdate(user_script_master->GetSharedMemory());
629 void BrowserRenderProcessHost::InitExtensions() {
630 // TODO(aa): Should only bother sending these function names if this is an
631 // extension process.
632 std::vector<std::string> function_names;
633 ExtensionFunctionDispatcher::GetAllFunctionNames(&function_names);
634 Send(new ViewMsg_Extension_SetFunctionNames(function_names));
637 void BrowserRenderProcessHost::SendUserScriptsUpdate(
638 base::SharedMemory *shared_memory) {
639 // Process is being started asynchronously. We'll end up calling
640 // InitUserScripts when it's created which will call this again.
641 if (child_process_.get() && child_process_->IsStarting())
642 return;
644 base::SharedMemoryHandle handle_for_process;
645 if (!shared_memory->ShareToProcess(GetHandle(), &handle_for_process)) {
646 // This can legitimately fail if the renderer asserts at startup.
647 return;
650 if (base::SharedMemory::IsHandleValid(handle_for_process)) {
651 Send(new ViewMsg_UserScripts_UpdatedScripts(handle_for_process));
655 void BrowserRenderProcessHost::SendExtensionInfo() {
656 // Check if the process is still starting and we don't have a handle for it
657 // yet, in which case this will happen later when InitVisitedLinks is called.
658 if (!run_renderer_in_process() &&
659 (!child_process_.get() || child_process_->IsStarting())) {
660 return;
663 ExtensionsService* service = profile()->GetExtensionsService();
664 if (!service)
665 return;
666 ViewMsg_ExtensionsUpdated_Params params;
667 for (size_t i = 0; i < service->extensions()->size(); ++i) {
668 Extension* extension = service->extensions()->at(i);
669 ViewMsg_ExtensionRendererInfo info;
670 info.id = extension->id();
671 info.web_extent = extension->web_extent();
672 info.name = extension->name();
673 info.location = extension->location();
674 info.icon_url =
675 extension->GetIconURLAllowLargerSize(Extension::EXTENSION_ICON_MEDIUM);
676 params.extensions.push_back(info);
679 Send(new ViewMsg_ExtensionsUpdated(params));
682 bool BrowserRenderProcessHost::FastShutdownIfPossible() {
683 if (run_renderer_in_process())
684 return false; // Single process mode can't do fast shutdown.
686 if (!child_process_.get() || child_process_->IsStarting() || !GetHandle())
687 return false; // Render process hasn't started or is probably crashed.
689 // Test if there's an unload listener.
690 // NOTE: It's possible that an onunload listener may be installed
691 // while we're shutting down, so there's a small race here. Given that
692 // the window is small, it's unlikely that the web page has much
693 // state that will be lost by not calling its unload handlers properly.
694 if (!sudden_termination_allowed())
695 return false;
697 // Check for any external tab containers, since they may still be running even
698 // though this window closed.
699 listeners_iterator iter(ListenersIterator());
700 while (!iter.IsAtEnd()) {
701 // NOTE: This is a bit dangerous. We know that for now, listeners are
702 // always RenderWidgetHosts. But in theory, they don't have to be.
703 const RenderWidgetHost* widget =
704 static_cast<const RenderWidgetHost*>(iter.GetCurrentValue());
705 DCHECK(widget);
706 if (widget && widget->IsRenderView()) {
707 const RenderViewHost* rvh = static_cast<const RenderViewHost*>(widget);
708 if (rvh->delegate()->IsExternalTabContainer())
709 return false;
712 iter.Advance();
715 child_process_.reset();
716 fast_shutdown_started_ = true;
717 return true;
720 bool BrowserRenderProcessHost::SendWithTimeout(IPC::Message* msg,
721 int timeout_ms) {
722 if (!channel_.get()) {
723 delete msg;
724 return false;
726 return channel_->SendWithTimeout(msg, timeout_ms);
729 // This is a platform specific function for mapping a transport DIB given its id
730 TransportDIB* BrowserRenderProcessHost::MapTransportDIB(
731 TransportDIB::Id dib_id) {
732 #if defined(OS_WIN)
733 // On Windows we need to duplicate the handle from the remote process
734 HANDLE section = win_util::GetSectionFromProcess(
735 dib_id.handle, GetHandle(), false /* read write */);
736 return TransportDIB::Map(section);
737 #elif defined(OS_MACOSX)
738 // On OSX, the browser allocates all DIBs and keeps a file descriptor around
739 // for each.
740 return widget_helper_->MapTransportDIB(dib_id);
741 #elif defined(OS_POSIX)
742 return TransportDIB::Map(dib_id);
743 #endif // defined(OS_POSIX)
746 TransportDIB* BrowserRenderProcessHost::GetTransportDIB(
747 TransportDIB::Id dib_id) {
748 const std::map<TransportDIB::Id, TransportDIB*>::iterator
749 i = cached_dibs_.find(dib_id);
750 if (i != cached_dibs_.end()) {
751 cached_dibs_cleaner_.Reset();
752 return i->second;
755 TransportDIB* dib = MapTransportDIB(dib_id);
756 if (!dib)
757 return NULL;
759 if (cached_dibs_.size() >= MAX_MAPPED_TRANSPORT_DIBS) {
760 // Clean a single entry from the cache
761 std::map<TransportDIB::Id, TransportDIB*>::iterator smallest_iterator;
762 size_t smallest_size = std::numeric_limits<size_t>::max();
764 for (std::map<TransportDIB::Id, TransportDIB*>::iterator
765 i = cached_dibs_.begin(); i != cached_dibs_.end(); ++i) {
766 if (i->second->size() <= smallest_size) {
767 smallest_iterator = i;
768 smallest_size = i->second->size();
772 delete smallest_iterator->second;
773 cached_dibs_.erase(smallest_iterator);
776 cached_dibs_[dib_id] = dib;
777 cached_dibs_cleaner_.Reset();
778 return dib;
781 void BrowserRenderProcessHost::ClearTransportDIBCache() {
782 STLDeleteContainerPairSecondPointers(
783 cached_dibs_.begin(), cached_dibs_.end());
784 cached_dibs_.clear();
787 bool BrowserRenderProcessHost::Send(IPC::Message* msg) {
788 if (!channel_.get()) {
789 delete msg;
790 return false;
793 if (child_process_.get() && child_process_->IsStarting()) {
794 queued_messages_.push(msg);
795 return true;
798 return channel_->Send(msg);
801 void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) {
802 mark_child_process_activity_time();
803 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
804 // Dispatch control messages.
805 bool msg_is_ok = true;
806 IPC_BEGIN_MESSAGE_MAP_EX(BrowserRenderProcessHost, msg, msg_is_ok)
807 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdatedCacheStats,
808 OnUpdatedCacheStats)
809 IPC_MESSAGE_HANDLER(ViewHostMsg_SuddenTerminationChanged,
810 SuddenTerminationChanged);
811 IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionAddListener,
812 OnExtensionAddListener)
813 IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionRemoveListener,
814 OnExtensionRemoveListener)
815 IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionCloseChannel,
816 OnExtensionCloseChannel)
817 IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_RequestDictionary,
818 OnSpellCheckerRequestDictionary)
819 IPC_MESSAGE_UNHANDLED_ERROR()
820 IPC_END_MESSAGE_MAP_EX()
822 if (!msg_is_ok) {
823 // The message had a handler, but its de-serialization failed.
824 // We consider this a capital crime. Kill the renderer if we have one.
825 ReceivedBadMessage(msg.type());
827 return;
830 // Dispatch incoming messages to the appropriate RenderView/WidgetHost.
831 IPC::Channel::Listener* listener = GetListenerByID(msg.routing_id());
832 if (!listener) {
833 if (msg.is_sync()) {
834 // The listener has gone away, so we must respond or else the caller will
835 // hang waiting for a reply.
836 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
837 reply->set_reply_error();
838 Send(reply);
840 return;
842 listener->OnMessageReceived(msg);
845 void BrowserRenderProcessHost::OnChannelConnected(int32 peer_pid) {
846 #if defined(IPC_MESSAGE_LOG_ENABLED)
847 Send(new ViewMsg_SetIPCLoggingEnabled(IPC::Logging::current()->Enabled()));
848 #endif
851 // Static. This function can be called from any thread.
852 void BrowserRenderProcessHost::BadMessageTerminateProcess(
853 uint32 msg_type, base::ProcessHandle process) {
854 LOG(ERROR) << "bad message " << msg_type << " terminating renderer.";
855 if (run_renderer_in_process()) {
856 // In single process mode it is better if we don't suicide but just crash.
857 CHECK(false);
859 NOTREACHED();
860 base::KillProcess(process, ResultCodes::KILLED_BAD_MESSAGE, false);
863 void BrowserRenderProcessHost::OnChannelError() {
864 // Our child process has died. If we didn't expect it, it's a crash.
865 // In any case, we need to let everyone know it's gone.
866 // The OnChannelError notification can fire multiple times due to nested sync
867 // calls to a renderer. If we don't have a valid channel here it means we
868 // already handled the error.
869 if (!channel_.get())
870 return;
872 // NULL in single process mode or if fast termination happened.
873 bool did_crash =
874 child_process_.get() ? child_process_->DidProcessCrash() : false;
876 if (did_crash) {
877 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes",
878 extension_process_ ? 2 : 1);
881 RendererClosedDetails details(did_crash, extension_process_);
882 NotificationService::current()->Notify(
883 NotificationType::RENDERER_PROCESS_CLOSED,
884 Source<RenderProcessHost>(this),
885 Details<RendererClosedDetails>(&details));
887 WebCacheManager::GetInstance()->Remove(id());
888 child_process_.reset();
889 channel_.reset();
891 IDMap<IPC::Channel::Listener>::iterator iter(&listeners_);
892 while (!iter.IsAtEnd()) {
893 iter.GetCurrentValue()->OnMessageReceived(
894 ViewHostMsg_RenderViewGone(iter.GetCurrentKey()));
895 iter.Advance();
898 ClearTransportDIBCache();
900 // this object is not deleted at this point and may be reused later.
901 // TODO(darin): clean this up
904 void BrowserRenderProcessHost::OnUpdatedCacheStats(
905 const WebCache::UsageStats& stats) {
906 WebCacheManager::GetInstance()->ObserveStats(id(), stats);
909 void BrowserRenderProcessHost::SuddenTerminationChanged(bool enabled) {
910 set_sudden_termination_allowed(enabled);
913 void BrowserRenderProcessHost::SetBackgrounded(bool backgrounded) {
914 // Note: we always set the backgrounded_ value. If the process is NULL
915 // (and hence hasn't been created yet), we will set the process priority
916 // later when we create the process.
917 backgrounded_ = backgrounded;
918 if (!child_process_.get() || child_process_->IsStarting())
919 return;
921 #if defined(OS_WIN)
922 // The cbstext.dll loads as a global GetMessage hook in the browser process
923 // and intercepts/unintercepts the kernel32 API SetPriorityClass in a
924 // background thread. If the UI thread invokes this API just when it is
925 // intercepted the stack is messed up on return from the interceptor
926 // which causes random crashes in the browser process. Our hack for now
927 // is to not invoke the SetPriorityClass API if the dll is loaded.
928 if (GetModuleHandle(L"cbstext.dll"))
929 return;
930 #endif // OS_WIN
932 child_process_->SetProcessBackgrounded(backgrounded);
935 void BrowserRenderProcessHost::Observe(NotificationType type,
936 const NotificationSource& source,
937 const NotificationDetails& details) {
938 switch (type.value) {
939 case NotificationType::USER_SCRIPTS_UPDATED: {
940 base::SharedMemory* shared_memory =
941 Details<base::SharedMemory>(details).ptr();
942 if (shared_memory) {
943 SendUserScriptsUpdate(shared_memory);
945 break;
947 case NotificationType::EXTENSION_LOADED:
948 case NotificationType::EXTENSION_UNLOADED: {
949 SendExtensionInfo();
950 break;
952 case NotificationType::SPELLCHECK_HOST_REINITIALIZED: {
953 InitSpellChecker();
954 break;
956 case NotificationType::SPELLCHECK_WORD_ADDED: {
957 AddSpellCheckWord(
958 reinterpret_cast<const Source<SpellCheckHost>*>(&source)->
959 ptr()->last_added_word());
960 break;
962 case NotificationType::SPELLCHECK_AUTOSPELL_TOGGLED: {
963 PrefService* prefs = profile()->GetPrefs();
964 EnableAutoSpellCorrect(
965 prefs->GetBoolean(prefs::kEnableAutoSpellCorrect));
966 break;
968 default: {
969 NOTREACHED();
970 break;
975 void BrowserRenderProcessHost::OnProcessLaunched() {
976 // At this point, we used to set the process priority if it were marked as
977 // backgrounded_. We don't do that anymore because when we create a process,
978 // we really don't know how it will be used. If it is backgrounded, and not
979 // yet processed, a stray hung-cpu process (not chrome) can cause pages to
980 // not load at all. (see http://crbug.com/21884).
981 // If we could perfectly track when a process is created as visible or not,
982 // we could potentially call SetBackgrounded() properly at this point. But
983 // there are many cases, and no effective way to automate those cases.
984 // I'm choosing correctness over the feature of de-prioritizing this work.
986 Send(new ViewMsg_SetIsIncognitoProcess(profile()->IsOffTheRecord()));
988 InitVisitedLinks();
989 InitUserScripts();
990 InitExtensions();
991 SendExtensionInfo();
993 // We don't want to initialize the spellchecker unless SpellCheckHost has been
994 // created. In InitSpellChecker(), we know if GetSpellCheckHost() is NULL
995 // then the spellchecker has been turned off, but here, we don't know if
996 // it's been turned off or just not loaded yet.
997 if (profile()->GetSpellCheckHost())
998 InitSpellChecker();
1000 if (max_page_id_ != -1)
1001 Send(new ViewMsg_SetNextPageID(max_page_id_ + 1));
1003 while (!queued_messages_.empty()) {
1004 Send(queued_messages_.front());
1005 queued_messages_.pop();
1008 NotificationService::current()->Notify(
1009 NotificationType::RENDERER_PROCESS_CREATED,
1010 Source<RenderProcessHost>(this), NotificationService::NoDetails());
1013 void BrowserRenderProcessHost::OnExtensionAddListener(
1014 const std::string& event_name) {
1015 if (profile()->GetExtensionMessageService()) {
1016 profile()->GetExtensionMessageService()->AddEventListener(
1017 event_name, id());
1021 void BrowserRenderProcessHost::OnExtensionRemoveListener(
1022 const std::string& event_name) {
1023 if (profile()->GetExtensionMessageService()) {
1024 profile()->GetExtensionMessageService()->RemoveEventListener(
1025 event_name, id());
1029 void BrowserRenderProcessHost::OnExtensionCloseChannel(int port_id) {
1030 if (profile()->GetExtensionMessageService()) {
1031 profile()->GetExtensionMessageService()->CloseChannel(port_id);
1035 void BrowserRenderProcessHost::OnSpellCheckerRequestDictionary() {
1036 if (profile()->GetSpellCheckHost()) {
1037 // The spellchecker initialization already started and finished; just send
1038 // it to the renderer.
1039 InitSpellChecker();
1040 } else {
1041 // We may have gotten multiple requests from different renderers. We don't
1042 // want to initialize multiple times in this case, so we set |force| to
1043 // false.
1044 profile()->ReinitializeSpellCheckHost(false);
1048 void BrowserRenderProcessHost::AddSpellCheckWord(const std::string& word) {
1049 Send(new ViewMsg_SpellChecker_WordAdded(word));
1052 void BrowserRenderProcessHost::InitSpellChecker() {
1053 SpellCheckHost* spellcheck_host = profile()->GetSpellCheckHost();
1054 if (spellcheck_host) {
1055 PrefService* prefs = profile()->GetPrefs();
1056 IPC::PlatformFileForTransit file;
1058 if (spellcheck_host->bdict_file() != base::kInvalidPlatformFileValue) {
1059 #if defined(OS_POSIX)
1060 file = base::FileDescriptor(spellcheck_host->bdict_file(), false);
1061 #elif defined(OS_WIN)
1062 ::DuplicateHandle(::GetCurrentProcess(), spellcheck_host->bdict_file(),
1063 GetHandle(), &file, 0, false, DUPLICATE_SAME_ACCESS);
1064 #endif
1067 Send(new ViewMsg_SpellChecker_Init(
1068 file,
1069 spellcheck_host->custom_words(),
1070 spellcheck_host->language(),
1071 prefs->GetBoolean(prefs::kEnableAutoSpellCorrect)));
1072 } else {
1073 Send(new ViewMsg_SpellChecker_Init(
1074 IPC::InvalidPlatformFileForTransit(),
1075 std::vector<std::string>(),
1076 std::string(),
1077 false));
1081 void BrowserRenderProcessHost::EnableAutoSpellCorrect(bool enable) {
1082 Send(new ViewMsg_SpellChecker_EnableAutoSpellCorrect(enable));