Home | History | Annotate | Download | only in policy
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/logging.h"
     10 #include "base/metrics/histogram.h"
     11 #include "base/metrics/sparse_histogram.h"
     12 #include "base/sequenced_task_runner.h"
     13 #include "chrome/browser/browser_process.h"
     14 #include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
     15 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
     16 #include "chrome/browser/chromeos/policy/wildcard_login_checker.h"
     17 #include "chrome/browser/chromeos/profiles/profile_helper.h"
     18 #include "chrome/browser/lifetime/application_lifetime.h"
     19 #include "components/policy/core/common/cloud/cloud_external_data_manager.h"
     20 #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
     21 #include "components/policy/core/common/cloud/device_management_service.h"
     22 #include "components/policy/core/common/cloud/system_policy_request_context.h"
     23 #include "components/policy/core/common/policy_pref_names.h"
     24 #include "content/public/common/content_client.h"
     25 #include "net/url_request/url_request_context_getter.h"
     26 #include "url/gurl.h"
     27 
     28 namespace em = enterprise_management;
     29 
     30 namespace policy {
     31 
     32 namespace {
     33 
     34 // UMA histogram names.
     35 const char kUMADelayInitialization[] =
     36     "Enterprise.UserPolicyChromeOS.DelayInitialization";
     37 const char kUMAInitialFetchClientError[] =
     38     "Enterprise.UserPolicyChromeOS.InitialFetch.ClientError";
     39 const char kUMAInitialFetchDelayClientRegister[] =
     40     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayClientRegister";
     41 const char kUMAInitialFetchDelayOAuth2Token[] =
     42     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayOAuth2Token";
     43 const char kUMAInitialFetchDelayPolicyFetch[] =
     44     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayPolicyFetch";
     45 const char kUMAInitialFetchDelayTotal[] =
     46     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayTotal";
     47 const char kUMAInitialFetchOAuth2Error[] =
     48     "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2Error";
     49 const char kUMAInitialFetchOAuth2NetworkError[] =
     50     "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2NetworkError";
     51 
     52 void OnWildcardCheckCompleted(const std::string& username, bool result) {
     53   if (!result) {
     54     LOG(ERROR) << "Online wildcard login check failed, terminating session.";
     55 
     56     // TODO(mnissler): This only removes the user pod from the login screen, but
     57     // the cryptohome remains. This is because deleting the cryptohome for a
     58     // logged-in session is not possible. Fix this either by delaying the
     59     // cryptohome deletion operation or by getting rid of the in-session
     60     // wildcard check.
     61     chromeos::UserManager::Get()->RemoveUserFromList(username);
     62     chrome::AttemptUserExit();
     63   }
     64 }
     65 
     66 }  // namespace
     67 
     68 UserCloudPolicyManagerChromeOS::UserCloudPolicyManagerChromeOS(
     69     scoped_ptr<CloudPolicyStore> store,
     70     scoped_ptr<CloudExternalDataManager> external_data_manager,
     71     const base::FilePath& component_policy_cache_path,
     72     bool wait_for_policy_fetch,
     73     base::TimeDelta initial_policy_fetch_timeout,
     74     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
     75     const scoped_refptr<base::SequencedTaskRunner>& file_task_runner,
     76     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
     77     : CloudPolicyManager(
     78           PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()),
     79           store.get(),
     80           task_runner,
     81           file_task_runner,
     82           io_task_runner),
     83       store_(store.Pass()),
     84       external_data_manager_(external_data_manager.Pass()),
     85       component_policy_cache_path_(component_policy_cache_path),
     86       wait_for_policy_fetch_(wait_for_policy_fetch),
     87       policy_fetch_timeout_(false, false) {
     88   time_init_started_ = base::Time::Now();
     89   if (wait_for_policy_fetch_) {
     90     policy_fetch_timeout_.Start(
     91         FROM_HERE,
     92         initial_policy_fetch_timeout,
     93         base::Bind(&UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch,
     94                    base::Unretained(this)));
     95   }
     96 }
     97 
     98 UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {}
     99 
    100 void UserCloudPolicyManagerChromeOS::Connect(
    101     PrefService* local_state,
    102     DeviceManagementService* device_management_service,
    103     scoped_refptr<net::URLRequestContextGetter> system_request_context,
    104     UserAffiliation user_affiliation) {
    105   DCHECK(device_management_service);
    106   DCHECK(local_state);
    107   local_state_ = local_state;
    108   scoped_refptr<net::URLRequestContextGetter> request_context;
    109   if (system_request_context) {
    110     // |system_request_context| can be null for tests.
    111     // Use the system request context here instead of a context derived
    112     // from the Profile because Connect() is called before the profile is
    113     // fully initialized (required so we can perform the initial policy load).
    114     // TODO(atwilson): Change this to use a UserPolicyRequestContext once
    115     // Connect() is called after profile initialization. http://crbug.com/323591
    116     request_context = new SystemPolicyRequestContext(
    117         system_request_context,
    118         content::GetUserAgent(GURL(
    119             device_management_service->GetServerUrl())));
    120   }
    121   scoped_ptr<CloudPolicyClient> cloud_policy_client(
    122       new CloudPolicyClient(std::string(), std::string(), user_affiliation,
    123                             NULL, device_management_service,
    124                             request_context));
    125   core()->Connect(cloud_policy_client.Pass());
    126   client()->AddObserver(this);
    127 
    128   external_data_manager_->Connect(request_context);
    129 
    130   CreateComponentCloudPolicyService(component_policy_cache_path_,
    131                                     request_context);
    132 
    133   // Determine the next step after the CloudPolicyService initializes.
    134   if (service()->IsInitializationComplete()) {
    135     OnInitializationCompleted(service());
    136   } else {
    137     service()->AddObserver(this);
    138   }
    139 }
    140 
    141 void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable(
    142     const std::string& access_token) {
    143   access_token_ = access_token;
    144 
    145   if (!wildcard_username_.empty()) {
    146     wildcard_login_checker_.reset(new WildcardLoginChecker());
    147     wildcard_login_checker_->StartWithAccessToken(
    148         access_token,
    149         base::Bind(&OnWildcardCheckCompleted, wildcard_username_));
    150   }
    151 
    152   if (service() && service()->IsInitializationComplete() &&
    153       client() && !client()->is_registered()) {
    154     OnOAuth2PolicyTokenFetched(
    155         access_token, GoogleServiceAuthError(GoogleServiceAuthError::NONE));
    156   }
    157 }
    158 
    159 bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const {
    160   return client() && client()->is_registered();
    161 }
    162 
    163 void UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck(
    164     const std::string& username) {
    165   DCHECK(access_token_.empty());
    166   wildcard_username_ = username;
    167 }
    168 
    169 void UserCloudPolicyManagerChromeOS::Shutdown() {
    170   if (client())
    171     client()->RemoveObserver(this);
    172   if (service())
    173     service()->RemoveObserver(this);
    174   token_fetcher_.reset();
    175   external_data_manager_->Disconnect();
    176   CloudPolicyManager::Shutdown();
    177 }
    178 
    179 bool UserCloudPolicyManagerChromeOS::IsInitializationComplete(
    180     PolicyDomain domain) const {
    181   if (!CloudPolicyManager::IsInitializationComplete(domain))
    182     return false;
    183   if (domain == POLICY_DOMAIN_CHROME)
    184     return !wait_for_policy_fetch_;
    185   return true;
    186 }
    187 
    188 void UserCloudPolicyManagerChromeOS::OnInitializationCompleted(
    189     CloudPolicyService* cloud_policy_service) {
    190   DCHECK_EQ(service(), cloud_policy_service);
    191   cloud_policy_service->RemoveObserver(this);
    192 
    193   time_init_completed_ = base::Time::Now();
    194   UMA_HISTOGRAM_TIMES(kUMADelayInitialization,
    195                       time_init_completed_ - time_init_started_);
    196 
    197   // If the CloudPolicyClient isn't registered at this stage then it needs an
    198   // OAuth token for the initial registration.
    199   //
    200   // If |wait_for_policy_fetch_| is true then Profile initialization is blocking
    201   // on the initial policy fetch, so the token must be fetched immediately.
    202   // In that case, the signin Profile is used to authenticate a Gaia request to
    203   // fetch a refresh token, and then the policy token is fetched.
    204   //
    205   // If |wait_for_policy_fetch_| is false then the UserCloudPolicyTokenForwarder
    206   // service will eventually call OnAccessTokenAvailable() once an access token
    207   // is available. That call may have already happened while waiting for
    208   // initialization of the CloudPolicyService, so in that case check if an
    209   // access token is already available.
    210   if (!client()->is_registered()) {
    211     if (wait_for_policy_fetch_) {
    212       FetchPolicyOAuthTokenUsingSigninProfile();
    213     } else if (!access_token_.empty()) {
    214       OnAccessTokenAvailable(access_token_);
    215     }
    216   }
    217 
    218   if (!wait_for_policy_fetch_) {
    219     // If this isn't blocking on a policy fetch then
    220     // CloudPolicyManager::OnStoreLoaded() already published the cached policy.
    221     // Start the refresh scheduler now, which will eventually refresh the
    222     // cached policy or make the first fetch once the OAuth2 token is
    223     // available.
    224     StartRefreshSchedulerIfReady();
    225   }
    226 }
    227 
    228 void UserCloudPolicyManagerChromeOS::OnPolicyFetched(
    229     CloudPolicyClient* client) {
    230   // No action required. If we're blocked on a policy fetch, we'll learn about
    231   // completion of it through OnInitialPolicyFetchComplete().
    232 }
    233 
    234 void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged(
    235     CloudPolicyClient* cloud_policy_client) {
    236   DCHECK_EQ(client(), cloud_policy_client);
    237 
    238   if (wait_for_policy_fetch_) {
    239     time_client_registered_ = base::Time::Now();
    240     if (!time_token_available_.is_null()) {
    241       UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayClientRegister,
    242                           time_client_registered_ - time_token_available_);
    243     }
    244 
    245     // If we're blocked on the policy fetch, now is a good time to issue it.
    246     if (client()->is_registered()) {
    247       service()->RefreshPolicy(
    248           base::Bind(
    249               &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete,
    250               base::Unretained(this)));
    251     } else {
    252       // If the client has switched to not registered, we bail out as this
    253       // indicates the cloud policy setup flow has been aborted.
    254       CancelWaitForPolicyFetch();
    255     }
    256   }
    257 }
    258 
    259 void UserCloudPolicyManagerChromeOS::OnClientError(
    260     CloudPolicyClient* cloud_policy_client) {
    261   DCHECK_EQ(client(), cloud_policy_client);
    262   if (wait_for_policy_fetch_) {
    263     UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchClientError,
    264                                 cloud_policy_client->status());
    265   }
    266   CancelWaitForPolicyFetch();
    267 }
    268 
    269 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() {
    270   CloudPolicyManager::OnComponentCloudPolicyUpdated();
    271   StartRefreshSchedulerIfReady();
    272 }
    273 
    274 void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() {
    275   scoped_refptr<net::URLRequestContextGetter> signin_context;
    276   Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile();
    277   if (signin_profile)
    278     signin_context = signin_profile->GetRequestContext();
    279   if (!signin_context.get()) {
    280     LOG(ERROR) << "No signin Profile for policy oauth token fetch!";
    281     OnOAuth2PolicyTokenFetched(
    282         std::string(), GoogleServiceAuthError(GoogleServiceAuthError::NONE));
    283     return;
    284   }
    285 
    286   token_fetcher_.reset(new PolicyOAuth2TokenFetcher(
    287       signin_context.get(),
    288       g_browser_process->system_request_context(),
    289       base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched,
    290                  base::Unretained(this))));
    291   token_fetcher_->Start();
    292 }
    293 
    294 void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched(
    295     const std::string& policy_token,
    296     const GoogleServiceAuthError& error) {
    297   DCHECK(!client()->is_registered());
    298   time_token_available_ = base::Time::Now();
    299   if (wait_for_policy_fetch_) {
    300     UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayOAuth2Token,
    301                         time_token_available_ - time_init_completed_);
    302   }
    303 
    304   if (error.state() == GoogleServiceAuthError::NONE) {
    305     // Start client registration. Either OnRegistrationStateChanged() or
    306     // OnClientError() will be called back.
    307     client()->Register(em::DeviceRegisterRequest::USER,
    308                        policy_token, std::string(), false, std::string());
    309   } else {
    310     // Failed to get a token, stop waiting and use an empty policy.
    311     CancelWaitForPolicyFetch();
    312 
    313     UMA_HISTOGRAM_ENUMERATION(kUMAInitialFetchOAuth2Error,
    314                               error.state(),
    315                               GoogleServiceAuthError::NUM_STATES);
    316     if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
    317       UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError,
    318                                   error.network_error());
    319     }
    320   }
    321 
    322   token_fetcher_.reset();
    323 }
    324 
    325 void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete(
    326     bool success) {
    327   const base::Time now = base::Time::Now();
    328   UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayPolicyFetch,
    329                       now - time_client_registered_);
    330   UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayTotal, now - time_init_started_);
    331   CancelWaitForPolicyFetch();
    332 }
    333 
    334 void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() {
    335   if (!wait_for_policy_fetch_)
    336     return;
    337 
    338   wait_for_policy_fetch_ = false;
    339   CheckAndPublishPolicy();
    340   // Now that |wait_for_policy_fetch_| is guaranteed to be false, the scheduler
    341   // can be started.
    342   StartRefreshSchedulerIfReady();
    343 }
    344 
    345 void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() {
    346   if (core()->refresh_scheduler())
    347     return;  // Already started.
    348 
    349   if (wait_for_policy_fetch_)
    350     return;  // Still waiting for the initial, blocking fetch.
    351 
    352   if (!service() || !local_state_)
    353     return;  // Not connected.
    354 
    355   if (component_policy_service() &&
    356       !component_policy_service()->is_initialized()) {
    357     // If the client doesn't have the list of components to fetch yet then don't
    358     // start the scheduler. The |component_policy_service_| will call back into
    359     // OnComponentCloudPolicyUpdated() once it's ready.
    360     return;
    361   }
    362 
    363   core()->StartRefreshScheduler();
    364   core()->TrackRefreshDelayPref(local_state_,
    365                                 policy_prefs::kUserPolicyRefreshRate);
    366 }
    367 
    368 }  // namespace policy
    369