|
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 |
|
3 // found in the LICENSE file. |
|
4 |
|
5 #include "chrome/common/child_thread.h" |
|
6 |
|
7 #include "base/string_util.h" |
|
8 #include "base/command_line.h" |
|
9 #include "chrome/common/child_process.h" |
|
10 #include "chrome/common/chrome_switches.h" |
|
11 #include "chrome/common/ipc_logging.h" |
|
12 |
|
13 // V8 needs a 1MB stack size. |
|
14 const size_t ChildThread::kV8StackSize = 1024 * 1024; |
|
15 |
|
16 ChildThread::ChildThread(Thread::Options options) |
|
17 : Thread("Chrome_ChildThread"), |
|
18 owner_loop_(MessageLoop::current()), |
|
19 options_(options), |
|
20 check_with_browser_before_shutdown_(false) { |
|
21 DCHECK(owner_loop_); |
|
22 channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValue( |
|
23 switches::kProcessChannelID); |
|
24 } |
|
25 |
|
26 ChildThread::~ChildThread() { |
|
27 } |
|
28 |
|
29 #ifdef MOZ_NUWA_PROCESS |
|
30 #include "ipc/Nuwa.h" |
|
31 #endif |
|
32 |
|
33 bool ChildThread::Run() { |
|
34 bool r = StartWithOptions(options_); |
|
35 #ifdef MOZ_NUWA_PROCESS |
|
36 NS_ASSERTION(NuwaMarkCurrentThread, "NuwaMarkCurrentThread is not defined!"); |
|
37 if (IsNuwaProcess()) { |
|
38 message_loop()->PostTask(FROM_HERE, |
|
39 NewRunnableFunction(&ChildThread::MarkThread)); |
|
40 } |
|
41 #endif |
|
42 return r; |
|
43 } |
|
44 |
|
45 void ChildThread::OnChannelError() { |
|
46 owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
|
47 } |
|
48 |
|
49 #ifdef MOZ_NUWA_PROCESS |
|
50 void ChildThread::MarkThread() { |
|
51 NuwaMarkCurrentThread(nullptr, nullptr); |
|
52 if (!NuwaCheckpointCurrentThread()) { |
|
53 NS_RUNTIMEABORT("Should not be here!"); |
|
54 } |
|
55 } |
|
56 #endif |
|
57 |
|
58 bool ChildThread::Send(IPC::Message* msg) { |
|
59 if (!channel_.get()) { |
|
60 delete msg; |
|
61 return false; |
|
62 } |
|
63 |
|
64 return channel_->Send(msg); |
|
65 } |
|
66 |
|
67 void ChildThread::AddRoute(int32_t routing_id, IPC::Channel::Listener* listener) { |
|
68 DCHECK(MessageLoop::current() == message_loop()); |
|
69 |
|
70 router_.AddRoute(routing_id, listener); |
|
71 } |
|
72 |
|
73 void ChildThread::RemoveRoute(int32_t routing_id) { |
|
74 DCHECK(MessageLoop::current() == message_loop()); |
|
75 |
|
76 router_.RemoveRoute(routing_id); |
|
77 } |
|
78 |
|
79 void ChildThread::OnMessageReceived(const IPC::Message& msg) { |
|
80 if (msg.routing_id() == MSG_ROUTING_CONTROL) { |
|
81 OnControlMessageReceived(msg); |
|
82 } else { |
|
83 router_.OnMessageReceived(msg); |
|
84 } |
|
85 } |
|
86 |
|
87 ChildThread* ChildThread::current() { |
|
88 return ChildProcess::current()->child_thread(); |
|
89 } |
|
90 |
|
91 void ChildThread::Init() { |
|
92 channel_.reset(new IPC::Channel(channel_name_, |
|
93 IPC::Channel::MODE_CLIENT, |
|
94 this)); |
|
95 |
|
96 #ifdef IPC_MESSAGE_LOG_ENABLED |
|
97 IPC::Logging::current()->SetIPCSender(this); |
|
98 #endif |
|
99 } |
|
100 |
|
101 void ChildThread::CleanUp() { |
|
102 #ifdef IPC_MESSAGE_LOG_ENABLED |
|
103 IPC::Logging::current()->SetIPCSender(NULL); |
|
104 #endif |
|
105 // Need to destruct the SyncChannel to the browser before we go away because |
|
106 // it caches a pointer to this thread. |
|
107 channel_.reset(); |
|
108 } |
|
109 |
|
110 void ChildThread::OnProcessFinalRelease() { |
|
111 if (!check_with_browser_before_shutdown_) { |
|
112 owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
|
113 return; |
|
114 } |
|
115 } |