Home | History | Annotate | Download | only in policy
      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:
     46   DeviceManagementServiceTestBase()
     47       : request_context_(new TestURLRequestContextGetter()),
     48         io_thread_(BrowserThread::IO, &loop_) {
     49     ResetService();
     50     service_->Initialize(request_context_.get());
     51   }
     52 
     53   virtual void SetUp() {
     54     URLFetcher::set_factory(&factory_);
     55   }
     56 
     57   virtual void TearDown() {
     58     URLFetcher::set_factory(NULL);
     59     backend_.reset();
     60     service_.reset();
     61     request_context_ = NULL;
     62     loop_.RunAllPending();
     63   }
     64 
     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 {
     82   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 
    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 
    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 
    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:
    209   explicit QueryParams(const std::string& query) {
    210     base::SplitStringIntoKeyValuePairs(query, '=', '&', &params_);
    211   }
    212 
    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:
    249   void ResetBackend() {
    250     backend_.reset();
    251   }
    252 
    253  protected:
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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