普通文本  |  120行  |  4.18 KB

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/signin/signin_header_helper.h"

#include "base/command_line.h"
#include "chrome/browser/extensions/extension_renderer_state.h"
#include "chrome/browser/profiles/profile_io_data.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"

namespace {

const char kChromeConnectedHeader[] = "X-Chrome-Connected";
const char kChromeManageAccountsHeader[] = "X-Chrome-Manage-Accounts";
const char kGaiaAuthExtensionID[] = "mfffpogegjflfpflabcdkioaeobkgjik";

// Show profile avatar bubble on UI thread. Must be called on the UI thread.
void ShowAvatarBubbleUIThread(int child_id, int route_id) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

#if !defined(OS_ANDROID)
  content::WebContents* web_contents =
      tab_util::GetWebContentsByID(child_id, route_id);
  if (!web_contents)
    return;

  Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
  if (browser)
    browser->window()->ShowAvatarBubbleFromAvatarButton();
  // TODO(guohui): need to handle the case when avatar button is not available.
#endif // OS_ANDROID
}

bool IsDriveOrigin(const GURL& url) {
  if (!url.SchemeIsSecure())
    return false;

  const GURL kGoogleDriveURL("https://drive.google.com");
  const GURL kGoogleDocsURL("https://docs.google.com");
  return url == kGoogleDriveURL || url == kGoogleDocsURL;
}

} // empty namespace

namespace signin {

void AppendMirrorRequestHeaderIfPossible(
    net::URLRequest* request,
    const GURL& redirect_url,
    ProfileIOData* io_data,
    int child_id,
    int route_id) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

   if (io_data->is_incognito() ||
       io_data->google_services_username()->GetValue().empty()) {
     return;
   }

  // Only set the header for Gaia (in the mirror world) and Drive. Gaia needs
  // the header to redirect certain user actions to Chrome native UI. Drive
  // needs the header to tell if the current user is connected. The drive path
  // is a temporary workaround until the more generic chrome.principals API is
  // available.
  const GURL& url = redirect_url.is_empty() ? request->url() : redirect_url;
  GURL origin(url.GetOrigin());
  bool enable_inline = CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableInlineSignin);
  bool is_gaia_signin = enable_inline &&
      profiles::IsNewProfileManagementEnabled() &&
      gaia::IsGaiaSignonRealm(origin);
  if (!is_gaia_signin && !IsDriveOrigin(origin))
    return;

  ExtensionRendererState* renderer_state =
      ExtensionRendererState::GetInstance();
  ExtensionRendererState::WebViewInfo webview_info;
  bool is_guest = renderer_state->GetWebViewInfo(
      child_id, route_id, &webview_info);
  if (is_guest && webview_info.extension_id == kGaiaAuthExtensionID){
    return;
  }

  std::string account_id(io_data->google_services_account_id()->GetValue());
  if (account_id.empty())
    account_id = "1"; // Dummy value if focus ID not available yet.

  request->SetExtraRequestHeaderByName(
      kChromeConnectedHeader, account_id, false);
}

void ProcessMirrorResponseHeaderIfExists(
    net::URLRequest* request,
    ProfileIOData* io_data,
    int child_id,
    int route_id) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

  if (gaia::IsGaiaSignonRealm(request->url().GetOrigin()) &&
      request->response_headers()->HasHeader(kChromeManageAccountsHeader)) {
    DCHECK(profiles::IsNewProfileManagementEnabled() &&
           !io_data->is_incognito());
    content::BrowserThread::PostTask(
        content::BrowserThread::UI, FROM_HERE,
        base::Bind(ShowAvatarBubbleUIThread, child_id, route_id));
  }
}

} // namespace signin