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

Side by Side Diff: chrome/browser/policy/test_request_interceptor.cc

Issue 12209070: Fix cloud policy duplicate registrations issue. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 10 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 | « chrome/browser/policy/test_request_interceptor.h ('k') | chrome/browser/policy/test_utils.h » ('j') | 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 (c) 2013 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/browser/policy/test_request_interceptor.h"
6
7 #include <limits>
8 #include <queue>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/test/test_utils.h"
15 #include "googleurl/src/gurl.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/upload_bytes_element_reader.h"
18 #include "net/base/upload_data_stream.h"
19 #include "net/base/upload_element_reader.h"
20 #include "net/url_request/url_request_error_job.h"
21 #include "net/url_request/url_request_filter.h"
22 #include "net/url_request/url_request_job_factory.h"
23 #include "net/url_request/url_request_test_job.h"
24
25 namespace em = enterprise_management;
26
27 namespace policy {
28
29 namespace {
30
31 // Helper to execute a |task| on IO, and return only after it has completed.
32 void PostToIOAndWait(const base::Closure& task) {
33 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, task);
34 content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
35 }
36
37 // Helper callback for jobs that should fail with a network |error|.
38 net::URLRequestJob* ErrorJobCallback(int error,
39 net::URLRequest* request,
40 net::NetworkDelegate* network_delegate) {
41 return new net::URLRequestErrorJob(request, network_delegate, error);
42 }
43
44 // Helper callback for jobs that should fail with a 400 HTTP error.
45 net::URLRequestJob* BadRequestJobCallback(
46 net::URLRequest* request,
47 net::NetworkDelegate* network_delegate) {
48 static const char kBadHeaders[] =
49 "HTTP/1.1 400 Bad request\0"
50 "Content-type: application/protobuf\0"
51 "\0";
52 std::string headers(kBadHeaders, arraysize(kBadHeaders));
53 return new net::URLRequestTestJob(
54 request, network_delegate, headers, std::string(), true);
55 }
56
57 // Parses the upload data in |request| into |request_msg|, and validates the
58 // request. The query string in the URL must contain the |expected_type| for
59 // the "request" parameter. Returns true if all checks succeeded, and the
60 // request data has been parsed into |request_msg|.
61 bool ValidRequest(net::URLRequest* request,
62 const std::string& expected_type,
63 em::DeviceManagementRequest* request_msg) {
64 if (request->method() != "POST")
65 return false;
66 std::string spec = request->url().spec();
67 if (spec.find("request=" + expected_type) == std::string::npos)
68 return false;
69
70 // This assumes that the payload data was set from a single string. In that
71 // case the UploadDataStream has a single UploadBytesElementReader with the
72 // data in memory.
73 const net::UploadDataStream* stream = request->get_upload();
74 if (!stream)
75 return false;
76 const ScopedVector<net::UploadElementReader>& readers =
77 stream->element_readers();
78 if (readers.size() != 1u)
79 return false;
80 const net::UploadBytesElementReader* reader = readers[0]->AsBytesReader();
81 if (!reader)
82 return false;
83 std::string data(reader->bytes(), reader->length());
84 if (!request_msg->ParseFromString(data))
85 return false;
86
87 return true;
88 }
89
90 // Helper callback for register jobs that should suceed. Validates the request
91 // parameters and returns an appropriate response job. If |expect_reregister|
92 // is true then the reregister flag must be set in the DeviceRegisterRequest
93 // protobuf.
94 net::URLRequestJob* RegisterJobCallback(
95 em::DeviceRegisterRequest::Type expected_type,
96 bool expect_reregister,
97 net::URLRequest* request,
98 net::NetworkDelegate* network_delegate) {
99 em::DeviceManagementRequest request_msg;
100 if (!ValidRequest(request, "register", &request_msg))
101 return BadRequestJobCallback(request, network_delegate);
102
103 if (!request_msg.has_register_request() ||
104 request_msg.has_unregister_request() ||
105 request_msg.has_policy_request() ||
106 request_msg.has_device_status_report_request() ||
107 request_msg.has_session_status_report_request() ||
108 request_msg.has_auto_enrollment_request()) {
109 return BadRequestJobCallback(request, network_delegate);
110 }
111
112 const em::DeviceRegisterRequest& register_request =
113 request_msg.register_request();
114 if (expect_reregister &&
115 (!register_request.has_reregister() || !register_request.reregister())) {
116 return BadRequestJobCallback(request, network_delegate);
117 } else if (!expect_reregister &&
118 register_request.has_reregister() &&
119 register_request.reregister()) {
120 return BadRequestJobCallback(request, network_delegate);
121 }
122
123 if (!register_request.has_type() || register_request.type() != expected_type)
124 return BadRequestJobCallback(request, network_delegate);
125
126 em::DeviceManagementResponse response;
127 em::DeviceRegisterResponse* register_response =
128 response.mutable_register_response();
129 register_response->set_device_management_token("s3cr3t70k3n");
130 std::string data;
131 response.SerializeToString(&data);
132
133 static const char kGoodHeaders[] =
134 "HTTP/1.1 200 OK\0"
135 "Content-type: application/protobuf\0"
136 "\0";
137 std::string headers(kGoodHeaders, arraysize(kGoodHeaders));
138 return new net::URLRequestTestJob(
139 request, network_delegate, headers, data, true);
140 }
141
142 } // namespace
143
144 class TestRequestInterceptor::Delegate
145 : public net::URLRequestJobFactory::ProtocolHandler {
146 public:
147 explicit Delegate(const std::string& hostname);
148 virtual ~Delegate();
149
150 // ProtocolHandler implementation:
151 virtual net::URLRequestJob* MaybeCreateJob(
152 net::URLRequest* request,
153 net::NetworkDelegate* network_delegate) const OVERRIDE;
154
155 void GetPendingSize(size_t* pending_size) const;
156 void PushJobCallback(const JobCallback& callback);
157
158 private:
159 const std::string hostname_;
160
161 // The queue of pending callbacks. 'mutable' because MaybeCreateJob() is a
162 // const method; it can't reenter though, because it runs exclusively on
163 // the IO thread.
164 mutable std::queue<JobCallback> pending_job_callbacks_;
165 };
166
167 TestRequestInterceptor::Delegate::Delegate(const std::string& hostname)
168 : hostname_(hostname) {}
169
170 TestRequestInterceptor::Delegate::~Delegate() {}
171
172 net::URLRequestJob* TestRequestInterceptor::Delegate::MaybeCreateJob(
173 net::URLRequest* request,
174 net::NetworkDelegate* network_delegate) const {
175 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
176
177 if (request->url().host() != hostname_) {
178 // Reject requests to other servers.
179 return ErrorJobCallback(
180 net::ERR_CONNECTION_REFUSED, request, network_delegate);
181 }
182
183 if (pending_job_callbacks_.empty()) {
184 // Reject dmserver requests by default.
185 return BadRequestJobCallback(request, network_delegate);
186 }
187
188 JobCallback callback = pending_job_callbacks_.front();
189 pending_job_callbacks_.pop();
190 return callback.Run(request, network_delegate);
191 }
192
193 void TestRequestInterceptor::Delegate::GetPendingSize(
194 size_t* pending_size) const {
195 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
196 *pending_size = pending_job_callbacks_.size();
197 }
198
199 void TestRequestInterceptor::Delegate::PushJobCallback(
200 const JobCallback& callback) {
201 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
202 pending_job_callbacks_.push(callback);
203 }
204
205 TestRequestInterceptor::TestRequestInterceptor(const std::string& hostname)
206 : hostname_(hostname) {
207 delegate_ = new Delegate(hostname_);
208 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> handler(delegate_);
209 PostToIOAndWait(
210 base::Bind(&net::URLRequestFilter::AddHostnameProtocolHandler,
211 base::Unretained(net::URLRequestFilter::GetInstance()),
212 "http", hostname_, base::Passed(&handler)));
213 }
214
215 TestRequestInterceptor::~TestRequestInterceptor() {
216 // RemoveHostnameHandler() destroys the |delegate_|, which is owned by
217 // the URLRequestFilter.
218 delegate_ = NULL;
219 PostToIOAndWait(
220 base::Bind(&net::URLRequestFilter::RemoveHostnameHandler,
221 base::Unretained(net::URLRequestFilter::GetInstance()),
222 "http", hostname_));
223 }
224
225 size_t TestRequestInterceptor::GetPendingSize() const {
226 size_t pending_size = std::numeric_limits<size_t>::max();
227 PostToIOAndWait(base::Bind(&Delegate::GetPendingSize,
228 base::Unretained(delegate_),
229 &pending_size));
230 return pending_size;
231 }
232
233 void TestRequestInterceptor::PushJobCallback(const JobCallback& callback) {
234 PostToIOAndWait(base::Bind(&Delegate::PushJobCallback,
235 base::Unretained(delegate_),
236 callback));
237 }
238
239 // static
240 TestRequestInterceptor::JobCallback TestRequestInterceptor::ErrorJob(
241 int error) {
242 return base::Bind(&ErrorJobCallback, error);
243 }
244
245 // static
246 TestRequestInterceptor::JobCallback TestRequestInterceptor::BadRequestJob() {
247 return base::Bind(&BadRequestJobCallback);
248 }
249
250 // static
251 TestRequestInterceptor::JobCallback TestRequestInterceptor::RegisterJob(
252 em::DeviceRegisterRequest::Type expected_type,
253 bool expect_reregister) {
254 return base::Bind(&RegisterJobCallback, expected_type, expect_reregister);
255 }
256
257 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/test_request_interceptor.h ('k') | chrome/browser/policy/test_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698