user_cloud_policy_manager_chromeos_unittest.cc revision 5e3f23d412006dc4db4e659864679f29341e113f
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind_helpers.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/testing_pref_service.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/run_loop.h"
155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/profiles/profile_helper.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/policy/cloud/cloud_policy_service.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/policy/cloud/mock_cloud_policy_store.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/policy/cloud/mock_device_management_service.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/policy/cloud/resource_cache.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/policy/mock_configuration_policy_provider.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/browser_prefs.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/token_service.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/token_service_factory.h"
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_constants.h"
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/base/testing_browser_process.h"
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/base/testing_profile.h"
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/base/testing_profile_manager.h"
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/test/test_browser_thread.h"
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_auth_consumer.h"
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_urls.h"
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/test_url_fetcher_factory.h"
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/url_request_status.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "policy/policy_constants.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace em = enterprise_management;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::AnyNumber;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::AtLeast;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Mock;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::_;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuthTokenCookie[] = "oauth_token=1234";
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuth2TokenPairData[] =
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "{"
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "  \"refresh_token\": \"1234\","
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "  \"access_token\": \"5678\","
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "  \"expires_in\": 3600"
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "}";
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOAuth2AccessTokenData[] =
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "{"
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "  \"access_token\": \"5678\","
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "  \"expires_in\": 3600"
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "}";
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class UserCloudPolicyManagerChromeOSTest : public testing::Test {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UserCloudPolicyManagerChromeOSTest()
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : ui_thread_(content::BrowserThread::UI, &loop_),
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        io_thread_(content::BrowserThread::IO, &loop_),
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        store_(NULL),
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        profile_(NULL),
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        signin_profile_(NULL) {}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The initialization path that blocks on the initial policy fetch requires
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // a signin Profile to use its URLRequestContext.
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    profile_manager_.reset(
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(profile_manager_->SetUp());
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    profile_ = profile_manager_->CreateTestingProfile(
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        chrome::kInitialProfile, UTF8ToUTF16("testing_profile"), 0);
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    signin_profile_ = profile_manager_->CreateTestingProfile("signin_profile");
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    signin_profile_->set_incognito(true);
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Usually the signin Profile and the main Profile are separate, but since
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // the signin Profile is an OTR Profile then for this test it suffices to
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // attach it to the main Profile.
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    profile_->SetOffTheRecordProfile(signin_profile_);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    signin_profile_->SetOriginalProfile(profile_);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    signin_profile_->CreateRequestContext();
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_EQ(signin_profile_, chromeos::ProfileHelper::GetSigninProfile());
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::RegisterLocalState(prefs_.registry());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set up a policy map for testing.
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    policy_map_.Set("HomepageLocation",
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    base::Value::CreateStringValue("http://chromium.org"));
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    expected_bundle_.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .CopyFrom(policy_map_);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Create fake policy blobs to deliver to the client.
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    em::DeviceRegisterResponse* register_response =
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        register_blob_.mutable_register_response();
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    register_response->set_device_management_token("dmtoken123");
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    em::CloudPolicySettings policy_proto;
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    policy_proto.mutable_homepagelocation()->set_value("http://chromium.org");
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        policy_proto.SerializeToString(policy_data_.mutable_policy_value()));
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    policy_data_.set_policy_type(dm_protocol::kChromeUserPolicyType);
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    policy_data_.set_request_token("dmtoken123");
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    policy_data_.set_device_id("id987");
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    em::PolicyFetchResponse* policy_response =
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        policy_blob_.mutable_policy_response()->add_response();
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(policy_data_.SerializeToString(
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        policy_response->mutable_policy_data()));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _, _))
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Times(AnyNumber());
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (manager_) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      manager_->RemoveObserver(&observer_);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      manager_->Shutdown();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    signin_profile_->ResetRequestContext();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void CreateManager(bool wait_for_fetch) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    store_ = new MockCloudPolicyStore();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(*store_, Load());
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manager_.reset(new UserCloudPolicyManagerChromeOS(
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scoped_ptr<CloudPolicyStore>(store_),
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scoped_ptr<ResourceCache>(),
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        wait_for_fetch));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager_->Init();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager_->AddObserver(&observer_);
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manager_->Connect(&prefs_, &device_management_service_, NULL,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      USER_AFFILIATION_NONE);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mock::VerifyAndClearExpectations(store_);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!wait_for_fetch) {
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Create the UserCloudPolicyTokenForwarder, which forwards the refresh
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // token from the TokenService to the UserCloudPolicyManagerChromeOS.
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // This service is automatically created for regular Profiles but not for
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // testing Profiles.
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      TokenService* token_service =
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          TokenServiceFactory::GetForProfile(profile_);
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_TRUE(token_service);
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      token_forwarder_.reset(
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          new UserCloudPolicyTokenForwarder(manager_.get(), token_service));
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Expects a pending URLFetcher for the |expected_url|, and returns it with
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // prepared to deliver a response to its delegate.
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::TestURLFetcher* PrepareOAuthFetcher(const std::string& expected_url) {
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    net::TestURLFetcher* fetcher = test_url_fetcher_factory_.GetFetcherByID(0);
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(fetcher);
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!fetcher)
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return NULL;
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(fetcher->delegate());
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(StartsWithASCII(fetcher->GetOriginalURL().spec(),
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                expected_url,
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                true));
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fetcher->set_url(fetcher->GetOriginalURL());
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fetcher->set_response_code(200);
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fetcher->set_status(net::URLRequestStatus());
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return fetcher;
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Issues the OAuth2 tokens and returns the device management register job
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // if the flow succeeded.
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockDeviceManagementJob* IssueOAuthToken(bool has_request_token) {
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_FALSE(manager_->core()->client()->is_registered());
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    net::TestURLFetcher* fetcher = NULL;
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!has_request_token) {
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Issue the oauth_token cookie first.
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fetcher = PrepareOAuthFetcher(gaia_urls->client_login_to_oauth2_url());
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!fetcher)
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return NULL;
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      net::ResponseCookies cookies;
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      cookies.push_back(kOAuthTokenCookie);
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fetcher->set_cookies(cookies);
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fetcher->delegate()->OnURLFetchComplete(fetcher);
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Issue the refresh token.
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fetcher = PrepareOAuthFetcher(gaia_urls->oauth2_token_url());
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!fetcher)
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return NULL;
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fetcher->SetResponseString(kOAuth2TokenPairData);
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fetcher->delegate()->OnURLFetchComplete(fetcher);
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Issue the access token.
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fetcher = PrepareOAuthFetcher(gaia_urls->oauth2_token_url());
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!fetcher)
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return NULL;
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fetcher->SetResponseString(kOAuth2AccessTokenData);
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Issuing this token triggers the callback of the OAuth2PolicyFetcher,
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // which triggers the registration request.
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MockDeviceManagementJob* register_request = NULL;
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(device_management_service_,
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION))
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(device_management_service_.CreateAsyncJob(&register_request));
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fetcher->delegate()->OnURLFetchComplete(fetcher);
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(register_request);
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_FALSE(manager_->core()->client()->is_registered());
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Mock::VerifyAndClearExpectations(&device_management_service_);
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _, _))
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .Times(AnyNumber());
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return register_request;
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Expects a policy fetch request to be issued after invoking |trigger_fetch|.
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This method replies to that fetch request and verifies that the manager
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // handled the response.
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void FetchPolicy(const base::Closure& trigger_fetch) {
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MockDeviceManagementJob* policy_request = NULL;
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(device_management_service_,
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH))
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(device_management_service_.CreateAsyncJob(&policy_request));
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    trigger_fetch.Run();
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(policy_request);
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(manager_->core()->client()->is_registered());
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Mock::VerifyAndClearExpectations(&device_management_service_);
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(device_management_service_, StartJob(_, _, _, _, _, _, _))
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .Times(AnyNumber());
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Send the initial policy back. This completes the initialization flow.
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(*store_, Store(_));
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    policy_request->SendResponse(DM_STATUS_SUCCESS, policy_blob_);
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Mock::VerifyAndClearExpectations(store_);
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Notifying that the store is has cached the fetched policy completes the
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // process, and initializes the manager.
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    store_->policy_map_.CopyFrom(policy_map_);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    store_->NotifyStoreLoaded();
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mock::VerifyAndClearExpectations(&observer_);
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(manager_->policies().Equals(expected_bundle_));
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Required by the refresh scheduler that's created by the manager.
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop loop_;
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  content::TestBrowserThread ui_thread_;
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Required to cleanup the URLRequestContextGetter of the |signin_profile_|.
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  content::TestBrowserThread io_thread_;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convenience policy objects.
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  em::PolicyData policy_data_;
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  em::DeviceManagementResponse register_blob_;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  em::DeviceManagementResponse policy_blob_;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyMap policy_map_;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyBundle expected_bundle_;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Policy infrastructure.
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::TestURLFetcherFactory test_url_fetcher_factory_;
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingPrefServiceSimple prefs_;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConfigurationPolicyObserver observer_;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockDeviceManagementService device_management_service_;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockCloudPolicyStore* store_;
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<UserCloudPolicyManagerChromeOS> manager_;
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<UserCloudPolicyTokenForwarder> token_forwarder_;
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Required by ProfileHelper to get the signin Profile context.
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<TestingProfileManager> profile_manager_;
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestingProfile* profile_;
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestingProfile* signin_profile_;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyManagerChromeOSTest);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFirstFetch) {
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Tests the initialization of a manager whose Profile is waiting for the
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // initial fetch, when the policy cache is empty.
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CreateManager(true));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Initialize the CloudPolicyService without any stored data.
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  store_->NotifyStoreLoaded();
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->client()->is_registered());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This starts the OAuth2 policy token fetcher using the signin Profile.
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The manager will then issue the registration request.
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockDeviceManagementJob* register_request = IssueOAuthToken(false);
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(register_request);
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Reply with a valid registration response. This triggers the initial policy
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // fetch.
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FetchPolicy(base::Bind(&MockDeviceManagementJob::SendResponse,
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         base::Unretained(register_request),
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         DM_STATUS_SUCCESS, register_blob_));
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingRefreshFetch) {
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Tests the initialization of a manager whose Profile is waiting for the
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // initial fetch, when a previously cached policy and DMToken already exist.
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CreateManager(true));
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Set the initially cached data and initialize the CloudPolicyService.
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The initial policy fetch is issued using the cached DMToken.
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  store_->policy_.reset(new em::PolicyData(policy_data_));
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FetchPolicy(base::Bind(&MockCloudPolicyStore::NotifyStoreLoaded,
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         base::Unretained(store_)));
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFetchStoreError) {
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Tests the initialization of a manager whose Profile is waiting for the
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // initial fetch, when the initial store load fails.
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CreateManager(true));
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Initialize the CloudPolicyService without any stored data.
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  store_->NotifyStoreError();
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->client()->is_registered());
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This starts the OAuth2 policy token fetcher using the signin Profile.
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The manager will then issue the registration request.
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockDeviceManagementJob* register_request = IssueOAuthToken(false);
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(register_request);
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Reply with a valid registration response. This triggers the initial policy
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // fetch.
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FetchPolicy(base::Bind(&MockDeviceManagementJob::SendResponse,
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         base::Unretained(register_request),
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         DM_STATUS_SUCCESS, register_blob_));
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFetchOAuthError) {
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Tests the initialization of a manager whose Profile is waiting for the
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // initial fetch, when the OAuth2 token fetch fails.
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CreateManager(true));
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Initialize the CloudPolicyService without any stored data.
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  store_->NotifyStoreLoaded();
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->client()->is_registered());
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This starts the OAuth2 policy token fetcher using the signin Profile.
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The manager will initialize with no policy after the token fetcher fails.
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The PolicyOAuth2TokenFetcher posts delayed retries on some errors. This
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // data will make it fail immediately.
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::TestURLFetcher* fetcher = PrepareOAuthFetcher(
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GaiaUrls::GetInstance()->client_login_to_oauth2_url());
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(fetcher);
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fetcher->set_response_code(400);
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fetcher->SetResponseString("Error=BadAuthentication");
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fetcher->delegate()->OnURLFetchComplete(fetcher);
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(PolicyBundle().Equals(manager_->policies()));
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mock::VerifyAndClearExpectations(&observer_);
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFetchRegisterError) {
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Tests the initialization of a manager whose Profile is waiting for the
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // initial fetch, when the device management registration fails.
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CreateManager(true));
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Initialize the CloudPolicyService without any stored data.
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  store_->NotifyStoreError();
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->client()->is_registered());
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This starts the OAuth2 policy token fetcher using the signin Profile.
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The manager will then issue the registration request.
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockDeviceManagementJob* register_request = IssueOAuthToken(false);
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(register_request);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Now make it fail.
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  register_request->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE,
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 em::DeviceManagementResponse());
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(PolicyBundle().Equals(manager_->policies()));
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mock::VerifyAndClearExpectations(&observer_);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFetchPolicyFetchError) {
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Tests the initialization of a manager whose Profile is waiting for the
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // initial fetch, when the policy fetch request fails.
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CreateManager(true));
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Initialize the CloudPolicyService without any stored data.
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  store_->NotifyStoreLoaded();
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->client()->is_registered());
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This starts the OAuth2 policy token fetcher using the signin Profile.
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The manager will then issue the registration request.
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockDeviceManagementJob* register_request = IssueOAuthToken(false);
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(register_request);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Reply with a valid registration response. This triggers the initial policy
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // fetch.
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockDeviceManagementJob* policy_request = NULL;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(device_management_service_,
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH))
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(device_management_service_.CreateAsyncJob(&policy_request));
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  register_request->SendResponse(DM_STATUS_SUCCESS, register_blob_);
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Mock::VerifyAndClearExpectations(&device_management_service_);
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(policy_request);
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->core()->client()->is_registered());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make the policy fetch fail. The observer gets 2 notifications: one from the
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // RefreshPolicies callback, and another from the OnClientError callback.
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // A single notification suffices for this edge case, but this behavior is
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // also correct and makes the implementation simpler.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get())).Times(AtLeast(1));
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  policy_request->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE,
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               em::DeviceManagementResponse());
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mock::VerifyAndClearExpectations(&observer_);
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(PolicyBundle().Equals(manager_->policies()));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(UserCloudPolicyManagerChromeOSTest, NonBlockingFirstFetch) {
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Tests the first policy fetch request by a Profile that isn't managed.
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CreateManager(false));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Initialize the CloudPolicyService without any stored data. Since the
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // manager is not waiting for the initial fetch, it will become initialized
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // once the store is ready.
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  store_->NotifyStoreLoaded();
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Mock::VerifyAndClearExpectations(&observer_);
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->client()->is_registered());
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The manager is waiting for the refresh token, and hasn't started any
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // fetchers.
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(test_url_fetcher_factory_.GetFetcherByID(0));
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Set a fake refresh token at the TokenService.
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(token_service);
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GaiaAuthConsumer::ClientOAuthResult tokens("refresh", "access", 3600);
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(token_service->HasOAuthLoginToken());
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  token_service->UpdateCredentialsWithOAuth2(tokens);
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(token_service->HasOAuthLoginToken());
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // That should have notified the manager, which now issues the request for the
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // policy oauth token.
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockDeviceManagementJob* register_request = IssueOAuthToken(true);
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(register_request);
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  register_request->SendResponse(DM_STATUS_SUCCESS, register_blob_);
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The refresh scheduler takes care of the initial fetch for unmanaged users.
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // It posts a delayed task with 0ms delay in this case, so spinning the loop
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // issues the initial fetch.
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::RunLoop loop;
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FetchPolicy(
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&base::RunLoop::RunUntilIdle, base::Unretained(&loop)));
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(UserCloudPolicyManagerChromeOSTest, NonBlockingRefreshFetch) {
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Tests a non-blocking initial policy fetch for a Profile that already has
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // a cached DMToken.
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CreateManager(false));
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Set the initially cached data and initialize the CloudPolicyService.
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The initial policy fetch is issued using the cached DMToken.
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  store_->policy_.reset(new em::PolicyData(policy_data_));
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  store_->NotifyStoreLoaded();
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mock::VerifyAndClearExpectations(&observer_);
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(manager_->core()->client()->is_registered());
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The refresh scheduler takes care of the initial fetch for unmanaged users.
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // It posts a delayed task with 0ms delay in this case, so spinning the loop
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // issues the initial fetch.
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::RunLoop loop;
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FetchPolicy(
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&base::RunLoop::RunUntilIdle, base::Unretained(&loop)));
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace policy
516