Commit 569a169a authored by Pavol Marko's avatar Pavol Marko Committed by Commit Bot

Properly propagate proxy auth details on sign-in screen (v2)

(Reland with WebviewProxyAuthLoginTest browsertext fix)
This CL fixes sign-in behind an authenticated proxy. Two actual changes
were necessary in this context:
- SigninPartitionManager: copy auth data from the system request
  context into new StoragePartitions
  This makes SigninPartitionManager::StartSigninSession async, which
  made small changes necessary in GaiaScreenHandler and
  EnrollmentScreenHandler
- SigninScreenHandler: Don't reload gaia immediately when auth details
  have been supplied. This was unnecessary (the URL Request will
  continue) and actually harmful, as now that we're using a new
  StoragePartition for each sign-in attempt, this discards auth data
  before we can copy them.

To support the browsertest, testserver.py gets an argument to redirect
CONNECT requests to localhost when proxying (in sign-in browsertests
without proxy, we use RuleBasedHostResolverProc::AddRule to achieve
this effect).

      unit_tests --gtest_filter=SigninPartitionManagerTest*
  Manual test:
   Setup:
     Setup an proxy server with Basic authentication
     Configure the device to use the proxy server.
     Make sure the user adding screen is shown.
   Test 1:
     Expect proxy auth dialog. Enter correct proxy auth data.
     Expect that sign-in screen is shown and sign-in works.
   Test 2:
     Expect proxy auth dialog. Enter incorrect proxy auth data.
     Expect that proxy-auth dialog is shown again.
   Test 3:
     Expect proxy auth dialog. Press Cancel.
     Expect that a network error dialog is shown.
     Press "try to sign in again".
     Expect proxy auth dialog. Enter correct proxy auth data.
     Expect that sign-in screen is shown and sign-in works.

Bug: 793524
Test: browser_tests --gtest_filter=WebviewProxyAuthLoginTest.* &&
Change-Id: I56dafa240ad3bb5902517688a5cb17e309f2982d
Reviewed-on: https://chromium-review.googlesource.com/850472Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Pavol Marko <pmarko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#527103}
parent eb2d85a1
...@@ -435,6 +435,7 @@ void ExistingUserController::Observe( ...@@ -435,6 +435,7 @@ void ExistingUserController::Observe(
// just after the UI is closed but before the new credentials were stored // just after the UI is closed but before the new credentials were stored
// in the profile. Therefore we have to give it some time to make sure it // in the profile. Therefore we have to give it some time to make sure it
// has been updated before we copy it. // has been updated before we copy it.
// TODO(pmarko): Find a better way to do this, see https://crbug.com/796512.
VLOG(1) << "Authentication was entered manually, possibly for proxyauth."; VLOG(1) << "Authentication was entered manually, possibly for proxyauth.";
scoped_refptr<net::URLRequestContextGetter> browser_process_context_getter = scoped_refptr<net::URLRequestContextGetter> browser_process_context_getter =
g_browser_process->system_request_context(); g_browser_process->system_request_context();
......
...@@ -6,17 +6,26 @@ ...@@ -6,17 +6,26 @@
#include "base/guid.h" #include "base/guid.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/incognito_helpers.h"
#include "chromeos/chromeos_switches.h" #include "chromeos/chromeos_switches.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h" #include "content/public/common/url_constants.h"
#include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h"
#include "net/base/escape.h" #include "net/base/escape.h"
#include "net/http/http_auth_cache.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h" #include "url/gurl.h"
using content::BrowserThread;
namespace chromeos { namespace chromeos {
namespace login { namespace login {
...@@ -46,18 +55,50 @@ void ClearStoragePartition(content::StoragePartition* storage_partition, ...@@ -46,18 +55,50 @@ void ClearStoragePartition(content::StoragePartition* storage_partition,
base::Time::Max(), std::move(partition_data_cleared)); base::Time::Max(), std::move(partition_data_cleared));
} }
net::URLRequestContextGetter* GetSystemURLRequestContextGetter() {
return g_browser_process->system_request_context();
}
// Transfers HttpAuthCache content from |main_url_request_context_getter| into
// |signin_url_request_context_getter|.
void PrepareSigninURLRequestContextOnIOThread(
net::URLRequestContextGetter* main_url_request_context_getter,
net::URLRequestContextGetter* signin_url_request_context_getter) {
// Transfer proxy auth data from the main URLRequestContext.
net::HttpAuthCache* main_http_auth_cache =
main_url_request_context_getter->GetURLRequestContext()
->http_transaction_factory()
->GetSession()
->http_auth_cache();
net::HttpAuthCache* signin_http_auth_cache =
signin_url_request_context_getter->GetURLRequestContext()
->http_transaction_factory()
->GetSession()
->http_auth_cache();
signin_http_auth_cache->UpdateAllFrom(*main_http_auth_cache);
}
void InvokeStartSigninSessionDoneCallback(
SigninPartitionManager::StartSigninSessionDoneCallback callback,
const std::string& partition_name) {
std::move(callback).Run(partition_name);
}
} // namespace } // namespace
SigninPartitionManager::SigninPartitionManager( SigninPartitionManager::SigninPartitionManager(
content::BrowserContext* browser_context) content::BrowserContext* browser_context)
: browser_context_(browser_context), : browser_context_(browser_context),
clear_storage_partition_task_( clear_storage_partition_task_(
base::BindRepeating(&ClearStoragePartition)) {} base::BindRepeating(&ClearStoragePartition)),
get_system_url_request_context_getter_task_(
base::BindRepeating(&GetSystemURLRequestContextGetter)) {}
SigninPartitionManager::~SigninPartitionManager() {} SigninPartitionManager::~SigninPartitionManager() {}
void SigninPartitionManager::StartSigninSession( void SigninPartitionManager::StartSigninSession(
const content::WebContents* embedder_web_contents) { const content::WebContents* embedder_web_contents,
StartSigninSessionDoneCallback signin_session_started) {
// If we already were in a sign-in session, close it first. // If we already were in a sign-in session, close it first.
// This clears stale data from the last-used StorageParittion. // This clears stale data from the last-used StorageParittion.
CloseCurrentSigninSession(base::BindOnce(&base::DoNothing)); CloseCurrentSigninSession(base::BindOnce(&base::DoNothing));
...@@ -74,6 +115,19 @@ void SigninPartitionManager::StartSigninSession( ...@@ -74,6 +115,19 @@ void SigninPartitionManager::StartSigninSession(
current_storage_partition_ = current_storage_partition_ =
content::BrowserContext::GetStoragePartitionForSite(browser_context_, content::BrowserContext::GetStoragePartitionForSite(browser_context_,
guest_site, true); guest_site, true);
base::OnceClosure invoke_callback = base::BindOnce(
&InvokeStartSigninSessionDoneCallback, std::move(signin_session_started),
current_storage_partition_name_);
BrowserThread::PostTaskAndReply(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&PrepareSigninURLRequestContextOnIOThread,
base::RetainedRef(get_system_url_request_context_getter_task_.Run()),
base::RetainedRef(
current_storage_partition_->GetURLRequestContext())),
std::move(invoke_callback));
} }
void SigninPartitionManager::CloseCurrentSigninSession( void SigninPartitionManager::CloseCurrentSigninSession(
...@@ -97,6 +151,13 @@ void SigninPartitionManager::SetClearStoragePartitionTaskForTesting( ...@@ -97,6 +151,13 @@ void SigninPartitionManager::SetClearStoragePartitionTaskForTesting(
clear_storage_partition_task_ = clear_storage_partition_task; clear_storage_partition_task_ = clear_storage_partition_task;
} }
void SigninPartitionManager::SetGetSystemURLRequestContextGetterTaskForTesting(
GetSystemURLRequestContextGetterTask
get_system_url_request_context_getter_task) {
get_system_url_request_context_getter_task_ =
get_system_url_request_context_getter_task;
}
const std::string& SigninPartitionManager::GetCurrentStoragePartitionName() const std::string& SigninPartitionManager::GetCurrentStoragePartitionName()
const { const {
DCHECK(IsInSigninSession()); DCHECK(IsInSigninSession());
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
...@@ -19,6 +20,10 @@ class StoragePartition; ...@@ -19,6 +20,10 @@ class StoragePartition;
class WebContents; class WebContents;
} // namespace content } // namespace content
namespace net {
class URLRequestContextGetter;
}
namespace chromeos { namespace chromeos {
namespace login { namespace login {
...@@ -30,6 +35,12 @@ class SigninPartitionManager : public KeyedService { ...@@ -30,6 +35,12 @@ class SigninPartitionManager : public KeyedService {
base::RepeatingCallback<void(content::StoragePartition* storage_partition, base::RepeatingCallback<void(content::StoragePartition* storage_partition,
base::OnceClosure data_cleared)>; base::OnceClosure data_cleared)>;
using GetSystemURLRequestContextGetterTask =
base::RepeatingCallback<net::URLRequestContextGetter*()>;
using StartSigninSessionDoneCallback =
base::OnceCallback<void(const std::string& partition_name)>;
explicit SigninPartitionManager(content::BrowserContext* browser_context); explicit SigninPartitionManager(content::BrowserContext* browser_context);
~SigninPartitionManager() override; ~SigninPartitionManager() override;
...@@ -38,7 +49,11 @@ class SigninPartitionManager : public KeyedService { ...@@ -38,7 +49,11 @@ class SigninPartitionManager : public KeyedService {
// closed (and cleared). // closed (and cleared).
// |embedder_web_contents| is the WebContents instance embedding the webview // |embedder_web_contents| is the WebContents instance embedding the webview
// which will display the sign-in pages. // which will display the sign-in pages.
void StartSigninSession(const content::WebContents* embedder_web_contents); // |signin_session_started| will be invoked with the partition name of the
// started signin session on completition.
void StartSigninSession(
const content::WebContents* embedder_web_contents,
StartSigninSessionDoneCallback signin_session_started);
// Closes the current StoragePartition. All cached data in the // Closes the current StoragePartition. All cached data in the
// StoragePartition is cleared. |partition_data_cleared| will be called when // StoragePartition is cleared. |partition_data_cleared| will be called when
...@@ -66,6 +81,9 @@ class SigninPartitionManager : public KeyedService { ...@@ -66,6 +81,9 @@ class SigninPartitionManager : public KeyedService {
void SetClearStoragePartitionTaskForTesting( void SetClearStoragePartitionTaskForTesting(
ClearStoragePartitionTask clear_storage_partition_task); ClearStoragePartitionTask clear_storage_partition_task);
void SetGetSystemURLRequestContextGetterTaskForTesting(
GetSystemURLRequestContextGetterTask
get_system_url_request_context_getter_task);
class Factory : public BrowserContextKeyedServiceFactory { class Factory : public BrowserContextKeyedServiceFactory {
public: public:
...@@ -93,6 +111,8 @@ class SigninPartitionManager : public KeyedService { ...@@ -93,6 +111,8 @@ class SigninPartitionManager : public KeyedService {
content::BrowserContext* const browser_context_; content::BrowserContext* const browser_context_;
ClearStoragePartitionTask clear_storage_partition_task_; ClearStoragePartitionTask clear_storage_partition_task_;
GetSystemURLRequestContextGetterTask
get_system_url_request_context_getter_task_;
// GuestView StoragePartitions use the host of the embedder site's URL as the // GuestView StoragePartitions use the host of the embedder site's URL as the
// domain of their StoragePartition. // domain of their StoragePartition.
......
...@@ -12,13 +12,16 @@ ...@@ -12,13 +12,16 @@
#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/site_instance.h" #include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/web_contents_tester.h" #include "content/public/test/web_contents_tester.h"
#include "net/cookies/cookie_store.h" #include "net/cookies/cookie_store.h"
#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -27,6 +30,39 @@ namespace login { ...@@ -27,6 +30,39 @@ namespace login {
namespace { namespace {
constexpr char kEmbedderUrl[] = "http://www.whatever.com/"; constexpr char kEmbedderUrl[] = "http://www.whatever.com/";
void StorePartitionNameAndQuitLoop(base::RunLoop* loop,
std::string* out_partition_name,
const std::string& partition_name) {
*out_partition_name = partition_name;
loop->Quit();
}
void AddEntryToHttpAuthCache(
net::URLRequestContextGetter* url_request_context_getter) {
net::HttpAuthCache* http_auth_cache =
url_request_context_getter->GetURLRequestContext()
->http_transaction_factory()
->GetSession()
->http_auth_cache();
http_auth_cache->Add(GURL("http://whatever.com/"), "",
net::HttpAuth::AUTH_SCHEME_BASIC, "",
net::AuthCredentials(), "");
}
void IsEntryInHttpAuthCache(
net::URLRequestContextGetter* url_request_context_getter,
bool* out_entry_found) {
net::HttpAuthCache* http_auth_cache =
url_request_context_getter->GetURLRequestContext()
->http_transaction_factory()
->GetSession()
->http_auth_cache();
*out_entry_found =
http_auth_cache->Lookup(GURL("http://whatever.com/"), "",
net::HttpAuth::AUTH_SCHEME_BASIC) != nullptr;
}
} // namespace } // namespace
class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness { class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness {
...@@ -37,6 +73,10 @@ class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness { ...@@ -37,6 +73,10 @@ class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness {
void SetUp() override { void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp(); ChromeRenderViewHostTestHarness::SetUp();
system_request_context_getter_ = new net::TestURLRequestContextGetter(
content::BrowserThread::GetTaskRunnerForThread(
content::BrowserThread::IO));
signin_browser_context_ = base::MakeUnique<TestingProfile>(); signin_browser_context_ = base::MakeUnique<TestingProfile>();
signin_ui_web_contents_ = base::WrapUnique<content::WebContents>( signin_ui_web_contents_ = base::WrapUnique<content::WebContents>(
...@@ -51,6 +91,10 @@ class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness { ...@@ -51,6 +91,10 @@ class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness {
GetSigninPartitionManager()->SetClearStoragePartitionTaskForTesting( GetSigninPartitionManager()->SetClearStoragePartitionTaskForTesting(
base::Bind(&SigninPartitionManagerTest::ClearStoragePartitionTask, base::Bind(&SigninPartitionManagerTest::ClearStoragePartitionTask,
base::Unretained(this))); base::Unretained(this)));
GetSigninPartitionManager()
->SetGetSystemURLRequestContextGetterTaskForTesting(base::BindRepeating(
&SigninPartitionManagerTest::GetSystemURLRequestContextGetter,
base::Unretained(this)));
} }
void TearDown() override { void TearDown() override {
...@@ -89,12 +133,29 @@ class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness { ...@@ -89,12 +133,29 @@ class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness {
pending_clear_tasks_.clear(); pending_clear_tasks_.clear();
} }
std::string RunStartSigninSesssion(content::WebContents* webcontents) {
std::string partition_name;
base::RunLoop loop;
GetSigninPartitionManager()->StartSigninSession(
webcontents,
base::BindOnce(&StorePartitionNameAndQuitLoop, &loop, &partition_name));
loop.Run();
return partition_name;
}
net::URLRequestContextGetter* GetSystemURLRequestContextGetter() {
return system_request_context_getter_.get();
}
private: private:
void ClearStoragePartitionTask(content::StoragePartition* partition, void ClearStoragePartitionTask(content::StoragePartition* partition,
base::OnceClosure clear_done_closure) { base::OnceClosure clear_done_closure) {
pending_clear_tasks_.push_back({partition, std::move(clear_done_closure)}); pending_clear_tasks_.push_back({partition, std::move(clear_done_closure)});
} }
scoped_refptr<net::TestURLRequestContextGetter>
system_request_context_getter_;
std::unique_ptr<TestingProfile> signin_browser_context_; std::unique_ptr<TestingProfile> signin_browser_context_;
// Web contents of the sign-in UI, embedder of the signin-frame webview. // Web contents of the sign-in UI, embedder of the signin-frame webview.
...@@ -108,20 +169,22 @@ class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness { ...@@ -108,20 +169,22 @@ class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness {
TEST_F(SigninPartitionManagerTest, TestSubsequentAttempts) { TEST_F(SigninPartitionManagerTest, TestSubsequentAttempts) {
// First sign-in attempt // First sign-in attempt
GetSigninPartitionManager()->StartSigninSession(signin_ui_web_contents());
std::string signin_partition_name_1 = std::string signin_partition_name_1 =
GetSigninPartitionManager()->GetCurrentStoragePartitionName(); RunStartSigninSesssion(signin_ui_web_contents());
auto* signin_partition_1 = auto* signin_partition_1 =
GetSigninPartitionManager()->GetCurrentStoragePartition(); GetSigninPartitionManager()->GetCurrentStoragePartition();
EXPECT_FALSE(signin_partition_name_1.empty()); EXPECT_FALSE(signin_partition_name_1.empty());
EXPECT_EQ(signin_partition_name_1,
GetSigninPartitionManager()->GetCurrentStoragePartitionName());
// Second sign-in attempt // Second sign-in attempt
GetSigninPartitionManager()->StartSigninSession(signin_ui_web_contents());
std::string signin_partition_name_2 = std::string signin_partition_name_2 =
GetSigninPartitionManager()->GetCurrentStoragePartitionName(); RunStartSigninSesssion(signin_ui_web_contents());
auto* signin_partition_2 = auto* signin_partition_2 =
GetSigninPartitionManager()->GetCurrentStoragePartition(); GetSigninPartitionManager()->GetCurrentStoragePartition();
EXPECT_FALSE(signin_partition_name_2.empty()); EXPECT_FALSE(signin_partition_name_2.empty());
EXPECT_EQ(signin_partition_name_2,
GetSigninPartitionManager()->GetCurrentStoragePartitionName());
// Make sure that the StoragePartition has not been re-used. // Make sure that the StoragePartition has not been re-used.
EXPECT_NE(signin_partition_name_1, signin_partition_name_2); EXPECT_NE(signin_partition_name_1, signin_partition_name_2);
...@@ -148,5 +211,32 @@ TEST_F(SigninPartitionManagerTest, TestSubsequentAttempts) { ...@@ -148,5 +211,32 @@ TEST_F(SigninPartitionManagerTest, TestSubsequentAttempts) {
EXPECT_TRUE(closure_called); EXPECT_TRUE(closure_called);
} }
TEST_F(SigninPartitionManagerTest, HttpAuthCacheTransferred) {
base::RunLoop loop_prepare;
content::BrowserThread::PostTaskAndReply(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(AddEntryToHttpAuthCache,
base::RetainedRef(GetSystemURLRequestContextGetter())),
loop_prepare.QuitClosure());
loop_prepare.Run();
RunStartSigninSesssion(signin_ui_web_contents());
net::URLRequestContextGetter* signin_url_request_context_getter =
GetSigninPartitionManager()
->GetCurrentStoragePartition()
->GetURLRequestContext();
bool entry_found = false;
base::RunLoop loop_check;
content::BrowserThread::PostTaskAndReply(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(IsEntryInHttpAuthCache,
base::RetainedRef(signin_url_request_context_getter),
&entry_found),
loop_check.QuitClosure());
loop_check.Run();
EXPECT_TRUE(entry_found);
}
} // namespace login } // namespace login
} // namespace chromeos } // namespace chromeos
...@@ -707,13 +707,16 @@ void EnrollmentScreenHandler::DoShow() { ...@@ -707,13 +707,16 @@ void EnrollmentScreenHandler::DoShow() {
login::SigninPartitionManager* signin_partition_manager = login::SigninPartitionManager* signin_partition_manager =
login::SigninPartitionManager::Factory::GetForBrowserContext( login::SigninPartitionManager::Factory::GetForBrowserContext(
Profile::FromWebUI(web_ui())); Profile::FromWebUI(web_ui()));
signin_partition_manager->StartSigninSession(web_ui()->GetWebContents()); signin_partition_manager->StartSigninSession(
web_ui()->GetWebContents(),
base::BindOnce(&EnrollmentScreenHandler::DoShowWithPartition,
weak_ptr_factory_.GetWeakPtr()));
}
// Then leave it running forever. void EnrollmentScreenHandler::DoShowWithPartition(
const std::string& partition_name) {
base::DictionaryValue screen_data; base::DictionaryValue screen_data;
screen_data.SetString( screen_data.SetString("webviewPartitionName", partition_name);
"webviewPartitionName",
signin_partition_manager->GetCurrentStoragePartitionName());
screen_data.SetString("gaiaUrl", GaiaUrls::GetInstance()->gaia_url().spec()); screen_data.SetString("gaiaUrl", GaiaUrls::GetInstance()->gaia_url().spec());
screen_data.SetString("clientId", screen_data.SetString("clientId",
GaiaUrls::GetInstance()->oauth2_chrome_client_id()); GaiaUrls::GetInstance()->oauth2_chrome_client_id());
......
...@@ -118,6 +118,9 @@ class EnrollmentScreenHandler ...@@ -118,6 +118,9 @@ class EnrollmentScreenHandler
// Shows the screen. // Shows the screen.
void DoShow(); void DoShow();
// Shows the screen.
void DoShowWithPartition(const std::string& partition_name);
// Returns true if current visible screen is the enrollment sign-in page. // Returns true if current visible screen is the enrollment sign-in page.
bool IsOnEnrollmentScreen() const; bool IsOnEnrollmentScreen() const;
......
...@@ -300,31 +300,39 @@ void GaiaScreenHandler::DisableRestrictiveProxyCheckForTest() { ...@@ -300,31 +300,39 @@ void GaiaScreenHandler::DisableRestrictiveProxyCheckForTest() {
} }
void GaiaScreenHandler::LoadGaia(const GaiaContext& context) { void GaiaScreenHandler::LoadGaia(const GaiaContext& context) {
// Start a new session with SigninPartitionManager, generating a unique
// StoragePartition.
login::SigninPartitionManager* signin_partition_manager =
login::SigninPartitionManager::Factory::GetForBrowserContext(
Profile::FromWebUI(web_ui()));
signin_partition_manager->StartSigninSession(
web_ui()->GetWebContents(),
base::BindOnce(&GaiaScreenHandler::LoadGaiaWithPartition,
weak_factory_.GetWeakPtr(), context));
}
void GaiaScreenHandler::LoadGaiaWithPartition(
const GaiaContext& context,
const std::string& partition_name) {
std::unique_ptr<std::string> version = std::make_unique<std::string>(); std::unique_ptr<std::string> version = std::make_unique<std::string>();
std::unique_ptr<bool> consent = std::make_unique<bool>(); std::unique_ptr<bool> consent = std::make_unique<bool>();
base::OnceClosure get_version_and_consent = base::OnceClosure get_version_and_consent =
base::BindOnce(&GetVersionAndConsent, base::Unretained(version.get()), base::BindOnce(&GetVersionAndConsent, base::Unretained(version.get()),
base::Unretained(consent.get())); base::Unretained(consent.get()));
base::OnceClosure load_gaia = base::BindOnce( base::OnceClosure load_gaia = base::BindOnce(
&GaiaScreenHandler::LoadGaiaWithVersionAndConsent, &GaiaScreenHandler::LoadGaiaWithPartitionAndVersionAndConsent,
weak_factory_.GetWeakPtr(), context, base::Owned(version.release()), weak_factory_.GetWeakPtr(), context, partition_name,
base::Owned(consent.release())); base::Owned(version.release()), base::Owned(consent.release()));
base::PostTaskWithTraitsAndReply( base::PostTaskWithTraitsAndReply(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
std::move(get_version_and_consent), std::move(load_gaia)); std::move(get_version_and_consent), std::move(load_gaia));
} }
void GaiaScreenHandler::LoadGaiaWithVersionAndConsent( void GaiaScreenHandler::LoadGaiaWithPartitionAndVersionAndConsent(
const GaiaContext& context, const GaiaContext& context,
const std::string& partition_name,
const std::string* platform_version, const std::string* platform_version,
const bool* collect_stats_consent) { const bool* collect_stats_consent) {
// Start a new session with SigninPartitionManager, generating a a unique
// StoragePartition.
login::SigninPartitionManager* signin_partition_manager =
login::SigninPartitionManager::Factory::GetForBrowserContext(
Profile::FromWebUI(web_ui()));
signin_partition_manager->StartSigninSession(web_ui()->GetWebContents());
base::DictionaryValue params; base::DictionaryValue params;
params.SetBoolean("forceReload", context.force_reload); params.SetBoolean("forceReload", context.force_reload);
...@@ -400,8 +408,8 @@ void GaiaScreenHandler::LoadGaiaWithVersionAndConsent( ...@@ -400,8 +408,8 @@ void GaiaScreenHandler::LoadGaiaWithVersionAndConsent(
// sending device statistics. // sending device statistics.
if (*collect_stats_consent) if (*collect_stats_consent)
params.SetString("lsbReleaseBoard", base::SysInfo::GetLsbReleaseBoard()); params.SetString("lsbReleaseBoard", base::SysInfo::GetLsbReleaseBoard());
params.SetString("webviewPartitionName",
signin_partition_manager->GetCurrentStoragePartitionName()); params.SetString("webviewPartitionName", partition_name);
frame_state_ = FRAME_STATE_LOADING; frame_state_ = FRAME_STATE_LOADING;
CallJS("loadAuthExtension", params); CallJS("loadAuthExtension", params);
......
...@@ -64,7 +64,14 @@ class GaiaScreenHandler : public BaseScreenHandler, ...@@ -64,7 +64,14 @@ class GaiaScreenHandler : public BaseScreenHandler,
// Callback that loads GAIA after version and stat consent information has // Callback that loads GAIA after version and stat consent information has
// been retrieved. // been retrieved.
void LoadGaiaWithVersionAndConsent(const GaiaContext& context, void LoadGaiaWithPartition(const GaiaContext& context,
const std::string& partition_name);
// Callback that loads GAIA after version and stat consent information has
// been retrieved.
void LoadGaiaWithPartitionAndVersionAndConsent(
const GaiaContext& context,
const std::string& partition_name,
const std::string* platform_version, const std::string* platform_version,
const bool* collect_stats_consent); const bool* collect_stats_consent);
......
...@@ -685,7 +685,8 @@ void SigninScreenHandler::UpdateStateInternal(NetworkError::ErrorReason reason, ...@@ -685,7 +685,8 @@ void SigninScreenHandler::UpdateStateInternal(NetworkError::ErrorReason reason,
// Skip "update" notification about OFFLINE state from // Skip "update" notification about OFFLINE state from
// NetworkStateInformer if previous notification already was // NetworkStateInformer if previous notification already was
// delayed. // delayed.
if ((state == NetworkStateInformer::OFFLINE || has_pending_auth_ui_) && if ((state == NetworkStateInformer::OFFLINE ||
network_state_ignored_until_proxy_auth_) &&
!force_update && !update_state_closure_.IsCancelled()) { !force_update && !update_state_closure_.IsCancelled()) {
return; return;
} }
...@@ -693,7 +694,7 @@ void SigninScreenHandler::UpdateStateInternal(NetworkError::ErrorReason reason, ...@@ -693,7 +694,7 @@ void SigninScreenHandler::UpdateStateInternal(NetworkError::ErrorReason reason,
update_state_closure_.Cancel(); update_state_closure_.Cancel();
if ((state == NetworkStateInformer::OFFLINE && !force_update) || if ((state == NetworkStateInformer::OFFLINE && !force_update) ||
has_pending_auth_ui_) { network_state_ignored_until_proxy_auth_) {
update_state_closure_.Reset( update_state_closure_.Reset(
base::Bind(&SigninScreenHandler::UpdateStateInternal, base::Bind(&SigninScreenHandler::UpdateStateInternal,
weak_factory_.GetWeakPtr(), weak_factory_.GetWeakPtr(),
...@@ -789,7 +790,6 @@ void SigninScreenHandler::UpdateStateInternal(NetworkError::ErrorReason reason, ...@@ -789,7 +790,6 @@ void SigninScreenHandler::UpdateStateInternal(NetworkError::ErrorReason reason,
if (is_gaia_loading_timeout) { if (is_gaia_loading_timeout) {
LOG(WARNING) << "Retry frame load due to loading timeout."; LOG(WARNING) << "Retry frame load due to loading timeout.";
LOG(ERROR) << "UpdateStateInternal reload 4";
reload_gaia.ScheduleCall(); reload_gaia.ScheduleCall();
} }
...@@ -1082,20 +1082,33 @@ void SigninScreenHandler::Observe(int type, ...@@ -1082,20 +1082,33 @@ void SigninScreenHandler::Observe(int type,
const content::NotificationDetails& details) { const content::NotificationDetails& details) {
switch (type) { switch (type) {
case chrome::NOTIFICATION_AUTH_NEEDED: { case chrome::NOTIFICATION_AUTH_NEEDED: {
has_pending_auth_ui_ = true; network_state_ignored_until_proxy_auth_ = true;
break; break;
} }
case chrome::NOTIFICATION_AUTH_SUPPLIED: case chrome::NOTIFICATION_AUTH_SUPPLIED: {
has_pending_auth_ui_ = false; if (IsGaiaHiddenByError()) {
// Reload auth extension as proxy credentials are supplied. // Start listening to network state notifications immediately, hoping
if (!IsSigninScreenHiddenByError() && ui_state_ == UI_STATE_GAIA_SIGNIN) // that the network will switch to ONLINE soon.
ReloadGaia(true);
update_state_closure_.Cancel(); update_state_closure_.Cancel();
ReenableNetworkStateUpdatesAfterProxyAuth();
} else {
// Gaia is not hidden behind an error yet. Discard last cached network
// state notification and wait for |kOfflineTimeoutSec| before
// considering network update notifications again (hoping the network
// will become ONLINE by then).
update_state_closure_.Cancel();
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(
&SigninScreenHandler::ReenableNetworkStateUpdatesAfterProxyAuth,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromSeconds(kOfflineTimeoutSec));
}
break; break;
}
case chrome::NOTIFICATION_AUTH_CANCELLED: { case chrome::NOTIFICATION_AUTH_CANCELLED: {
// Don't reload auth extension if proxy auth dialog was cancelled.
has_pending_auth_ui_ = false;
update_state_closure_.Cancel(); update_state_closure_.Cancel();
ReenableNetworkStateUpdatesAfterProxyAuth();
break; break;
} }
default: default:
...@@ -1103,6 +1116,10 @@ void SigninScreenHandler::Observe(int type, ...@@ -1103,6 +1116,10 @@ void SigninScreenHandler::Observe(int type,
} }
} }
void SigninScreenHandler::ReenableNetworkStateUpdatesAfterProxyAuth() {
network_state_ignored_until_proxy_auth_ = false;
}
void SigninScreenHandler::SuspendDone(const base::TimeDelta& sleep_duration) { void SigninScreenHandler::SuspendDone(const base::TimeDelta& sleep_duration) {
for (user_manager::User* user : for (user_manager::User* user :
user_manager::UserManager::Get()->GetUnlockUsers()) { user_manager::UserManager::Get()->GetUnlockUsers()) {
......
...@@ -483,6 +483,10 @@ class SigninScreenHandler ...@@ -483,6 +483,10 @@ class SigninScreenHandler
// Called when the cros property controlling allowed input methods changes. // Called when the cros property controlling allowed input methods changes.
void OnAllowedInputMethodsChanged(); void OnAllowedInputMethodsChanged();
// After proxy auth information has been supplied, this function re-enables
// responding to network state notifications.
void ReenableNetworkStateUpdatesAfterProxyAuth();
// Current UI state of the signin screen. // Current UI state of the signin screen.
UIState ui_state_ = UI_STATE_UNKNOWN; UIState ui_state_ = UI_STATE_UNKNOWN;
...@@ -522,10 +526,10 @@ class SigninScreenHandler ...@@ -522,10 +526,10 @@ class SigninScreenHandler
std::unique_ptr<CrosSettings::ObserverSubscription> std::unique_ptr<CrosSettings::ObserverSubscription>
allowed_input_methods_subscription_; allowed_input_methods_subscription_;
// Whether there is an auth UI pending. This flag is set on receiving // Whether we're currently ignoring network state updates because a proxy auth
// NOTIFICATION_AUTH_NEEDED and reset on either NOTIFICATION_AUTH_SUPPLIED or // UI pending (or we're waiting for a grace period after the proxy auth UI is
// NOTIFICATION_AUTH_CANCELLED. // finished for the network to switch into the ONLINE state).
bool has_pending_auth_ui_ = false; bool network_state_ignored_until_proxy_auth_ = false;
// Used for pending GAIA reloads. // Used for pending GAIA reloads.
NetworkError::ErrorReason gaia_reload_reason_ = NetworkError::ErrorReason gaia_reload_reason_ =
......
...@@ -508,6 +508,12 @@ bool BaseTestServer::GenerateArguments(base::DictionaryValue* arguments) const { ...@@ -508,6 +508,12 @@ bool BaseTestServer::GenerateArguments(base::DictionaryValue* arguments) const {
arguments->Set("no-anonymous-ftp-user", std::make_unique<base::Value>()); arguments->Set("no-anonymous-ftp-user", std::make_unique<base::Value>());
} }
if (redirect_connect_to_localhost_) {
DCHECK_EQ(TYPE_BASIC_AUTH_PROXY, type_);
arguments->Set("redirect-connect-to-localhost",
std::make_unique<base::Value>());
}
if (UsingSSL(type_)) { if (UsingSSL(type_)) {
// Check the certificate arguments of the HTTPS server. // Check the certificate arguments of the HTTPS server.
base::FilePath certificate_path(certificates_dir_); base::FilePath certificate_path(certificates_dir_);
......
...@@ -370,6 +370,11 @@ class BaseTestServer { ...@@ -370,6 +370,11 @@ class BaseTestServer {
no_anonymous_ftp_user_ = no_anonymous_ftp_user; no_anonymous_ftp_user_ = no_anonymous_ftp_user;
} }
// Redirect proxied CONNECT requests to localhost.
void set_redirect_connect_to_localhost(bool redirect_connect_to_localhost) {
redirect_connect_to_localhost_ = redirect_connect_to_localhost;
}
// Marks the root certificate of an HTTPS test server as trusted for // Marks the root certificate of an HTTPS test server as trusted for
// the duration of tests. // the duration of tests.
bool LoadTestRootCert() const WARN_UNUSED_RESULT; bool LoadTestRootCert() const WARN_UNUSED_RESULT;
...@@ -454,6 +459,9 @@ class BaseTestServer { ...@@ -454,6 +459,9 @@ class BaseTestServer {
// Disable creation of anonymous FTP user? // Disable creation of anonymous FTP user?
bool no_anonymous_ftp_user_ = false; bool no_anonymous_ftp_user_ = false;
// Redirect proxied CONNECT requests to localhost?
bool redirect_connect_to_localhost_ = false;
std::unique_ptr<ScopedPortException> allowed_port_; std::unique_ptr<ScopedPortException> allowed_port_;
DISALLOW_COPY_AND_ASSIGN(BaseTestServer); DISALLOW_COPY_AND_ASSIGN(BaseTestServer);
......
...@@ -1765,6 +1765,7 @@ class BasicAuthProxyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -1765,6 +1765,7 @@ class BasicAuthProxyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
""" """
_AUTH_CREDENTIAL = 'Basic Zm9vOmJhcg==' # foo:bar _AUTH_CREDENTIAL = 'Basic Zm9vOmJhcg==' # foo:bar
redirect_connect_to_localhost = False;
def parse_request(self): def parse_request(self):
"""Overrides parse_request to check credential.""" """Overrides parse_request to check credential."""
...@@ -1850,6 +1851,9 @@ class BasicAuthProxyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -1850,6 +1851,9 @@ class BasicAuthProxyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.send_response(400) self.send_response(400)
self.end_headers() self.end_headers()
if BasicAuthProxyRequestHandler.redirect_connect_to_localhost:
host = "127.0.0.1"
try: try:
sock = socket.create_connection((host, port)) sock = socket.create_connection((host, port))
self.send_response(200, 'Connection established') self.send_response(200, 'Connection established')
...@@ -2108,6 +2112,8 @@ class ServerRunner(testserver_base.TestServerRunner): ...@@ -2108,6 +2112,8 @@ class ServerRunner(testserver_base.TestServerRunner):
print 'Echo UDP server started on port %d...' % server.server_port print 'Echo UDP server started on port %d...' % server.server_port
server_data['port'] = server.server_port server_data['port'] = server.server_port
elif self.options.server_type == SERVER_BASIC_AUTH_PROXY: elif self.options.server_type == SERVER_BASIC_AUTH_PROXY:
BasicAuthProxyRequestHandler.redirect_connect_to_localhost = \
self.options.redirect_connect_to_localhost
server = HTTPServer((host, port), BasicAuthProxyRequestHandler) server = HTTPServer((host, port), BasicAuthProxyRequestHandler)
print 'BasicAuthProxy server started on port %d...' % server.server_port print 'BasicAuthProxy server started on port %d...' % server.server_port
server_data['port'] = server.server_port server_data['port'] = server.server_port
...@@ -2323,6 +2329,12 @@ class ServerRunner(testserver_base.TestServerRunner): ...@@ -2323,6 +2329,12 @@ class ServerRunner(testserver_base.TestServerRunner):
action='store_true') action='store_true')
self.option_parser.add_option('--token-binding-params', action='append', self.option_parser.add_option('--token-binding-params', action='append',
default=[], type='int') default=[], type='int')
self.option_parser.add_option('--redirect-connect-to-localhost',
dest='redirect_connect_to_localhost',
default=False, action='store_true',
help='If set, the Proxy server will connect '
'to localhost instead of the requested URL '
'on CONNECT requests')
if __name__ == '__main__': if __name__ == '__main__':
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment