1// Copyright 2014 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/wildcard_login_checker.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/metrics/histogram.h"
10#include "chrome/browser/browser_process.h"
11#include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
12#include "components/policy/core/browser/browser_policy_connector.h"
13#include "net/url_request/url_request_context_getter.h"
14
15namespace policy {
16
17namespace {
18
19// Presence of this key in the userinfo response indicates whether the user is
20// on a hosted domain.
21const char kHostedDomainKey[] = "hd";
22
23// UMA histogram names.
24const char kUMADelayPolicyTokenFetch[] =
25    "Enterprise.WildcardLoginCheck.DelayPolicyTokenFetch";
26const char kUMADelayUserInfoFetch[] =
27    "Enterprise.WildcardLoginCheck.DelayUserInfoFetch";
28const char kUMADelayTotal[] =
29    "Enterprise.WildcardLoginCheck.DelayTotal";
30
31}  // namespace
32
33WildcardLoginChecker::WildcardLoginChecker() {}
34
35WildcardLoginChecker::~WildcardLoginChecker() {}
36
37void WildcardLoginChecker::Start(
38    scoped_refptr<net::URLRequestContextGetter> signin_context,
39    const StatusCallback& callback) {
40  CHECK(!token_fetcher_);
41  CHECK(!user_info_fetcher_);
42
43  start_timestamp_ = base::Time::Now();
44
45  callback_ = callback;
46  token_fetcher_.reset(new PolicyOAuth2TokenFetcher(
47      signin_context.get(),
48      g_browser_process->system_request_context(),
49      base::Bind(&WildcardLoginChecker::OnPolicyTokenFetched,
50                 base::Unretained(this))));
51  token_fetcher_->Start();
52}
53
54void WildcardLoginChecker::StartWithAccessToken(
55    const std::string& access_token,
56    const StatusCallback& callback) {
57  CHECK(!token_fetcher_);
58  CHECK(!user_info_fetcher_);
59  callback_ = callback;
60
61  StartUserInfoFetcher(access_token);
62}
63
64void WildcardLoginChecker::OnGetUserInfoSuccess(
65    const base::DictionaryValue* response) {
66  if (!start_timestamp_.is_null()) {
67    base::Time now = base::Time::Now();
68    UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayUserInfoFetch,
69                               now - token_available_timestamp_);
70    UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayTotal,
71                               now - start_timestamp_);
72  }
73
74  OnCheckCompleted(response->HasKey(kHostedDomainKey) ? RESULT_ALLOWED
75                                                      : RESULT_BLOCKED);
76}
77
78void WildcardLoginChecker::OnGetUserInfoFailure(
79    const GoogleServiceAuthError& error) {
80  LOG(ERROR) << "Failed to fetch user info " << error.ToString();
81  OnCheckCompleted(RESULT_FAILED);
82}
83
84void WildcardLoginChecker::OnPolicyTokenFetched(
85    const std::string& access_token,
86    const GoogleServiceAuthError& error) {
87  if (error.state() != GoogleServiceAuthError::NONE) {
88    LOG(ERROR) << "Failed to fetch policy token " << error.ToString();
89    OnCheckCompleted(RESULT_FAILED);
90    return;
91  }
92
93  if (!start_timestamp_.is_null()) {
94    token_available_timestamp_ = base::Time::Now();
95    UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayPolicyTokenFetch,
96                               token_available_timestamp_ - start_timestamp_);
97  }
98
99  token_fetcher_.reset();
100  StartUserInfoFetcher(access_token);
101}
102
103void WildcardLoginChecker::StartUserInfoFetcher(
104    const std::string& access_token) {
105  user_info_fetcher_.reset(
106      new UserInfoFetcher(this, g_browser_process->system_request_context()));
107  user_info_fetcher_->Start(access_token);
108}
109
110void WildcardLoginChecker::OnCheckCompleted(Result result) {
111  if (!callback_.is_null())
112    callback_.Run(result);
113}
114
115}  // namespace policy
116