• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 <vector>
6 
7 #include "base/message_loop.h"
8 #include "base/string_split.h"
9 #include "chrome/browser/policy/device_management_backend_impl.h"
10 #include "chrome/browser/policy/device_management_backend_mock.h"
11 #include "chrome/browser/policy/device_management_service.h"
12 #include "chrome/browser/policy/proto/device_management_constants.h"
13 #include "chrome/common/net/test_url_fetcher_factory.h"
14 #include "chrome/test/test_url_request_context_getter.h"
15 #include "content/browser/browser_thread.h"
16 #include "net/base/escape.h"
17 #include "net/url_request/url_request_status.h"
18 #include "net/url_request/url_request_test_util.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 using testing::_;
23 using testing::IgnoreResult;
24 using testing::InvokeWithoutArgs;
25 
26 namespace policy {
27 
28 const char kServiceUrl[] = "https://example.com/management_service";
29 
30 // Encoded empty response messages for testing the error code paths.
31 const char kResponseEmpty[] = "\x08\x00";
32 
33 #define PROTO_STRING(name) (std::string(name, arraysize(name) - 1))
34 
35 // Some helper constants.
36 const char kAuthToken[] = "auth-token";
37 const char kDMToken[] = "device-management-token";
38 const char kDeviceId[] = "device-id";
39 
40 // Unit tests for the device management policy service. The tests are run
41 // against a TestURLFetcherFactory that is used to short-circuit the request
42 // without calling into the actual network stack.
43 template<typename TESTBASE>
44 class DeviceManagementServiceTestBase : public TESTBASE {
45  protected:
DeviceManagementServiceTestBase()46   DeviceManagementServiceTestBase()
47       : request_context_(new TestURLRequestContextGetter()),
48         io_thread_(BrowserThread::IO, &loop_) {
49     ResetService();
50     service_->Initialize(request_context_.get());
51   }
52 
SetUp()53   virtual void SetUp() {
54     URLFetcher::set_factory(&factory_);
55   }
56 
TearDown()57   virtual void TearDown() {
58     URLFetcher::set_factory(NULL);
59     backend_.reset();
60     service_.reset();
61     request_context_ = NULL;
62     loop_.RunAllPending();
63   }
64 
ResetService()65   void ResetService() {
66     backend_.reset();
67     service_.reset(new DeviceManagementService(kServiceUrl));
68     backend_.reset(service_->CreateBackend());
69   }
70 
71   TestURLFetcherFactory factory_;
72   scoped_refptr<TestURLRequestContextGetter> request_context_;
73   scoped_ptr<DeviceManagementService> service_;
74   scoped_ptr<DeviceManagementBackend> backend_;
75 
76  private:
77   MessageLoopForUI loop_;
78   BrowserThread io_thread_;
79 };
80 
81 struct FailedRequestParams {
FailedRequestParamspolicy::FailedRequestParams82   FailedRequestParams(DeviceManagementBackend::ErrorCode expected_error,
83                       net::URLRequestStatus::Status request_status,
84                       int http_status,
85                       const std::string& response)
86       : expected_error_(expected_error),
87         request_status_(request_status, 0),
88         http_status_(http_status),
89         response_(response) {}
90 
91   DeviceManagementBackend::ErrorCode expected_error_;
92   net::URLRequestStatus request_status_;
93   int http_status_;
94   std::string response_;
95 };
96 
97 // A parameterized test case for erroneous response situations, they're mostly
98 // the same for all kinds of requests.
99 class DeviceManagementServiceFailedRequestTest
100     : public DeviceManagementServiceTestBase<
101           testing::TestWithParam<FailedRequestParams> > {
102 };
103 
TEST_P(DeviceManagementServiceFailedRequestTest,RegisterRequest)104 TEST_P(DeviceManagementServiceFailedRequestTest, RegisterRequest) {
105   DeviceRegisterResponseDelegateMock mock;
106   EXPECT_CALL(mock, OnError(GetParam().expected_error_));
107   em::DeviceRegisterRequest request;
108   backend_->ProcessRegisterRequest(kAuthToken, kDeviceId, request, &mock);
109   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
110   ASSERT_TRUE(fetcher);
111 
112   fetcher->delegate()->OnURLFetchComplete(fetcher,
113                                           GURL(kServiceUrl),
114                                           GetParam().request_status_,
115                                           GetParam().http_status_,
116                                           ResponseCookies(),
117                                           GetParam().response_);
118 }
119 
TEST_P(DeviceManagementServiceFailedRequestTest,UnregisterRequest)120 TEST_P(DeviceManagementServiceFailedRequestTest, UnregisterRequest) {
121   DeviceUnregisterResponseDelegateMock mock;
122   EXPECT_CALL(mock, OnError(GetParam().expected_error_));
123   em::DeviceUnregisterRequest request;
124   backend_->ProcessUnregisterRequest(kDMToken, kDeviceId, request, &mock);
125   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
126   ASSERT_TRUE(fetcher);
127 
128   fetcher->delegate()->OnURLFetchComplete(fetcher,
129                                           GURL(kServiceUrl),
130                                           GetParam().request_status_,
131                                           GetParam().http_status_,
132                                           ResponseCookies(),
133                                           GetParam().response_);
134 }
135 
TEST_P(DeviceManagementServiceFailedRequestTest,PolicyRequest)136 TEST_P(DeviceManagementServiceFailedRequestTest, PolicyRequest) {
137   DevicePolicyResponseDelegateMock mock;
138   EXPECT_CALL(mock, OnError(GetParam().expected_error_));
139   em::DevicePolicyRequest request;
140   request.set_policy_scope(kChromePolicyScope);
141   em::DevicePolicySettingRequest* setting_request =
142       request.add_setting_request();
143   setting_request->set_key(kChromeDevicePolicySettingKey);
144   backend_->ProcessPolicyRequest(kDMToken, kDeviceId, request, &mock);
145   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
146   ASSERT_TRUE(fetcher);
147 
148   fetcher->delegate()->OnURLFetchComplete(fetcher,
149                                           GURL(kServiceUrl),
150                                           GetParam().request_status_,
151                                           GetParam().http_status_,
152                                           ResponseCookies(),
153                                           GetParam().response_);
154 }
155 
156 INSTANTIATE_TEST_CASE_P(
157     DeviceManagementServiceFailedRequestTestInstance,
158     DeviceManagementServiceFailedRequestTest,
159     testing::Values(
160         FailedRequestParams(
161             DeviceManagementBackend::kErrorRequestFailed,
162             net::URLRequestStatus::FAILED,
163             200,
164             PROTO_STRING(kResponseEmpty)),
165         FailedRequestParams(
166             DeviceManagementBackend::kErrorHttpStatus,
167             net::URLRequestStatus::SUCCESS,
168             666,
169             PROTO_STRING(kResponseEmpty)),
170         FailedRequestParams(
171             DeviceManagementBackend::kErrorResponseDecoding,
172             net::URLRequestStatus::SUCCESS,
173             200,
174             PROTO_STRING("Not a protobuf.")),
175         FailedRequestParams(
176             DeviceManagementBackend::kErrorServiceManagementNotSupported,
177             net::URLRequestStatus::SUCCESS,
178             403,
179             PROTO_STRING(kResponseEmpty)),
180         FailedRequestParams(
181             DeviceManagementBackend::kErrorServiceDeviceNotFound,
182             net::URLRequestStatus::SUCCESS,
183             901,
184             PROTO_STRING(kResponseEmpty)),
185         FailedRequestParams(
186             DeviceManagementBackend::kErrorServiceManagementTokenInvalid,
187             net::URLRequestStatus::SUCCESS,
188             401,
189             PROTO_STRING(kResponseEmpty)),
190         FailedRequestParams(
191             DeviceManagementBackend::kErrorRequestInvalid,
192             net::URLRequestStatus::SUCCESS,
193             400,
194             PROTO_STRING(kResponseEmpty)),
195         FailedRequestParams(
196             DeviceManagementBackend::kErrorTemporaryUnavailable,
197             net::URLRequestStatus::SUCCESS,
198             404,
199             PROTO_STRING(kResponseEmpty)),
200         FailedRequestParams(
201             DeviceManagementBackend::kErrorServiceActivationPending,
202             net::URLRequestStatus::SUCCESS,
203             491,
204             PROTO_STRING(kResponseEmpty))));
205 
206 // Simple query parameter parser for testing.
207 class QueryParams {
208  public:
QueryParams(const std::string & query)209   explicit QueryParams(const std::string& query) {
210     base::SplitStringIntoKeyValuePairs(query, '=', '&', &params_);
211   }
212 
Check(const std::string & name,const std::string & expected_value)213   bool Check(const std::string& name, const std::string& expected_value) {
214     bool found = false;
215     for (ParamMap::const_iterator i(params_.begin()); i != params_.end(); ++i) {
216       std::string unescaped_name(
217           UnescapeURLComponent(i->first,
218                                UnescapeRule::NORMAL |
219                                UnescapeRule::SPACES |
220                                UnescapeRule::URL_SPECIAL_CHARS |
221                                UnescapeRule::CONTROL_CHARS |
222                                UnescapeRule::REPLACE_PLUS_WITH_SPACE));
223       if (unescaped_name == name) {
224         if (found)
225           return false;
226         found = true;
227         std::string unescaped_value(
228             UnescapeURLComponent(i->second,
229                                  UnescapeRule::NORMAL |
230                                  UnescapeRule::SPACES |
231                                  UnescapeRule::URL_SPECIAL_CHARS |
232                                  UnescapeRule::CONTROL_CHARS |
233                                  UnescapeRule::REPLACE_PLUS_WITH_SPACE));
234         if (unescaped_value != expected_value)
235           return false;
236       }
237     }
238     return found;
239   }
240 
241  private:
242   typedef std::vector<std::pair<std::string, std::string> > ParamMap;
243   ParamMap params_;
244 };
245 
246 class DeviceManagementServiceTest
247     : public DeviceManagementServiceTestBase<testing::Test> {
248  public:
ResetBackend()249   void ResetBackend() {
250     backend_.reset();
251   }
252 
253  protected:
CheckURLAndQueryParams(const GURL & request_url,const std::string & request_type,const std::string & device_id)254   void CheckURLAndQueryParams(const GURL& request_url,
255                               const std::string& request_type,
256                               const std::string& device_id) {
257     const GURL service_url(kServiceUrl);
258     EXPECT_EQ(service_url.scheme(), request_url.scheme());
259     EXPECT_EQ(service_url.host(), request_url.host());
260     EXPECT_EQ(service_url.port(), request_url.port());
261     EXPECT_EQ(service_url.path(), request_url.path());
262 
263     QueryParams query_params(request_url.query());
264     EXPECT_TRUE(query_params.Check(
265         DeviceManagementBackendImpl::kParamRequest, request_type));
266     EXPECT_TRUE(query_params.Check(
267         DeviceManagementBackendImpl::kParamDeviceID, device_id));
268     EXPECT_TRUE(query_params.Check(
269         DeviceManagementBackendImpl::kParamDeviceType,
270         DeviceManagementBackendImpl::kValueDeviceType));
271     EXPECT_TRUE(query_params.Check(
272         DeviceManagementBackendImpl::kParamAppType,
273         DeviceManagementBackendImpl::kValueAppType));
274     EXPECT_TRUE(query_params.Check(
275         DeviceManagementBackendImpl::kParamAgent,
276         DeviceManagementBackendImpl::GetAgentString()));
277   }
278 };
279 
280 MATCHER_P(MessageEquals, reference, "") {
281   std::string reference_data;
282   std::string arg_data;
283   return arg.SerializeToString(&arg_data) &&
284          reference.SerializeToString(&reference_data) &&
285          arg_data == reference_data;
286 }
287 
TEST_F(DeviceManagementServiceTest,RegisterRequest)288 TEST_F(DeviceManagementServiceTest, RegisterRequest) {
289   DeviceRegisterResponseDelegateMock mock;
290   em::DeviceRegisterResponse expected_response;
291   expected_response.set_device_management_token(kDMToken);
292   EXPECT_CALL(mock, HandleRegisterResponse(MessageEquals(expected_response)));
293   em::DeviceRegisterRequest request;
294   backend_->ProcessRegisterRequest(kDMToken, kDeviceId, request, &mock);
295   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
296   ASSERT_TRUE(fetcher);
297 
298   CheckURLAndQueryParams(fetcher->original_url(),
299                          DeviceManagementBackendImpl::kValueRequestRegister,
300                          kDeviceId);
301 
302   em::DeviceManagementRequest expected_request_wrapper;
303   expected_request_wrapper.mutable_register_request()->CopyFrom(request);
304   std::string expected_request_data;
305   ASSERT_TRUE(expected_request_wrapper.SerializeToString(
306       &expected_request_data));
307   EXPECT_EQ(expected_request_data, fetcher->upload_data());
308 
309   // Generate the response.
310   std::string response_data;
311   em::DeviceManagementResponse response_wrapper;
312   response_wrapper.mutable_register_response()->CopyFrom(expected_response);
313   ASSERT_TRUE(response_wrapper.SerializeToString(&response_data));
314   net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
315   fetcher->delegate()->OnURLFetchComplete(fetcher,
316                                           GURL(kServiceUrl),
317                                           status,
318                                           200,
319                                           ResponseCookies(),
320                                           response_data);
321 }
322 
TEST_F(DeviceManagementServiceTest,UnregisterRequest)323 TEST_F(DeviceManagementServiceTest, UnregisterRequest) {
324   DeviceUnregisterResponseDelegateMock mock;
325   em::DeviceUnregisterResponse expected_response;
326   EXPECT_CALL(mock, HandleUnregisterResponse(MessageEquals(expected_response)));
327   em::DeviceUnregisterRequest request;
328   backend_->ProcessUnregisterRequest(kDMToken, kDeviceId, request, &mock);
329   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
330   ASSERT_TRUE(fetcher);
331 
332   // Check the data the fetcher received.
333   const GURL& request_url(fetcher->original_url());
334   const GURL service_url(kServiceUrl);
335   EXPECT_EQ(service_url.scheme(), request_url.scheme());
336   EXPECT_EQ(service_url.host(), request_url.host());
337   EXPECT_EQ(service_url.port(), request_url.port());
338   EXPECT_EQ(service_url.path(), request_url.path());
339 
340   CheckURLAndQueryParams(fetcher->original_url(),
341                          DeviceManagementBackendImpl::kValueRequestUnregister,
342                          kDeviceId);
343 
344   em::DeviceManagementRequest expected_request_wrapper;
345   expected_request_wrapper.mutable_unregister_request()->CopyFrom(request);
346   std::string expected_request_data;
347   ASSERT_TRUE(expected_request_wrapper.SerializeToString(
348       &expected_request_data));
349   EXPECT_EQ(expected_request_data, fetcher->upload_data());
350 
351   // Generate the response.
352   std::string response_data;
353   em::DeviceManagementResponse response_wrapper;
354   response_wrapper.mutable_unregister_response()->CopyFrom(expected_response);
355   ASSERT_TRUE(response_wrapper.SerializeToString(&response_data));
356   net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
357   fetcher->delegate()->OnURLFetchComplete(fetcher,
358                                           GURL(kServiceUrl),
359                                           status,
360                                           200,
361                                           ResponseCookies(),
362                                           response_data);
363 }
364 
TEST_F(DeviceManagementServiceTest,CancelRegisterRequest)365 TEST_F(DeviceManagementServiceTest, CancelRegisterRequest) {
366   DeviceRegisterResponseDelegateMock mock;
367   EXPECT_CALL(mock, HandleRegisterResponse(_)).Times(0);
368   em::DeviceRegisterRequest request;
369   backend_->ProcessRegisterRequest(kAuthToken, kDeviceId, request, &mock);
370   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
371   ASSERT_TRUE(fetcher);
372 
373   // There shouldn't be any callbacks.
374   backend_.reset();
375 }
376 
TEST_F(DeviceManagementServiceTest,CancelUnregisterRequest)377 TEST_F(DeviceManagementServiceTest, CancelUnregisterRequest) {
378   DeviceUnregisterResponseDelegateMock mock;
379   EXPECT_CALL(mock, HandleUnregisterResponse(_)).Times(0);
380   em::DeviceUnregisterRequest request;
381   backend_->ProcessUnregisterRequest(kDMToken, kDeviceId, request, &mock);
382   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
383   ASSERT_TRUE(fetcher);
384 
385   // There shouldn't be any callbacks.
386   backend_.reset();
387 }
388 
TEST_F(DeviceManagementServiceTest,CancelPolicyRequest)389 TEST_F(DeviceManagementServiceTest, CancelPolicyRequest) {
390   DevicePolicyResponseDelegateMock mock;
391   EXPECT_CALL(mock, HandlePolicyResponse(_)).Times(0);
392   em::DevicePolicyRequest request;
393   request.set_policy_scope(kChromePolicyScope);
394   em::DevicePolicySettingRequest* setting_request =
395       request.add_setting_request();
396   setting_request->set_key(kChromeDevicePolicySettingKey);
397   setting_request->set_watermark("stale");
398   backend_->ProcessPolicyRequest(kDMToken, kDeviceId, request, &mock);
399   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
400   ASSERT_TRUE(fetcher);
401 
402   // There shouldn't be any callbacks.
403   backend_.reset();
404 }
405 
TEST_F(DeviceManagementServiceTest,JobQueueing)406 TEST_F(DeviceManagementServiceTest, JobQueueing) {
407   // Start with a non-initialized service.
408   ResetService();
409 
410   // Make a request. We should not see any fetchers being created.
411   DeviceRegisterResponseDelegateMock mock;
412   em::DeviceRegisterResponse expected_response;
413   expected_response.set_device_management_token(kDMToken);
414   EXPECT_CALL(mock, HandleRegisterResponse(MessageEquals(expected_response)));
415   em::DeviceRegisterRequest request;
416   backend_->ProcessRegisterRequest(kAuthToken, kDeviceId, request, &mock);
417   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
418   ASSERT_FALSE(fetcher);
419 
420   // Now initialize the service. That should start the job.
421   service_->Initialize(request_context_.get());
422   fetcher = factory_.GetFetcherByID(0);
423   ASSERT_TRUE(fetcher);
424   factory_.RemoveFetcherFromMap(0);
425 
426   // Check that the request is processed as expected.
427   std::string response_data;
428   em::DeviceManagementResponse response_wrapper;
429   response_wrapper.mutable_register_response()->CopyFrom(expected_response);
430   ASSERT_TRUE(response_wrapper.SerializeToString(&response_data));
431   net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
432   fetcher->delegate()->OnURLFetchComplete(fetcher,
433                                           GURL(kServiceUrl),
434                                           status,
435                                           200,
436                                           ResponseCookies(),
437                                           response_data);
438 }
439 
TEST_F(DeviceManagementServiceTest,CancelRequestAfterShutdown)440 TEST_F(DeviceManagementServiceTest, CancelRequestAfterShutdown) {
441   DevicePolicyResponseDelegateMock mock;
442   EXPECT_CALL(mock, HandlePolicyResponse(_)).Times(0);
443   em::DevicePolicyRequest request;
444   request.set_policy_scope(kChromePolicyScope);
445   em::DevicePolicySettingRequest* setting_request =
446       request.add_setting_request();
447   setting_request->set_key(kChromeDevicePolicySettingKey);
448   setting_request->set_watermark("stale");
449   backend_->ProcessPolicyRequest(kDMToken, kDeviceId, request, &mock);
450   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
451   ASSERT_TRUE(fetcher);
452 
453   // Shutdown the service and cancel the job afterwards.
454   service_->Shutdown();
455   backend_.reset();
456 }
457 
TEST_F(DeviceManagementServiceTest,CancelDuringCallback)458 TEST_F(DeviceManagementServiceTest, CancelDuringCallback) {
459   // Make a request.
460   DeviceRegisterResponseDelegateMock mock;
461   EXPECT_CALL(mock, OnError(_))
462       .WillOnce(InvokeWithoutArgs(this,
463                                   &DeviceManagementServiceTest::ResetBackend))
464       .RetiresOnSaturation();
465   em::DeviceRegisterRequest request;
466   backend_->ProcessRegisterRequest(kAuthToken, kDeviceId, request, &mock);
467   TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
468   ASSERT_TRUE(fetcher);
469 
470   // Generate a callback.
471   net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
472   fetcher->delegate()->OnURLFetchComplete(fetcher,
473                                           GURL(kServiceUrl),
474                                           status,
475                                           500,
476                                           ResponseCookies(),
477                                           "");
478 
479   // Backend should have been reset.
480   EXPECT_FALSE(backend_.get());
481 }
482 
483 }  // namespace policy
484