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, '=', '&', ¶ms_); 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