Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(554)

Side by Side Diff: mojo/spy/spy.cc

Issue 354043003: Add support for logging information about mojo messages retrieved by the mojo debugger (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed indentation Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #include "mojo/spy/spy.h" 5 #include "mojo/spy/spy.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/logging.h"
10 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
12 #include "base/time/time.h"
11 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_split.h" 14 #include "base/strings/string_split.h"
13 #include "base/threading/thread.h" 15 #include "base/threading/thread.h"
14 #include "base/threading/worker_pool.h" 16 #include "base/threading/worker_pool.h"
15 17
16 #include "mojo/public/cpp/system/core.h" 18 #include "mojo/public/cpp/system/core.h"
17 #include "mojo/service_manager/service_manager.h" 19 #include "mojo/service_manager/service_manager.h"
20 #include "mojo/spy/common.h"
18 #include "mojo/spy/websocket_server.h" 21 #include "mojo/spy/websocket_server.h"
19 22
20 namespace { 23 namespace {
21 24
25 spy::WebSocketServer* ws_server = NULL;
26
22 const size_t kMessageBufSize = 2 * 1024; 27 const size_t kMessageBufSize = 2 * 1024;
23 const size_t kHandleBufSize = 64; 28 const size_t kHandleBufSize = 64;
24 const int kDefaultWebSocketPort = 42424; 29 const int kDefaultWebSocketPort = 42424;
25 30
26 void CloseHandles(MojoHandle* handles, size_t count) { 31 void CloseHandles(MojoHandle* handles, size_t count) {
27 for (size_t ix = 0; ix != count; ++count) 32 for (size_t ix = 0; ix != count; ++count)
28 MojoClose(handles[ix]); 33 MojoClose(handles[ix]);
29 } 34 }
30 35
31 // In charge of processing messages that flow over a 36 // In charge of processing messages that flow over a
32 // single message pipe. 37 // single message pipe.
33 class MessageProcessor : 38 class MessageProcessor :
34 public base::RefCountedThreadSafe<MessageProcessor> { 39 public base::RefCountedThreadSafe<MessageProcessor> {
35 public: 40 public:
36 41
37 MessageProcessor() 42 MessageProcessor(base::MessageLoopProxy* control_loop_proxy)
38 : last_result_(MOJO_RESULT_OK), 43 : last_result_(MOJO_RESULT_OK),
39 bytes_transfered_(0) { 44 bytes_transfered_(0),
45 control_loop_proxy_(control_loop_proxy) {
40 46
41 message_count_[0] = 0; 47 message_count_[0] = 0;
42 message_count_[1] = 0; 48 message_count_[1] = 0;
43 handle_count_[0] = 0; 49 handle_count_[0] = 0;
44 handle_count_[1] = 0; 50 handle_count_[1] = 0;
45 } 51 }
46 52
47 void Start(mojo::ScopedMessagePipeHandle client, 53 void Start(mojo::ScopedMessagePipeHandle client,
48 mojo::ScopedMessagePipeHandle interceptor) { 54 mojo::ScopedMessagePipeHandle interceptor,
55 const GURL& url) {
49 std::vector<mojo::MessagePipeHandle> pipes; 56 std::vector<mojo::MessagePipeHandle> pipes;
50 pipes.push_back(client.get()); 57 pipes.push_back(client.get());
51 pipes.push_back(interceptor.get()); 58 pipes.push_back(interceptor.get());
52 std::vector<MojoHandleSignals> handle_signals; 59 std::vector<MojoHandleSignals> handle_signals;
53 handle_signals.push_back(MOJO_HANDLE_SIGNAL_READABLE); 60 handle_signals.push_back(MOJO_HANDLE_SIGNAL_READABLE);
54 handle_signals.push_back(MOJO_HANDLE_SIGNAL_READABLE); 61 handle_signals.push_back(MOJO_HANDLE_SIGNAL_READABLE);
55 62
56 scoped_ptr<char[]> mbuf(new char[kMessageBufSize]); 63 scoped_ptr<char[]> mbuf(new char[kMessageBufSize]);
57 scoped_ptr<MojoHandle[]> hbuf(new MojoHandle[kHandleBufSize]); 64 scoped_ptr<MojoHandle[]> hbuf(new MojoHandle[kHandleBufSize]);
58 65
(...skipping 22 matching lines...) Expand all
81 88
82 if (!bytes_read && !handles_read) 89 if (!bytes_read && !handles_read)
83 continue; 90 continue;
84 91
85 if (handles_read) 92 if (handles_read)
86 handle_count_[r] += handles_read; 93 handle_count_[r] += handles_read;
87 94
88 ++message_count_[r]; 95 ++message_count_[r];
89 bytes_transfered_ += bytes_read; 96 bytes_transfered_ += bytes_read;
90 97
98 LogMessageInfo(mbuf.get(), url);
99
91 mojo::MessagePipeHandle write_handle = (r == 0) ? pipes[1] : pipes[0]; 100 mojo::MessagePipeHandle write_handle = (r == 0) ? pipes[1] : pipes[0];
92 if (!CheckResult(Wait(write_handle, 101 if (!CheckResult(Wait(write_handle,
93 MOJO_HANDLE_SIGNAL_WRITABLE, 102 MOJO_HANDLE_SIGNAL_WRITABLE,
94 MOJO_DEADLINE_INDEFINITE))) 103 MOJO_DEADLINE_INDEFINITE)))
95 break; 104 break;
96 105
97 if (!CheckResult(WriteMessageRaw(write_handle, 106 if (!CheckResult(WriteMessageRaw(write_handle,
98 mbuf.get(), bytes_read, 107 mbuf.get(), bytes_read,
99 hbuf.get(), handles_read, 108 hbuf.get(), handles_read,
100 MOJO_WRITE_MESSAGE_FLAG_NONE))) { 109 MOJO_WRITE_MESSAGE_FLAG_NONE))) {
101 // On failure we own the handles. For now just close them. 110 // On failure we own the handles. For now just close them.
102 if (handles_read) 111 if (handles_read)
103 CloseHandles(hbuf.get(), handles_read); 112 CloseHandles(hbuf.get(), handles_read);
104 break; 113 break;
105 } 114 }
106 } 115 }
107 } 116 }
108 117
109 private: 118 private:
110 friend class base::RefCountedThreadSafe<MessageProcessor>; 119 friend class base::RefCountedThreadSafe<MessageProcessor>;
111 virtual ~MessageProcessor() {} 120 virtual ~MessageProcessor() {}
112 121
113 bool CheckResult(MojoResult mr) { 122 bool CheckResult(MojoResult mr) {
114 if (mr == MOJO_RESULT_OK) 123 if (mr == MOJO_RESULT_OK)
115 return true; 124 return true;
116 last_result_ = mr; 125 last_result_ = mr;
117 return false; 126 return false;
118 } 127 }
119 128
129 void LogMessageInfo(void* data, const GURL& url) {
130 mojo::MojoMessageData* message_data =
131 reinterpret_cast<mojo::MojoMessageData*>(data);
132 control_loop_proxy_->PostTask(
133 FROM_HERE,
134 base::Bind(&spy::WebSocketServer::LogMessageInfo,
135 base::Unretained(ws_server),
136 message_data->header, url, base::Time::Now()));
137 }
138
120 MojoResult last_result_; 139 MojoResult last_result_;
121 uint32_t bytes_transfered_; 140 uint32_t bytes_transfered_;
122 uint32_t message_count_[2]; 141 uint32_t message_count_[2];
123 uint32_t handle_count_[2]; 142 uint32_t handle_count_[2];
143 scoped_refptr<base::MessageLoopProxy> control_loop_proxy_;
124 }; 144 };
125 145
126 // In charge of intercepting access to the service manager. 146 // In charge of intercepting access to the service manager.
127 class SpyInterceptor : public mojo::ServiceManager::Interceptor { 147 class SpyInterceptor : public mojo::ServiceManager::Interceptor {
148 public:
149 SpyInterceptor(base::MessageLoopProxy* control_loop_proxy)
150 : control_loop_proxy_(control_loop_proxy) {}
151
128 private: 152 private:
129 virtual mojo::ScopedMessagePipeHandle OnConnectToClient( 153 virtual mojo::ScopedMessagePipeHandle OnConnectToClient(
130 const GURL& url, mojo::ScopedMessagePipeHandle real_client) OVERRIDE { 154 const GURL& url, mojo::ScopedMessagePipeHandle real_client) OVERRIDE {
131 if (!MustIntercept(url)) 155 if (!MustIntercept(url))
132 return real_client.Pass(); 156 return real_client.Pass();
133 157
134 // You can get an invalid handle if the app (or service) is 158 // You can get an invalid handle if the app (or service) is
135 // created by unconventional means, for example the command line. 159 // created by unconventional means, for example the command line.
136 if (!real_client.is_valid()) 160 if (!real_client.is_valid())
137 return real_client.Pass(); 161 return real_client.Pass();
138 162
139 mojo::ScopedMessagePipeHandle faux_client; 163 mojo::ScopedMessagePipeHandle faux_client;
140 mojo::ScopedMessagePipeHandle interceptor; 164 mojo::ScopedMessagePipeHandle interceptor;
141 CreateMessagePipe(NULL, &faux_client, &interceptor); 165 CreateMessagePipe(NULL, &faux_client, &interceptor);
142 166
143 scoped_refptr<MessageProcessor> processor = new MessageProcessor(); 167 scoped_refptr<MessageProcessor> processor = new MessageProcessor(
168 control_loop_proxy_);
144 base::WorkerPool::PostTask( 169 base::WorkerPool::PostTask(
145 FROM_HERE, 170 FROM_HERE,
146 base::Bind(&MessageProcessor::Start, 171 base::Bind(&MessageProcessor::Start,
147 processor, 172 processor,
148 base::Passed(&real_client), base::Passed(&interceptor)), 173 base::Passed(&real_client), base::Passed(&interceptor),
174 url),
149 true); 175 true);
150 176
151 return faux_client.Pass(); 177 return faux_client.Pass();
152 } 178 }
153 179
154 bool MustIntercept(const GURL& url) { 180 bool MustIntercept(const GURL& url) {
155 // TODO(cpu): manage who and when to intercept. 181 // TODO(cpu): manage who and when to intercept.
156 return true; 182 return true;
157 } 183 }
184
185 scoped_refptr<base::MessageLoopProxy> control_loop_proxy_;
158 }; 186 };
159 187
160 spy::WebSocketServer* ws_server = NULL;
161
162 void StartServer(int port) { 188 void StartServer(int port) {
163 // TODO(cpu) figure out lifetime of the server. See Spy() dtor. 189 // TODO(cpu) figure out lifetime of the server. See Spy() dtor.
164 ws_server = new spy::WebSocketServer(port); 190 ws_server = new spy::WebSocketServer(port);
165 ws_server->Start(); 191 ws_server->Start();
166 } 192 }
167 193
168 struct SpyOptions { 194 struct SpyOptions {
169 int websocket_port; 195 int websocket_port;
170 196
171 SpyOptions() 197 SpyOptions()
(...skipping 25 matching lines...) Expand all
197 Spy::Spy(mojo::ServiceManager* service_manager, const std::string& options) { 223 Spy::Spy(mojo::ServiceManager* service_manager, const std::string& options) {
198 SpyOptions spy_options = ProcessOptions(options); 224 SpyOptions spy_options = ProcessOptions(options);
199 // Start the tread what will accept commands from the frontend. 225 // Start the tread what will accept commands from the frontend.
200 control_thread_.reset(new base::Thread("mojo_spy_control_thread")); 226 control_thread_.reset(new base::Thread("mojo_spy_control_thread"));
201 base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0); 227 base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
202 control_thread_->StartWithOptions(thread_options); 228 control_thread_->StartWithOptions(thread_options);
203 control_thread_->message_loop_proxy()->PostTask( 229 control_thread_->message_loop_proxy()->PostTask(
204 FROM_HERE, base::Bind(&StartServer, spy_options.websocket_port)); 230 FROM_HERE, base::Bind(&StartServer, spy_options.websocket_port));
205 231
206 // Start intercepting mojo services. 232 // Start intercepting mojo services.
207 service_manager->SetInterceptor(new SpyInterceptor()); 233 service_manager->SetInterceptor(new SpyInterceptor(
234 control_thread_->message_loop_proxy()));
208 } 235 }
209 236
210 Spy::~Spy(){ 237 Spy::~Spy(){
211 // TODO(cpu): Do not leak the interceptor. Lifetime between the 238 // TODO(cpu): Do not leak the interceptor. Lifetime between the
212 // service_manager and the spy is still unclear hence the leak. 239 // service_manager and the spy is still unclear hence the leak.
213 } 240 }
214 241
215 } // namespace mojo 242 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/spy/common.h ('k') | mojo/spy/websocket_server.h » ('j') | mojo/spy/websocket_server.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698