Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / content / child / child_thread.cc
index 1852dc9..3222b41 100644 (file)
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
+#include "base/message_loop/timer_slack.h"
 #include "base/process/kill.h"
 #include "base/process/process_handle.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/lock.h"
@@ -29,6 +31,8 @@
 #include "content/child/child_resource_message_filter.h"
 #include "content/child/child_shared_bitmap_manager.h"
 #include "content/child/fileapi/file_system_dispatcher.h"
+#include "content/child/fileapi/webfilesystem_impl.h"
+#include "content/child/mojo/mojo_application.h"
 #include "content/child/power_monitor_broadcast_source.h"
 #include "content/child/quota_dispatcher.h"
 #include "content/child/quota_message_filter.h"
@@ -44,7 +48,6 @@
 #include "ipc/ipc_switches.h"
 #include "ipc/ipc_sync_channel.h"
 #include "ipc/ipc_sync_message_filter.h"
-#include "webkit/child/resource_loader_bridge.h"
 
 #if defined(OS_WIN)
 #include "content/common/handle_enumerator_win.h"
@@ -70,8 +73,11 @@ base::LazyInstance<base::ThreadLocalPointer<ChildThread> > g_lazy_tls =
 // plugins), PluginThread has EnsureTerminateMessageFilter.
 #if defined(OS_POSIX)
 
-// A thread delegate that waits for |duration| and then signals the process
-// with SIGALRM.
+// TODO(earthdok): Re-enable on CrOS http://crbug.com/360622
+#if (defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)) && !defined(OS_CHROMEOS)
+// A thread delegate that waits for |duration| and then exits the process with
+// _exit(0).
 class WaitAndExitDelegate : public base::PlatformThread::Delegate {
  public:
   explicit WaitAndExitDelegate(base::TimeDelta duration)
@@ -80,13 +86,6 @@ class WaitAndExitDelegate : public base::PlatformThread::Delegate {
 
   virtual void ThreadMain() OVERRIDE {
     base::PlatformThread::Sleep(duration_);
-    // This used to be implemented with alarm(2). Make sure to not break
-    // anything that requires the process being signaled.
-    CHECK_EQ(0, raise(SIGALRM));
-
-    base::PlatformThread::Sleep((base::TimeDelta::FromSeconds(10)));
-    // If something erroneously blocked SIGALRM, this will trigger.
-    NOTREACHED();
     _exit(0);
   }
 
@@ -95,13 +94,11 @@ class WaitAndExitDelegate : public base::PlatformThread::Delegate {
   DISALLOW_COPY_AND_ASSIGN(WaitAndExitDelegate);
 };
 
-// This is similar to using alarm(2), except it will spawn a thread
-// which will sleep for |duration| before raising SIGALRM.
-bool CreateAlarmThread(base::TimeDelta duration) {
+bool CreateWaitAndExitThread(base::TimeDelta duration) {
   scoped_ptr<WaitAndExitDelegate> delegate(new WaitAndExitDelegate(duration));
 
-  const bool thread_created = base::PlatformThread::CreateNonJoinable(
-      0 /* stack_size */, delegate.get());
+  const bool thread_created =
+      base::PlatformThread::CreateNonJoinable(0, delegate.get());
   if (!thread_created)
     return false;
 
@@ -113,17 +110,18 @@ bool CreateAlarmThread(base::TimeDelta duration) {
   ignore_result(leaking_delegate);
   return true;
 }
+#endif
 
-class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter {
+class SuicideOnChannelErrorFilter : public IPC::MessageFilter {
  public:
-  // IPC::ChannelProxy::MessageFilter
+  // IPC::MessageFilter
   virtual void OnChannelError() OVERRIDE {
     // For renderer/worker processes:
     // On POSIX, at least, one can install an unload handler which loops
     // forever and leave behind a renderer process which eats 100% CPU forever.
     //
     // This is because the terminate signals (ViewMsg_ShouldClose and the error
-    // from the IPC channel) are routed to the main message loop but never
+    // from the IPC sender) are routed to the main message loop but never
     // processed (because that message loop is stuck in V8).
     //
     // One could make the browser SIGKILL the renderers, but that leaves open a
@@ -131,23 +129,23 @@ class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter {
     // the browser because "it's stuck") will leave behind a process eating all
     // the CPU.
     //
-    // So, we install a filter on the channel so that we can process this event
+    // So, we install a filter on the sender so that we can process this event
     // here and kill the process.
-    if (CommandLine::ForCurrentProcess()->
-        HasSwitch(switches::kChildCleanExit)) {
-      // If clean exit is requested, we want to kill this process after giving
-      // it 60 seconds to run exit handlers. Exit handlers may including ones
-      // that write profile data to disk (which happens under profile collection
-      // mode).
-      CHECK(CreateAlarmThread(base::TimeDelta::FromSeconds(60)));
+    // TODO(earthdok): Re-enable on CrOS http://crbug.com/360622
+#if (defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)) && !defined(OS_CHROMEOS)
+    // Some sanitizer tools rely on exit handlers (e.g. to run leak detection,
+    // or dump code coverage data to disk). Instead of exiting the process
+    // immediately, we give it 60 seconds to run exit handlers.
+    CHECK(CreateWaitAndExitThread(base::TimeDelta::FromSeconds(60)));
 #if defined(LEAK_SANITIZER)
-      // Invoke LeakSanitizer early to avoid detecting shutdown-only leaks. If
-      // leaks are found, the process will exit here.
-      __lsan_do_leak_check();
+    // Invoke LeakSanitizer early to avoid detecting shutdown-only leaks. If
+    // leaks are found, the process will exit here.
+    __lsan_do_leak_check();
+#endif
+#else
+    _exit(0);
 #endif
-    } else {
-      _exit(0);
-    }
   }
 
  protected:
@@ -229,18 +227,20 @@ void ChildThread::Init() {
   // the logger, and the logger does not like being created on the IO thread.
   IPC::Logging::GetInstance();
 #endif
-  channel_.reset(
-      new IPC::SyncChannel(channel_name_,
-                           IPC::Channel::MODE_CLIENT,
-                           this,
-                           ChildProcess::current()->io_message_loop_proxy(),
-                           true,
-                           ChildProcess::current()->GetShutDownEvent()));
+  channel_ =
+      IPC::SyncChannel::Create(channel_name_,
+                               IPC::Channel::MODE_CLIENT,
+                               this,
+                               ChildProcess::current()->io_message_loop_proxy(),
+                               true,
+                               ChildProcess::current()->GetShutDownEvent());
 #ifdef IPC_MESSAGE_LOG_ENABLED
   if (!in_browser_process_)
     IPC::Logging::GetInstance()->SetIPCSender(this);
 #endif
 
+  mojo_application_.reset(new MojoApplication(this));
+
   sync_message_filter_ =
       new IPC::SyncMessageFilter(ChildProcess::current()->GetShutDownEvent());
   thread_safe_sender_ = new ThreadSafeSender(
@@ -267,12 +267,17 @@ void ChildThread::Init() {
 
   channel_->AddFilter(histogram_message_filter_.get());
   channel_->AddFilter(sync_message_filter_.get());
-  channel_->AddFilter(new tracing::ChildTraceMessageFilter(
-      ChildProcess::current()->io_message_loop_proxy()));
   channel_->AddFilter(resource_message_filter_.get());
   channel_->AddFilter(quota_message_filter_->GetFilter());
   channel_->AddFilter(service_worker_message_filter_->GetFilter());
 
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) {
+    // In single process mode, browser-side tracing will cover the whole
+    // process including renderers.
+    channel_->AddFilter(new tracing::ChildTraceMessageFilter(
+        ChildProcess::current()->io_message_loop_proxy()));
+  }
+
   // In single process mode we may already have a power monitor
   if (!base::PowerMonitor::Get()) {
     scoped_ptr<PowerMonitorBroadcastSource> power_monitor_source(
@@ -290,11 +295,21 @@ void ChildThread::Init() {
     channel_->AddFilter(new SuicideOnChannelErrorFilter());
 #endif
 
+  int connection_timeout = kConnectionTimeoutS;
+  std::string connection_override =
+      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+          switches::kIPCConnectionTimeout);
+  if (!connection_override.empty()) {
+    int temp;
+    if (base::StringToInt(connection_override, &temp))
+      connection_timeout = temp;
+  }
+
   base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&ChildThread::EnsureConnected,
                  channel_connected_factory_.GetWeakPtr()),
-      base::TimeDelta::FromSeconds(kConnectionTimeoutS));
+      base::TimeDelta::FromSeconds(connection_timeout));
 
 #if defined(OS_ANDROID)
   {
@@ -343,6 +358,7 @@ void ChildThread::Shutdown() {
   // safely shutdown blink in their Shutdown implementation.
   file_system_dispatcher_.reset();
   quota_dispatcher_.reset();
+  WebFileSystemImpl::DeleteThreadSpecificInstance();
 }
 
 void ChildThread::OnChannelConnected(int32 peer_pid) {
@@ -354,6 +370,15 @@ void ChildThread::OnChannelError() {
   base::MessageLoop::current()->Quit();
 }
 
+void ChildThread::ConnectToService(
+    const mojo::String& service_url,
+    const mojo::String& service_name,
+    mojo::ScopedMessagePipeHandle message_pipe,
+    const mojo::String& requestor_url) {
+  // By default, we don't expect incoming connections.
+  NOTREACHED();
+}
+
 bool ChildThread::Send(IPC::Message* msg) {
   DCHECK(base::MessageLoop::current() == message_loop());
   if (!channel_) {
@@ -369,11 +394,6 @@ MessageRouter* ChildThread::GetRouter() {
   return &router_;
 }
 
-webkit_glue::ResourceLoaderBridge* ChildThread::CreateBridge(
-    const RequestInfo& request_info) {
-  return resource_dispatcher()->CreateBridge(request_info);
-}
-
 base::SharedMemory* ChildThread::AllocateSharedMemory(size_t buf_size) {
   return AllocateSharedMemory(buf_size, this);
 }
@@ -414,6 +434,9 @@ base::SharedMemory* ChildThread::AllocateSharedMemory(
 }
 
 bool ChildThread::OnMessageReceived(const IPC::Message& msg) {
+  if (mojo_application_->OnMessageReceived(msg))
+    return true;
+
   // Resource responses are sent to the resource dispatcher.
   if (resource_dispatcher_->OnMessageReceived(msg))
     return true;
@@ -436,6 +459,8 @@ bool ChildThread::OnMessageReceived(const IPC::Message& msg) {
     IPC_MESSAGE_HANDLER(ChildProcessMsg_GetChildProfilerData,
                         OnGetChildProfilerData)
     IPC_MESSAGE_HANDLER(ChildProcessMsg_DumpHandles, OnDumpHandles)
+    IPC_MESSAGE_HANDLER(ChildProcessMsg_SetProcessBackgrounded,
+                        OnProcessBackgrounded)
 #if defined(USE_TCMALLOC)
     IPC_MESSAGE_HANDLER(ChildProcessMsg_GetTcmallocStats, OnGetTcmallocStats)
 #endif
@@ -544,4 +569,20 @@ void ChildThread::EnsureConnected() {
   base::KillProcess(base::GetCurrentProcessHandle(), 0, false);
 }
 
+void ChildThread::OnProcessBackgrounded(bool background) {
+  // Set timer slack to maximum on main thread when in background.
+  base::TimerSlack timer_slack = base::TIMER_SLACK_NONE;
+  if (background)
+    timer_slack = base::TIMER_SLACK_MAXIMUM;
+  base::MessageLoop::current()->SetTimerSlack(timer_slack);
+
+#ifdef OS_WIN
+  // Windows Vista+ has a fancy process backgrounding mode that can only be set
+  // from within the process.
+  // TODO(wfh) Do not set background from within process until the issue with
+  // white tabs is resolved.  See http://crbug.com/398103.
+  // base::Process::Current().SetProcessBackgrounded(background);
+#endif  // OS_WIN
+}
+
 }  // namespace content