12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/login/profile_auth_data.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string>
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/bind.h"
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/bind_helpers.h"
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/callback.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/location.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/logging.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/memory/ref_counted.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/message_loop/message_loop.h"
166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/time/time.h"
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/browser_context.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/cookies/canonical_cookie.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/cookies/cookie_monster.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/cookies/cookie_store.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_auth_cache.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_network_session.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_transaction_factory.h"
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/ssl/channel_id_service.h"
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/ssl/channel_id_store.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_context.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "url/gurl.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const char kSAMLStartCookie[] = "google-accounts-saml-start";
386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const char kSAMLEndCookie[] = "google-accounts-saml-end";
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ProfileAuthDataTransferer {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileAuthDataTransferer(
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      content::BrowserContext* from_context,
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      content::BrowserContext* to_context,
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      bool transfer_auth_cookies_and_channel_ids_on_first_login,
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      bool transfer_saml_auth_cookies_on_subsequent_login,
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::Closure& completion_callback);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void BeginTransfer();
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void BeginTransferOnIOThread();
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Transfer the proxy auth cache from |from_context_| to |to_context_|. If
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the user was required to authenticate with a proxy during login, this
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // authentication information will be transferred into the user's session.
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void TransferProxyAuthCache();
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Callback that receives the content of |to_context_|'s cookie jar. Checks
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // whether this is the user's first login, based on the state of the cookie
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // jar, and starts retrieval of the data that should be transfered. Calls
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Finish() if there is no data to transfer.
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void OnTargetCookieJarContentsRetrieved(
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const net::CookieList& target_cookies);
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Retrieve the contents of |from_context_|'s cookie jar. When the retrieval
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // finishes, OnCookiesToTransferRetrieved will be called with the result.
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void RetrieveCookiesToTransfer();
69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Callback that receives the contents of |from_context_|'s cookie jar. Calls
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // MaybeTransferCookiesAndChannelIDs() to try and perform the transfer.
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void OnCookiesToTransferRetrieved(const net::CookieList& cookies_to_transfer);
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Retrieve |from_context_|'s channel IDs. When the retrieval finishes,
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // OnChannelIDsToTransferRetrieved will be called with the result.
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void RetrieveChannelIDsToTransfer();
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Callback that receives |from_context_|'s channel IDs. Calls
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // MaybeTransferCookiesAndChannelIDs() to try and perform the transfer.
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void OnChannelIDsToTransferRetrieved(
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const net::ChannelIDStore::ChannelIDList& channel_ids_to_transfer);
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Given a |cookie| set during login, returns true if the cookie may have been
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // set by GAIA. The main criterion is the |cookie|'s creation date. The points
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // in time at which redirects from GAIA to SAML IdP and back occur are stored
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // in |saml_start_time_| and |saml_end_time_|. If the cookie was set between
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // these two times, it was created by the SAML IdP. Otherwise, it was created
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // by GAIA.
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // As an additional precaution, the cookie's domain is checked. If the domain
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // contains "google" or "youtube", the cookie is considered to have been set
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // by GAIA as well.
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  bool IsGAIACookie(const net::CanonicalCookie& cookie);
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // If all data to be transferred has been retrieved already, transfer it to
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |to_context_| and call Finish().
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void MaybeTransferCookiesAndChannelIDs();
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Post the |completion_callback_| to the UI thread and schedule destruction
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // of |this|.
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void Finish();
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> from_context_;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> to_context_;
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool transfer_auth_cookies_and_channel_ids_on_first_login_;
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool transfer_saml_auth_cookies_on_subsequent_login_;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure completion_callback_;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::CookieList cookies_to_transfer_;
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  net::ChannelIDStore::ChannelIDList channel_ids_to_transfer_;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // The time at which a redirect from GAIA to a SAML IdP occurred.
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::Time saml_start_time_;
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // The time at which a redirect from a SAML IdP back to GAIA occurred.
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::Time saml_end_time_;
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool first_login_;
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool waiting_for_auth_cookies_;
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool waiting_for_channel_ids_;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProfileAuthDataTransferer::ProfileAuthDataTransferer(
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    content::BrowserContext* from_context,
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    content::BrowserContext* to_context,
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool transfer_auth_cookies_and_channel_ids_on_first_login,
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool transfer_saml_auth_cookies_on_subsequent_login,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& completion_callback)
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : from_context_(from_context->GetRequestContext()),
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      to_context_(to_context->GetRequestContext()),
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      transfer_auth_cookies_and_channel_ids_on_first_login_(
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          transfer_auth_cookies_and_channel_ids_on_first_login),
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      transfer_saml_auth_cookies_on_subsequent_login_(
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          transfer_saml_auth_cookies_on_subsequent_login),
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      completion_callback_(completion_callback),
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      first_login_(false),
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      waiting_for_auth_cookies_(false),
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      waiting_for_channel_ids_(false) {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProfileAuthDataTransferer::BeginTransfer() {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // If we aren't transferring auth cookies or channel IDs, post the completion
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // callback immediately. Otherwise, it will be called when the transfer
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // finishes.
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!transfer_auth_cookies_and_channel_ids_on_first_login_ &&
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      !transfer_saml_auth_cookies_on_subsequent_login_) {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, completion_callback_);
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Null the callback so that when Finish is called, the callback won't be
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // called again.
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    completion_callback_.Reset();
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostTask(
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::IO, FROM_HERE,
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ProfileAuthDataTransferer::BeginTransferOnIOThread,
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(this)));
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProfileAuthDataTransferer::BeginTransferOnIOThread() {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  TransferProxyAuthCache();
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (transfer_auth_cookies_and_channel_ids_on_first_login_ ||
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      transfer_saml_auth_cookies_on_subsequent_login_) {
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Retrieve the contents of |to_context_|'s cookie jar.
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    net::CookieStore* to_store =
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        to_context_->GetURLRequestContext()->cookie_store();
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    net::CookieMonster* to_monster = to_store->GetCookieMonster();
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    to_monster->GetAllCookiesAsync(
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            &ProfileAuthDataTransferer::OnTargetCookieJarContentsRetrieved,
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Unretained(this)));
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Finish();
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ProfileAuthDataTransferer::TransferProxyAuthCache() {
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  net::HttpAuthCache* new_cache = to_context_->GetURLRequestContext()->
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      http_transaction_factory()->GetSession()->http_auth_cache();
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  new_cache->UpdateAllFrom(*from_context_->GetURLRequestContext()->
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      http_transaction_factory()->GetSession()->http_auth_cache());
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ProfileAuthDataTransferer::OnTargetCookieJarContentsRetrieved(
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const net::CookieList& target_cookies) {
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  first_login_ = target_cookies.empty();
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (first_login_) {
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // On first login, transfer all auth cookies and channel IDs if
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // |transfer_auth_cookies_and_channel_ids_on_first_login_| is true.
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    waiting_for_auth_cookies_ =
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        transfer_auth_cookies_and_channel_ids_on_first_login_;
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    waiting_for_channel_ids_ =
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        transfer_auth_cookies_and_channel_ids_on_first_login_;
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // On subsequent login, transfer auth cookies set by the SAML IdP if
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // |transfer_saml_auth_cookies_on_subsequent_login_| is true.
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    waiting_for_auth_cookies_ = transfer_saml_auth_cookies_on_subsequent_login_;
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!waiting_for_auth_cookies_ && !waiting_for_channel_ids_) {
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Finish();
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (waiting_for_auth_cookies_)
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RetrieveCookiesToTransfer();
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (waiting_for_channel_ids_)
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RetrieveChannelIDsToTransfer();
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ProfileAuthDataTransferer::RetrieveCookiesToTransfer() {
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  net::CookieStore* from_store =
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      from_context_->GetURLRequestContext()->cookie_store();
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  net::CookieMonster* from_monster = from_store->GetCookieMonster();
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  from_monster->SetKeepExpiredCookies();
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  from_monster->GetAllCookiesAsync(
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&ProfileAuthDataTransferer::OnCookiesToTransferRetrieved,
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 base::Unretained(this)));
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ProfileAuthDataTransferer::OnCookiesToTransferRetrieved(
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const net::CookieList& cookies_to_transfer) {
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  waiting_for_auth_cookies_ = false;
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  cookies_to_transfer_ = cookies_to_transfer;
2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Look for cookies indicating the points in time at which redirects from GAIA
2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // to SAML IdP and back occurred. These cookies are synthesized by
2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // chrome/browser/resources/gaia_auth/background.js. If the cookies are found,
2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // their creation times are stored in |saml_start_time_| and
2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // |cookies_to_transfer_| and the cookies are deleted.
2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  for (net::CookieList::iterator it = cookies_to_transfer_.begin();
2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)       it != cookies_to_transfer_.end(); ) {
2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (it->Name() == kSAMLStartCookie) {
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      saml_start_time_ = it->CreationDate();
2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      it = cookies_to_transfer_.erase(it);
2386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else if (it->Name() == kSAMLEndCookie) {
2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      saml_end_time_ = it->CreationDate();
2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      it = cookies_to_transfer_.erase(it);
2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else {
2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ++it;
2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MaybeTransferCookiesAndChannelIDs();
247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ProfileAuthDataTransferer::RetrieveChannelIDsToTransfer() {
250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  net::ChannelIDService* from_service =
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      from_context_->GetURLRequestContext()->channel_id_service();
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  from_service->GetChannelIDStore()->GetAllChannelIDs(
254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(
2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          &ProfileAuthDataTransferer::OnChannelIDsToTransferRetrieved,
256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          base::Unretained(this)));
257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
258116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ProfileAuthDataTransferer::OnChannelIDsToTransferRetrieved(
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const net::ChannelIDStore::ChannelIDList& channel_ids_to_transfer) {
261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  channel_ids_to_transfer_ = channel_ids_to_transfer;
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  waiting_for_channel_ids_ = false;
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MaybeTransferCookiesAndChannelIDs();
265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool ProfileAuthDataTransferer::IsGAIACookie(
2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const net::CanonicalCookie& cookie) {
2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const base::Time& creation_date = cookie.CreationDate();
2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (creation_date < saml_start_time_)
2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return true;
2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!saml_end_time_.is_null() && creation_date > saml_end_time_)
2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return true;
2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const std::string& domain = cookie.Domain();
2766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return domain.find("google") != std::string::npos ||
2776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)         domain.find("youtube") != std::string::npos;
2786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ProfileAuthDataTransferer::MaybeTransferCookiesAndChannelIDs() {
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (waiting_for_auth_cookies_ || waiting_for_channel_ids_)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::CookieStore* to_store =
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      to_context_->GetURLRequestContext()->cookie_store();
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::CookieMonster* to_monster = to_store->GetCookieMonster();
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (first_login_) {
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    to_monster->ImportCookies(cookies_to_transfer_);
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    net::ChannelIDService* to_cert_service =
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        to_context_->GetURLRequestContext()->channel_id_service();
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    to_cert_service->GetChannelIDStore()->InitializeFrom(
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        channel_ids_to_transfer_);
2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::CookieList non_gaia_cookies;
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (net::CookieList::const_iterator it = cookies_to_transfer_.begin();
2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         it != cookies_to_transfer_.end(); ++it) {
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!IsGAIACookie(*it))
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        non_gaia_cookies.push_back(*it);
3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    to_monster->ImportCookies(non_gaia_cookies);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Finish();
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
307116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ProfileAuthDataTransferer::Finish() {
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!completion_callback_.is_null())
310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, completion_callback_);
3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProfileAuthData::Transfer(
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    content::BrowserContext* from_context,
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    content::BrowserContext* to_context,
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool transfer_auth_cookies_and_channel_ids_on_first_login,
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool transfer_saml_auth_cookies_on_subsequent_login,
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& completion_callback) {
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  (new ProfileAuthDataTransferer(
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       from_context,
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       to_context,
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       transfer_auth_cookies_and_channel_ids_on_first_login,
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       transfer_saml_auth_cookies_on_subsequent_login,
3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       completion_callback))->BeginTransfer();
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chromeos
332