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

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

Issue 225203002: Mojo Spy core first cut (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: gcc fix Created 6 years, 8 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
« no previous file with comments | « mojo/spy/spy.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "mojo/spy/spy.h"
6
7 #include "base/bind.h"
8 #include "base/compiler_specific.h"
9 #include "base/location.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/threading/worker_pool.h"
12
13 #include "mojo/public/cpp/system/core.h"
14 #include "mojo/service_manager/service_manager.h"
15
16 namespace {
17
18 const size_t kMessageBufSize = 2 * 1024;
19 const size_t kHandleBufSize = 64;
20
21 // In charge of processing messages that flow over a
22 // single message pipe.
23 class MessageProcessor :
24 public base::RefCountedThreadSafe<MessageProcessor> {
25 public:
26
27 MessageProcessor()
28 : last_result_(MOJO_RESULT_OK),
29 bytes_transfered_(0) {
30
31 message_count_[0] = 0;
32 message_count_[1] = 0;
33 handle_count_[0] = 0;
34 handle_count_[1] = 0;
35 }
36
37 void Start(mojo::ScopedMessagePipeHandle client,
38 mojo::ScopedMessagePipeHandle interceptor) {
39 std::vector<mojo::MessagePipeHandle> pipes;
40 pipes.push_back(client.get());
41 pipes.push_back(interceptor.get());
42 std::vector<MojoWaitFlags> wait_flags;
43 wait_flags.push_back(MOJO_WAIT_FLAG_READABLE);
44 wait_flags.push_back(MOJO_WAIT_FLAG_READABLE);
45
46 scoped_ptr<char> mbuf(new char[kMessageBufSize]);
47 scoped_ptr<MojoHandle> hbuf(new MojoHandle[kHandleBufSize]);
48
49 // Main processing loop:
50 // 1- Wait for an endpoint to have a message.
51 // 2- Read the message
52 // 3- Log data
53 // 4- Wait until the opposite port is ready for writting
54 // 4- Write the message to opposite port.
55
56 for (;;) {
57 int r = WaitMany(pipes, wait_flags, MOJO_DEADLINE_INDEFINITE);
58 if ((r < 0) || (r > 1)) {
59 last_result_ = r;
60 break;
61 }
62
63 uint32_t bytes_read = kMessageBufSize;
64 uint32_t handles_read = kHandleBufSize;
65
66 if (!CheckResult(ReadMessageRaw(pipes[r],
67 mbuf.get(), &bytes_read,
68 hbuf.get(), &handles_read,
69 MOJO_READ_MESSAGE_FLAG_NONE)))
70 break;
71
72 if (!bytes_read && !handles_read)
73 continue;
74
75 if (handles_read)
76 handle_count_[r] += handles_read;
77
78 ++message_count_[r];
79 bytes_transfered_ += bytes_read;
80
81 mojo::MessagePipeHandle write_handle = (r == 0) ? pipes[1] : pipes[0];
82 if (!CheckResult(Wait(write_handle,
83 MOJO_WAIT_FLAG_WRITABLE,
84 MOJO_DEADLINE_INDEFINITE)))
85 break;
86
87 if (!CheckResult(WriteMessageRaw(write_handle,
88 mbuf.get(), bytes_read,
89 hbuf.get(), handles_read,
90 MOJO_WRITE_MESSAGE_FLAG_NONE)))
91 break;
92 }
93
94 }
95
96 private:
97 friend class base::RefCountedThreadSafe<MessageProcessor>;
98 virtual ~MessageProcessor() {}
99
100 bool CheckResult(MojoResult mr) {
101 if (mr == MOJO_RESULT_OK)
102 return true;
103 last_result_ = mr;
104 return false;
105 }
106
107 MojoResult last_result_;
108 uint32_t bytes_transfered_;
109 uint32_t message_count_[2];
110 uint32_t handle_count_[2];
111 };
112
113 // In charge of intercepting access to the service manager.
114 class SpyInterceptor : public mojo::ServiceManager::Interceptor {
115 private:
116 virtual mojo::ScopedMessagePipeHandle OnConnectToClient(
117 const GURL& url, mojo::ScopedMessagePipeHandle real_client) OVERRIDE {
118 if (!MustIntercept(url))
119 return real_client.Pass();
120
121 // You can get an invalid handle if the app (or service) is
122 // by unconventional means, for example the command line.
123 if (!real_client.is_valid())
124 return real_client.Pass();
125
126 mojo::ScopedMessagePipeHandle faux_client;
127 mojo::ScopedMessagePipeHandle interceptor;
128 CreateMessagePipe(&faux_client, &interceptor);
129
130 scoped_refptr<MessageProcessor> processor = new MessageProcessor();
131 base::WorkerPool::PostTask(
132 FROM_HERE,
133 base::Bind(&MessageProcessor::Start,
134 processor,
135 base::Passed(&real_client), base::Passed(&interceptor)),
136 true);
137
138 return faux_client.Pass();
139 }
140
141 bool MustIntercept(const GURL& url) {
142 // TODO(cpu): manage who and when to intercept.
143 return true;
144 }
145 };
146
147 } // namespace
148
149 namespace mojo {
150
151 Spy::Spy(mojo::ServiceManager* service_manager, const std::string& options) {
152 service_manager->SetInterceptor(new SpyInterceptor());
153 }
154
155 Spy::~Spy(){
156 // TODO(cpu): Do not leak the interceptor. Lifetime between the
157 // service_manager and the spy is still unclear hence the leak.
158 }
159
160 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/spy/spy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698