1 // Copyright 2013 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/signin/signin_header_helper.h" 6 7 #include "base/command_line.h" 8 #include "chrome/browser/extensions/extension_renderer_state.h" 9 #include "chrome/browser/profiles/profile_io_data.h" 10 #include "chrome/browser/profiles/profiles_state.h" 11 #include "chrome/browser/tab_contents/tab_util.h" 12 #include "chrome/browser/ui/browser_finder.h" 13 #include "chrome/browser/ui/browser_window.h" 14 #include "chrome/common/chrome_switches.h" 15 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/web_contents.h" 17 #include "google_apis/gaia/gaia_auth_util.h" 18 #include "net/http/http_response_headers.h" 19 #include "net/url_request/url_request.h" 20 21 namespace { 22 23 const char kChromeConnectedHeader[] = "X-Chrome-Connected"; 24 const char kChromeManageAccountsHeader[] = "X-Chrome-Manage-Accounts"; 25 const char kGaiaAuthExtensionID[] = "mfffpogegjflfpflabcdkioaeobkgjik"; 26 27 // Show profile avatar bubble on UI thread. Must be called on the UI thread. 28 void ShowAvatarBubbleUIThread(int child_id, int route_id) { 29 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 30 31 #if !defined(OS_ANDROID) 32 content::WebContents* web_contents = 33 tab_util::GetWebContentsByID(child_id, route_id); 34 if (!web_contents) 35 return; 36 37 Browser* browser = chrome::FindBrowserWithWebContents(web_contents); 38 if (browser) 39 browser->window()->ShowAvatarBubbleFromAvatarButton(); 40 // TODO(guohui): need to handle the case when avatar button is not available. 41 #endif // OS_ANDROID 42 } 43 44 bool IsDriveOrigin(const GURL& url) { 45 if (!url.SchemeIsSecure()) 46 return false; 47 48 const GURL kGoogleDriveURL("https://drive.google.com"); 49 const GURL kGoogleDocsURL("https://docs.google.com"); 50 return url == kGoogleDriveURL || url == kGoogleDocsURL; 51 } 52 53 } // empty namespace 54 55 namespace signin { 56 57 void AppendMirrorRequestHeaderIfPossible( 58 net::URLRequest* request, 59 const GURL& redirect_url, 60 ProfileIOData* io_data, 61 int child_id, 62 int route_id) { 63 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 64 65 if (io_data->is_incognito() || 66 io_data->google_services_username()->GetValue().empty()) { 67 return; 68 } 69 70 // Only set the header for Gaia (in the mirror world) and Drive. Gaia needs 71 // the header to redirect certain user actions to Chrome native UI. Drive 72 // needs the header to tell if the current user is connected. The drive path 73 // is a temporary workaround until the more generic chrome.principals API is 74 // available. 75 const GURL& url = redirect_url.is_empty() ? request->url() : redirect_url; 76 GURL origin(url.GetOrigin()); 77 bool enable_inline = CommandLine::ForCurrentProcess()->HasSwitch( 78 switches::kEnableInlineSignin); 79 bool is_gaia_signin = enable_inline && 80 profiles::IsNewProfileManagementEnabled() && 81 gaia::IsGaiaSignonRealm(origin); 82 if (!is_gaia_signin && !IsDriveOrigin(origin)) 83 return; 84 85 ExtensionRendererState* renderer_state = 86 ExtensionRendererState::GetInstance(); 87 ExtensionRendererState::WebViewInfo webview_info; 88 bool is_guest = renderer_state->GetWebViewInfo( 89 child_id, route_id, &webview_info); 90 if (is_guest && webview_info.extension_id == kGaiaAuthExtensionID){ 91 return; 92 } 93 94 std::string account_id(io_data->google_services_account_id()->GetValue()); 95 if (account_id.empty()) 96 account_id = "1"; // Dummy value if focus ID not available yet. 97 98 request->SetExtraRequestHeaderByName( 99 kChromeConnectedHeader, account_id, false); 100 } 101 102 void ProcessMirrorResponseHeaderIfExists( 103 net::URLRequest* request, 104 ProfileIOData* io_data, 105 int child_id, 106 int route_id) { 107 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 108 109 if (gaia::IsGaiaSignonRealm(request->url().GetOrigin()) && 110 request->response_headers()->HasHeader(kChromeManageAccountsHeader)) { 111 DCHECK(profiles::IsNewProfileManagementEnabled() && 112 !io_data->is_incognito()); 113 content::BrowserThread::PostTask( 114 content::BrowserThread::UI, FROM_HERE, 115 base::Bind(ShowAvatarBubbleUIThread, child_id, route_id)); 116 } 117 } 118 119 } // namespace signin 120