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/ui/sync/one_click_signin_sync_observer.h" 6 7 #include "base/bind.h" 8 #include "base/message_loop/message_loop.h" 9 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/signin/signin_promo.h" 11 #include "chrome/browser/sync/profile_sync_service.h" 12 #include "chrome/browser/sync/profile_sync_service_factory.h" 13 #include "content/public/browser/web_contents.h" 14 #include "content/public/browser/web_contents_delegate.h" 15 16 namespace { 17 18 void CloseTab(content::WebContents* tab) { 19 content::WebContentsDelegate* tab_delegate = tab->GetDelegate(); 20 if (tab_delegate) 21 tab_delegate->CloseContents(tab); 22 } 23 24 } // namespace 25 26 27 OneClickSigninSyncObserver::OneClickSigninSyncObserver( 28 content::WebContents* web_contents, 29 const GURL& continue_url) 30 : content::WebContentsObserver(web_contents), 31 continue_url_(continue_url), 32 weak_ptr_factory_(this) { 33 DCHECK(!continue_url_.is_empty()); 34 35 ProfileSyncService* sync_service = GetSyncService(web_contents); 36 if (sync_service) { 37 sync_service->AddObserver(this); 38 } else { 39 LoadContinueUrl(); 40 // Post a task rather than calling |delete this| here, so that the 41 // destructor is not called directly from the constructor. Note that it's 42 // important to pass a weak pointer rather than base::Unretained(this) 43 // because it's possible for e.g. WebContentsDestroyed() to be called 44 // before this task has a chance to run. 45 base::MessageLoop::current()->PostTask( 46 FROM_HERE, 47 base::Bind(&OneClickSigninSyncObserver::DeleteObserver, 48 weak_ptr_factory_.GetWeakPtr())); 49 } 50 } 51 52 OneClickSigninSyncObserver::~OneClickSigninSyncObserver() {} 53 54 void OneClickSigninSyncObserver::WebContentsDestroyed() { 55 ProfileSyncService* sync_service = GetSyncService(web_contents()); 56 if (sync_service) 57 sync_service->RemoveObserver(this); 58 59 delete this; 60 } 61 62 void OneClickSigninSyncObserver::OnStateChanged() { 63 ProfileSyncService* sync_service = GetSyncService(web_contents()); 64 65 // At this point, the sign-in process is complete, and control has been handed 66 // back to the sync engine. Close the gaia sign in tab if the |continue_url_| 67 // contains the |auto_close| parameter. Otherwise, wait for sync setup to 68 // complete and then navigate to the |continue_url_|. 69 if (signin::IsAutoCloseEnabledInURL(continue_url_)) { 70 // Close the Gaia sign-in tab via a task to make sure we aren't in the 71 // middle of any WebUI handler code. 72 base::MessageLoop::current()->PostTask( 73 FROM_HERE, 74 base::Bind(&CloseTab, base::Unretained(web_contents()))); 75 } else { 76 if (sync_service->FirstSetupInProgress()) { 77 // Sync setup has not completed yet. Wait for it to complete. 78 return; 79 } 80 81 if (sync_service->sync_initialized() && 82 signin::GetSourceForPromoURL(continue_url_) 83 != signin::SOURCE_SETTINGS) { 84 // TODO(isherman): Having multiple settings pages open can cause issues 85 // redirecting after Sync is set up: http://crbug.com/355885 86 LoadContinueUrl(); 87 } 88 } 89 90 sync_service->RemoveObserver(this); 91 delete this; 92 } 93 94 void OneClickSigninSyncObserver::LoadContinueUrl() { 95 web_contents()->GetController().LoadURL( 96 continue_url_, 97 content::Referrer(), 98 content::PAGE_TRANSITION_AUTO_TOPLEVEL, 99 std::string()); 100 } 101 102 ProfileSyncService* OneClickSigninSyncObserver::GetSyncService( 103 content::WebContents* web_contents) { 104 Profile* profile = 105 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 106 return ProfileSyncServiceFactory::GetForProfile(profile); 107 } 108 109 // static 110 void OneClickSigninSyncObserver::DeleteObserver( 111 base::WeakPtr<OneClickSigninSyncObserver> observer) { 112 if (observer) 113 delete observer.get(); 114 } 115