Home | History | Annotate | Download | only in signin
      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