15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef GOOGLE_APIS_GAIA_MERGE_SESSION_HELPER_H_ 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define GOOGLE_APIS_GAIA_MERGE_SESSION_HELPER_H_ 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <deque> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/observer_list.h" 116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/timer/timer.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_consumer.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gaia/ubertoken_fetcher.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class GaiaAuthFetcher; 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class GoogleServiceAuthError; 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class OAuth2TokenService; 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace net { 216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class URLFetcher; 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class URLRequestContextGetter; 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Merges a Google account known to Chrome into the cookie jar. When merging 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// multiple accounts, one instance of the helper is better than multiple 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// instances if there is the possibility that they run concurrently, since 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// changes to the cookie must be serialized. 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// By default instances of MergeSessionHelper delete themselves when done. 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MergeSessionHelper : public GaiaAuthConsumer, 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public UbertokenConsumer, 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public net::URLFetcherDelegate { 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) class Observer { 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Called whenever a merge session is completed. The account that was 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // merged is given by |account_id|. If |error| is equal to 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // GoogleServiceAuthError::AuthErrorNone() then the merge succeeeded. 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void MergeSessionCompleted(const std::string& account_id, 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const GoogleServiceAuthError& error) = 0; 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected: 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~Observer() {} 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Class to retrieve the external connection check results from gaia. 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Declared publicly for unit tests. 486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) class ExternalCcResultFetcher : public GaiaAuthConsumer, 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public net::URLFetcherDelegate { 506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public: 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Maps connection URLs, as returned by StartGetCheckConnectionInfo() to 526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // token and URLFetcher used to fetch the URL. 536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) typedef std::map<GURL, std::pair<std::string, net::URLFetcher*> > 546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) URLToTokenAndFetcher; 556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Maps tokens to the fetched result for that token. 576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) typedef std::map<std::string, std::string> ResultMap; 586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ExternalCcResultFetcher(MergeSessionHelper* helper); 606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) virtual ~ExternalCcResultFetcher(); 616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Gets the current value of the external connection check result string. 636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string GetExternalCcResult(); 646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Start fetching the external CC result. If a fetch is already in progress 666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // it is canceled. 676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void Start(); 686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Are external URLs still being checked? 706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool IsRunning(); 716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Returns a copy of the internal token to fetcher map. 736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) URLToTokenAndFetcher get_fetcher_map_for_testing() { 746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return fetchers_; 756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Simulate a timeout for tests. 786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void TimeoutForTests(); 796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private: 816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Overridden from GaiaAuthConsumer. 826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) virtual void OnGetCheckConnectionInfoSuccess( 836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const std::string& data) OVERRIDE; 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Creates and initializes a URL fetcher for doing a connection check. 866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) net::URLFetcher* CreateFetcher(const GURL& url); 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Overridden from URLFetcherDelgate. 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Any fetches still ongoing after this call are considered timed out. 926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void Timeout(); 936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void CleanupTransientState(); 956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MergeSessionHelper* helper_; 976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::OneShotTimer<ExternalCcResultFetcher> timer_; 986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<GaiaAuthFetcher> gaia_auth_fetcher_; 996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) URLToTokenAndFetcher fetchers_; 1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ResultMap results_; 1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ExternalCcResultFetcher); 1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) }; 1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MergeSessionHelper(OAuth2TokenService* token_service, 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::URLRequestContextGetter* request_context, 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Observer* observer); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~MergeSessionHelper(); 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void LogIn(const std::string& account_id); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Add or remove observers of this helper. 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void AddObserver(Observer* observer); 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RemoveObserver(Observer* observer); 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Cancel all login requests. 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void CancelAll(); 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Signout of |account_id| given a list of accounts already signed in. 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Since this involves signing out of all accounts and resigning back in, 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the order which |accounts| are given is important as it will dictate 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the sign in order. |account_id| does not have to be in |accounts|. 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void LogOut(const std::string& account_id, 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<std::string>& accounts); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Signout all accounts. 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void LogOutAllAccounts(); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Call observers when merge session completes. This public so that callers 130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // that know that a given account is already in the cookie jar can simply 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // inform the observers. 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void SignalComplete(const std::string& account_id, 133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const GoogleServiceAuthError& error); 134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Returns true of there are pending log ins or outs. 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool is_running() const { return accounts_.size() > 0; } 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Start the process of fetching the external check connection result so that 1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // its ready when we try to perform a merge session. 1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void StartFetchingExternalCcResult(); 1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Returns true if the helper is still fetching external check connection 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // results. 1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool StillFetchingExternalCcResult(); 1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) net::URLRequestContextGetter* request_context() { return request_context_; } 1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Overridden from UbertokenConsumer. 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnUbertokenSuccess(const std::string& token) OVERRIDE; 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnUbertokenFailure(const GoogleServiceAuthError& error) OVERRIDE; 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Overridden from GaiaAuthConsumer. 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnMergeSessionSuccess(const std::string& data) OVERRIDE; 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnMergeSessionFailure(const GoogleServiceAuthError& error) 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OVERRIDE; 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void LogOutInternal(const std::string& account_id, 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<std::string>& accounts); 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Starts the proess of fetching the uber token and performing a merge session 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // for the next account. Virtual so that it can be overriden in tests. 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void StartFetching(); 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Virtual for testing purpose. 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void StartLogOutUrlFetch(); 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Start the next merge session, if needed. 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void HandleNextAccount(); 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Overridden from URLFetcherDelgate. 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OAuth2TokenService* token_service_; 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::URLRequestContextGetter* request_context_; 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<GaiaAuthFetcher> gaia_auth_fetcher_; 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<UbertokenFetcher> uber_token_fetcher_; 1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ExternalCcResultFetcher result_fetcher_; 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // A worklist for this class. Accounts names are stored here if 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // we are pending a signin action for that account. Empty strings 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // represent a signout request. 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::deque<std::string> accounts_; 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // List of observers to notify when merge session completes. 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Makes sure list is empty on destruction. 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ObserverList<Observer, true> observer_list_; 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MergeSessionHelper); 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // GOOGLE_APIS_GAIA_MERGE_SESSION_HELPER_H_ 193