OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 "arc_opt_in_manager_impl.h" | |
6 #include "base/strings/string_split.h" | |
7 #include "base/strings/string_util.h" | |
8 #include "base/strings/stringprintf.h" | |
9 #include "chrome/browser/profiles/profile.h" | |
10 #include "components/arc/arc_bridge_service.h" | |
11 #include "google_apis/gaia/gaia_constants.h" | |
12 #include "google_apis/gaia/gaia_urls.h" | |
13 #include "net/http/http_status_code.h" | |
14 #include "net/url_request/url_fetcher.h" | |
15 | |
16 namespace arc { | |
17 | |
18 namespace { | |
19 | |
20 const char kClientId[] = | |
21 "1070009224336-sdh77n7uot3oc99ais00jmuft6sk2fg9.apps.googleusercontent.com"; | |
22 const char kCookiePartSecure[] = "secure"; | |
23 const char kCookiePartHttpOnly[] = "httponly"; | |
24 const char kCookiePartCodePrefix[] = "oauth_code="; | |
25 const int kCookiePartCodePrefixLength = arraysize(kCookiePartCodePrefix) - 1; | |
26 | |
27 static bool CookiePartsContains(const std::vector<std::string>& parts, | |
khmel
2016/01/22 21:55:24
Works with cookies here and at some places below a
| |
28 const char* part) { | |
29 for (std::vector<std::string>::const_iterator it = parts.begin(); | |
30 it != parts.end(); ++it) { | |
31 if (base::LowerCaseEqualsASCII(*it, part)) | |
32 return true; | |
33 } | |
34 return false; | |
35 } | |
36 | |
37 } // namespace | |
38 | |
39 ArcOptInManagerImpl::ArcOptInManagerImpl() {} | |
40 | |
41 ArcOptInManagerImpl::~ArcOptInManagerImpl() {} | |
42 | |
43 ArcOptInManager::State ArcOptInManagerImpl::state() const { | |
44 return state_; | |
45 } | |
46 | |
47 void ArcOptInManagerImpl::SetProfile(Profile* profile) { | |
48 DCHECK(profile == nullptr || profile != profile_); | |
49 DCHECK(thread_checker_.CalledOnValidThread()); | |
50 | |
51 ArcBridgeService::Get()->Shutdown(); | |
52 if (state_ != State::DISABLE) { | |
53 auth_fetcher_.reset(); | |
54 state_ = State::DISABLE; | |
55 FOR_EACH_OBSERVER(Observer, observer_list_, OnOptInChanged(state_)); | |
56 } | |
57 | |
58 profile_ = profile; | |
59 | |
60 // TODO(khmel). At this moment UI to handle ARC OptIn is not ready yet. Assume | |
61 // we opted in by default. When UI is ready, this should be synced with | |
62 // user's prefs. | |
63 if (profile_ != nullptr) | |
64 FetchToken(); | |
65 } | |
66 | |
67 void ArcOptInManagerImpl::AddObserver(Observer* observer) { | |
68 DCHECK(thread_checker_.CalledOnValidThread()); | |
69 observer_list_.AddObserver(observer); | |
70 } | |
71 | |
72 void ArcOptInManagerImpl::RemoveObserver(Observer* observer) { | |
73 DCHECK(thread_checker_.CalledOnValidThread()); | |
74 observer_list_.RemoveObserver(observer); | |
75 } | |
76 | |
77 std::string ArcOptInManagerImpl::GetAuthToken() { | |
78 DCHECK(thread_checker_.CalledOnValidThread()); | |
79 std::string auth_token; | |
80 auth_token_.swap(auth_token); | |
81 return auth_token; | |
82 } | |
83 | |
84 void ArcOptInManagerImpl::SetAuthTokenAndStartArc( | |
85 const std::string auth_token) { | |
86 DCHECK(thread_checker_.CalledOnValidThread()); | |
87 DCHECK(!auth_token.empty()); | |
88 DCHECK(state_ != State::ENABLE); | |
89 | |
90 auth_fetcher_.reset(); | |
91 auth_token_ = auth_token; | |
92 state_ = State::ENABLE; | |
93 | |
94 ArcBridgeService::Get()->HandleStartup(); | |
95 FOR_EACH_OBSERVER(Observer, observer_list_, OnOptInChanged(state_)); | |
96 } | |
97 | |
98 GURL ArcOptInManagerImpl::CreateURL(Profile* profile) { | |
99 DCHECK(profile != nullptr); | |
100 | |
101 std::string query_string = base::StringPrintf( | |
102 "?scope=%s&client_id=%s&email=%s", GaiaConstants::kOAuth1LoginScope, | |
103 kClientId, profile->GetProfileUserName().c_str()); | |
104 | |
105 return GaiaUrls::GetInstance()->client_login_to_oauth2_url().Resolve( | |
106 query_string); | |
107 } | |
108 | |
109 void ArcOptInManagerImpl::FetchToken() { | |
110 DCHECK(thread_checker_.CalledOnValidThread()); | |
111 DCHECK(state_ == State::DISABLE); | |
112 | |
113 auth_token_ = ""; | |
114 state_ = State::FETCHING_TOKEN; | |
115 FOR_EACH_OBSERVER(Observer, observer_list_, OnOptInChanged(state_)); | |
116 | |
117 auth_fetcher_ = ::net::URLFetcher::Create(CreateURL(profile_), | |
118 ::net::URLFetcher::GET, this); | |
119 auth_fetcher_->SetRequestContext(profile_->GetRequestContext()); | |
120 // Executed asynchronously. | |
121 auth_fetcher_->Start(); | |
122 } | |
123 | |
124 bool ArcOptInManagerImpl::ParseAuthToken(const net::URLFetcher* source, | |
125 std::string* token) { | |
126 DCHECK(source != nullptr && token != nullptr); | |
127 net::ResponseCookies::const_iterator iter; | |
128 const net::ResponseCookies& cookies = source->GetCookies(); | |
129 for (iter = cookies.begin(); iter != cookies.end(); ++iter) { | |
130 std::vector<std::string> parts = base::SplitString( | |
131 *iter, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
132 // Per documentation, the cookie should have Secure and HttpOnly. | |
133 if (!CookiePartsContains(parts, kCookiePartSecure) || | |
134 !CookiePartsContains(parts, kCookiePartHttpOnly)) { | |
135 continue; | |
136 } | |
137 | |
138 std::vector<std::string>::const_iterator iter; | |
139 for (iter = parts.begin(); iter != parts.end(); ++iter) { | |
140 const std::string& part = *iter; | |
141 if (base::StartsWith(part, kCookiePartCodePrefix, | |
142 base::CompareCase::INSENSITIVE_ASCII)) { | |
143 *token = part.substr(kCookiePartCodePrefixLength); | |
144 return true; | |
145 } | |
146 } | |
147 } | |
148 | |
149 return false; | |
150 } | |
151 | |
152 void ArcOptInManagerImpl::OnURLFetchComplete(const net::URLFetcher* source) { | |
153 DCHECK(thread_checker_.CalledOnValidThread()); | |
154 | |
155 std::string auth_token; | |
156 if (!source->GetStatus().is_success() || | |
157 source->GetResponseCode() != net::HTTP_OK || | |
158 !ParseAuthToken(source, &auth_token)) { | |
159 state_ = State::NO_TOKEN; | |
160 // TODO(khmel). There is no UI currently available. So start bridge anyway. | |
161 // GMS won't be signed in automatically. | |
162 ArcBridgeService::Get()->HandleStartup(); | |
163 FOR_EACH_OBSERVER(Observer, observer_list_, OnOptInChanged(state_)); | |
164 } else { | |
165 SetAuthTokenAndStartArc(auth_token); | |
166 } | |
167 } | |
168 | |
169 } // namespace arc | |
OLD | NEW |