blob: 7e326dd501cd64845f455718aac1433ff0ae3e73 [file] [log] [blame]
// 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/chrome_signin_helper.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/profiles/profile_io_data.h"
#include "chrome/browser/signin/account_reconcilor_factory.h"
#include "chrome/browser/signin/chrome_signin_client.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/url_constants.h"
#include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/core/browser/signin_header_helper.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/web_contents.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "net/url_request/url_request.h"
#if defined(OS_ANDROID)
#include "chrome/browser/android/signin/account_management_screen_helper.h"
#else
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
#endif // defined(OS_ANDROID)
namespace signin {
namespace {
// Processes the mirror response header on the UI thread. Currently depending
// on the value of |header_value|, it either shows the profile avatar menu, or
// opens an incognito window/tab.
void ProcessMirrorHeaderUIThread(int child_id,
int route_id,
ManageAccountsParams manage_accounts_params) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
GAIAServiceType service_type = manage_accounts_params.service_type;
DCHECK_NE(GAIA_SERVICE_TYPE_NONE, service_type);
content::WebContents* web_contents =
tab_util::GetWebContentsByID(child_id, route_id);
if (!web_contents)
return;
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
AccountReconcilor* account_reconcilor =
AccountReconcilorFactory::GetForProfile(profile);
account_reconcilor->OnReceivedManageAccountsResponse(
manage_accounts_params.service_type);
#if !defined(OS_ANDROID)
Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
if (browser) {
BrowserWindow::AvatarBubbleMode bubble_mode;
switch (service_type) {
case GAIA_SERVICE_TYPE_INCOGNITO:
chrome::NewIncognitoWindow(browser);
return;
case GAIA_SERVICE_TYPE_ADDSESSION:
bubble_mode = BrowserWindow::AVATAR_BUBBLE_MODE_ADD_ACCOUNT;
break;
case GAIA_SERVICE_TYPE_REAUTH:
bubble_mode = BrowserWindow::AVATAR_BUBBLE_MODE_REAUTH;
break;
default:
bubble_mode = BrowserWindow::AVATAR_BUBBLE_MODE_ACCOUNT_MANAGEMENT;
}
signin_metrics::LogAccountReconcilorStateOnGaiaResponse(
account_reconcilor->GetState());
browser->window()->ShowAvatarBubbleFromAvatarButton(
bubble_mode, manage_accounts_params,
signin_metrics::AccessPoint::ACCESS_POINT_CONTENT_AREA, false);
}
#else // defined(OS_ANDROID)
if (service_type == signin::GAIA_SERVICE_TYPE_INCOGNITO) {
GURL url(manage_accounts_params.continue_url.empty()
? chrome::kChromeUINativeNewTabURL
: manage_accounts_params.continue_url);
web_contents->OpenURL(content::OpenURLParams(
url, content::Referrer(), WindowOpenDisposition::OFF_THE_RECORD,
ui::PAGE_TRANSITION_AUTO_TOPLEVEL, false));
} else {
signin_metrics::LogAccountReconcilorStateOnGaiaResponse(
account_reconcilor->GetState());
AccountManagementScreenHelper::OpenAccountManagementScreen(profile,
service_type);
}
#endif // !defined(OS_ANDROID)
}
// Returns the parameters contained in the X-Chrome-Manage-Accounts response
// header.
// If the request does not have a response header or if the header contains
// garbage, then |service_type| is set to |GAIA_SERVICE_TYPE_NONE|.
// Must be called on IO thread.
ManageAccountsParams BuildManageAccountsParamsHelper(net::URLRequest* request,
ProfileIOData* io_data) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
const content::ResourceRequestInfo* info =
content::ResourceRequestInfo::ForRequest(request);
if (!(info && info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME)) {
ManageAccountsParams empty_params;
empty_params.service_type = GAIA_SERVICE_TYPE_NONE;
return empty_params;
}
return BuildManageAccountsParamsIfExists(request, io_data->IsOffTheRecord());
}
} // namespace
void FixMirrorRequestHeaderHelper(net::URLRequest* request,
const GURL& redirect_url,
ProfileIOData* io_data,
int child_id,
int route_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (io_data->IsOffTheRecord())
return;
#if !defined(OS_ANDROID)
extensions::WebViewRendererState::WebViewInfo webview_info;
bool is_guest = extensions::WebViewRendererState::GetInstance()->GetInfo(
child_id, route_id, &webview_info);
// Do not set the x-chrome-connected header on requests from a native signin
// webview, as identified by an empty extension id which means the webview is
// embedded in a webui page, otherwise user may end up with a blank page as
// gaia uses the header to decide whether it returns 204 for certain end
// points.
if (is_guest && webview_info.owner_host.empty())
return;
#endif // !defined(OS_ANDROID)
int profile_mode_mask = PROFILE_MODE_DEFAULT;
if (io_data->incognito_availibility()->GetValue() ==
IncognitoModePrefs::DISABLED ||
IncognitoModePrefs::ArePlatformParentalControlsEnabled()) {
profile_mode_mask |= PROFILE_MODE_INCOGNITO_DISABLED;
}
// If new url is eligible to have the header, add it, otherwise remove it.
AppendOrRemoveMirrorRequestHeaderIfPossible(
request, redirect_url, io_data->google_services_account_id()->GetValue(),
io_data->GetCookieSettings(), profile_mode_mask);
}
void ProcessMirrorResponseHeaderIfExists(net::URLRequest* request,
ProfileIOData* io_data,
int child_id,
int route_id) {
ManageAccountsParams params =
BuildManageAccountsParamsHelper(request, io_data);
if (params.service_type == GAIA_SERVICE_TYPE_NONE)
return;
params.child_id = child_id;
params.route_id = route_id;
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(ProcessMirrorHeaderUIThread, child_id, route_id, params));
}
} // namespace signin