-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmojo_handler.cc
170 lines (136 loc) · 5.52 KB
/
mojo_handler.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cups_proxy/mojo_handler.h"
#include <map>
#include <utility>
#include <base/strings/string_util.h>
#include <chromeos/dbus/service_constants.h>
namespace cups_proxy {
namespace {
// Minimum proxy.mojom CupsProxier interface version required.
const int kMinVersionRequired = 1;
std::string ShowHeaders(const IppHeaders& headers) {
std::vector<std::string> ret;
for (const auto& header : headers) {
ret.push_back(base::JoinString({header->key, header->value}, " = "));
}
return base::JoinString(ret, ", ");
}
std::string ShowBody(const IppBody& body) {
std::string s(body.begin(), body.end());
std::replace_if(
s.begin(), s.end(), [](char c) -> bool { return c == '\0'; }, '|');
return s;
}
IppHeaders ConvertHeadersToMojom(
const std::map<std::string, std::string>& headers) {
IppHeaders ret;
for (const auto& header : headers) {
auto mojom_header = mojom::HttpHeader::New();
mojom_header->key = header.first;
mojom_header->value = header.second;
ret.push_back(std::move(mojom_header));
}
return ret;
}
} // namespace
MojoHandler::MojoHandler() : mojo_thread_("cups_proxy_mojo_thread") {}
MojoHandler::~MojoHandler() {
// The message pipe is bound on the mojo thread, and it has to be closed on
// the same thread which it is bound, so we close the message pipe by calling
// .reset() on the mojo thread.
mojo_task_runner_->PostTask(FROM_HERE,
base::Bind(&mojom::CupsProxierPtr::reset,
base::Unretained(&chrome_proxy_)));
mojo_thread_.Stop();
}
bool MojoHandler::StartThread() {
if (!mojo_thread_.Start()) {
return false;
}
mojo_task_runner_ = mojo_thread_.task_runner();
return true;
}
void MojoHandler::SetupMojoPipe(base::ScopedFD fd,
base::Closure error_handler) {
mojo::IncomingInvitation invitation = mojo::IncomingInvitation::Accept(
mojo::PlatformChannelEndpoint(mojo::PlatformHandle(std::move(fd))));
mojo_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&MojoHandler::SetupMojoPipeOnThread,
base::Unretained(this), std::move(error_handler),
std::move(invitation)));
}
void MojoHandler::SetupMojoPipeOnThread(base::Closure error_handler,
mojo::IncomingInvitation invitation) {
DCHECK(mojo_task_runner_->BelongsToCurrentThread());
DCHECK(!chrome_proxy_);
// Bind primordial message pipe to a CupsProxyService implementation.
chrome_proxy_.Bind(mojom::CupsProxierPtrInfo(
invitation.ExtractMessagePipe(
printing::kBootstrapMojoConnectionChannelToken),
0u /* version */));
chrome_proxy_.set_connection_error_handler(std::move(error_handler));
chrome_proxy_.RequireVersion(kMinVersionRequired);
for (auto& callback : queued_requests_) {
mojo_task_runner_->PostTask(FROM_HERE, std::move(callback));
}
queued_requests_.clear();
LOG(INFO) << "Mojo connection bootstrapped.";
}
bool MojoHandler::IsInitialized() {
return chrome_proxy_.is_bound();
}
void MojoHandler::ProxyRequestOnThread(
const std::string& method,
const std::string& url,
const std::string& version,
IppHeaders headers,
const IppBody& body,
mojom::CupsProxier::ProxyRequestCallback callback) {
DCHECK(mojo_task_runner_->BelongsToCurrentThread());
if (chrome_proxy_) {
chrome_proxy_->ProxyRequest(method, url, version, std::move(headers), body,
std::move(callback));
} else {
LOG(INFO) << "Chrome Proxy is not up yet, queuing the request.";
queued_requests_.push_back(base::BindOnce(
&MojoHandler::ProxyRequestOnThread, base::Unretained(this), method, url,
version, std::move(headers), body, std::move(callback)));
}
}
IppResponse MojoHandler::ProxyRequestSync(const MHDHttpRequest& request) {
DCHECK(!mojo_task_runner_->BelongsToCurrentThread());
const std::string& url = request.url();
const std::string& method = request.method();
const std::string& version = request.version();
IppHeaders headers = ConvertHeadersToMojom(request.headers());
const IppBody& body = request.body();
IppResponse response;
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
auto callback = base::BindOnce(
[](IppResponse* response, base::WaitableEvent* event, IppHeaders headers,
const IppBody& ipp_message, int http_status_code) {
response->headers = std::move(headers);
response->body = ipp_message;
response->http_status_code = http_status_code;
event->Signal();
},
&response, &event);
DVLOG(2) << "url = " << url << ", method = " << method
<< ", version = " << version;
DVLOG(2) << "headers = " << ShowHeaders(headers);
DVLOG(2) << "body = " << ShowBody(body);
mojo_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&MojoHandler::ProxyRequestOnThread,
base::Unretained(this), method, url, version,
std::move(headers), body, std::move(callback)));
event.Wait();
DVLOG(2) << "response code = " << response.http_status_code;
DVLOG(2) << "response headers = " << ShowHeaders(response.headers);
DVLOG(2) << "response body = " << ShowBody(response.body);
return response;
}
} // namespace cups_proxy