summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-31 17:42:51 +0000
committerdcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-31 17:42:51 +0000
commit9faccc4fecfc865078149ae258aa53452831ec9b (patch)
treed91f46b33fe9f47bef99cbb50de6c953af7ae0cc
parentb7d2489365a2d91f13a966cc47ca88751567a024 (diff)
downloadchromium_src-9faccc4fecfc865078149ae258aa53452831ec9b.zip
chromium_src-9faccc4fecfc865078149ae258aa53452831ec9b.tar.gz
chromium_src-9faccc4fecfc865078149ae258aa53452831ec9b.tar.bz2
Revert 203417 "Identity API: switch WebAuthFlow dialog to compon..."
> Identity API: switch WebAuthFlow dialog to component app > > All Identity API UI is moving into a webview tag inside a component > app, allowing Chrome Apps to be isolated from the browser. > > This change updates WebAuthFlow, which controls the dialogs, to invoke > the component app instead of a browser pop-up. > > BUG=228908 > (This is part of step #6 in the description.) > > Review URL: https://chromiumcodereview.appspot.com/15897006 TBR=courage@chromium.org Review URL: https://codereview.chromium.org/16212008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203432 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc27
-rw-r--r--chrome/browser/extensions/api/identity/gaia_web_auth_flow.h5
-rw-r--r--chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc5
-rw-r--r--chrome/browser/extensions/api/identity/identity_api.cc30
-rw-r--r--chrome/browser/extensions/api/identity/identity_api.h1
-rw-r--r--chrome/browser/extensions/api/identity/identity_apitest.cc77
-rw-r--r--chrome/browser/extensions/api/identity/web_auth_flow.cc258
-rw-r--r--chrome/browser/extensions/api/identity/web_auth_flow.h74
-rw-r--r--chrome/test/data/extensions/api_test/identity/five_hundred.html4
-rw-r--r--chrome/test/data/extensions/api_test/identity/five_hundred.html.mock-http-headers2
10 files changed, 161 insertions, 322 deletions
diff --git a/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc b/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
index cdfa8ff..d2b98eb 100644
--- a/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
+++ b/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
@@ -15,10 +15,12 @@ namespace extensions {
GaiaWebAuthFlow::GaiaWebAuthFlow(Delegate* delegate,
Profile* profile,
+ chrome::HostDesktopType host_desktop_type,
const std::string& extension_id,
const OAuth2Info& oauth2_info)
: delegate_(delegate),
- profile_(profile) {
+ profile_(profile),
+ host_desktop_type_(host_desktop_type) {
const char kOAuth2RedirectPathFormat[] = "/%s#";
const char kOAuth2AuthorizeFormat[] =
"%s?response_type=token&approval_prompt=force&authuser=0&"
@@ -77,23 +79,9 @@ void GaiaWebAuthFlow::OnUbertokenFailure(const GoogleServiceAuthError& error) {
}
void GaiaWebAuthFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) {
- GaiaWebAuthFlow::Failure gaia_failure;
-
- switch (failure) {
- case WebAuthFlow::WINDOW_CLOSED:
- gaia_failure = GaiaWebAuthFlow::WINDOW_CLOSED;
- break;
- case WebAuthFlow::LOAD_FAILED:
- gaia_failure = GaiaWebAuthFlow::LOAD_FAILED;
- break;
- default:
- NOTREACHED() << "Unexpected error from web auth flow: " << failure;
- gaia_failure = GaiaWebAuthFlow::LOAD_FAILED;
- break;
- }
-
+ DCHECK(failure == WebAuthFlow::WINDOW_CLOSED);
delegate_->OnGaiaFlowFailure(
- gaia_failure,
+ GaiaWebAuthFlow::WINDOW_CLOSED,
GoogleServiceAuthError(GoogleServiceAuthError::NONE),
std::string());
}
@@ -163,10 +151,13 @@ void GaiaWebAuthFlow::OnAuthFlowTitleChange(const std::string& title) {
}
scoped_ptr<WebAuthFlow> GaiaWebAuthFlow::CreateWebAuthFlow(GURL url) {
+ gfx::Rect initial_bounds;
return scoped_ptr<WebAuthFlow>(new WebAuthFlow(this,
profile_,
url,
- WebAuthFlow::INTERACTIVE));
+ WebAuthFlow::INTERACTIVE,
+ initial_bounds,
+ host_desktop_type_));
}
} // extensions
diff --git a/chrome/browser/extensions/api/identity/gaia_web_auth_flow.h b/chrome/browser/extensions/api/identity/gaia_web_auth_flow.h
index c77ddf3..8f9dba7 100644
--- a/chrome/browser/extensions/api/identity/gaia_web_auth_flow.h
+++ b/chrome/browser/extensions/api/identity/gaia_web_auth_flow.h
@@ -42,14 +42,12 @@ class GaiaWebAuthFlow : public UbertokenConsumer, public WebAuthFlow::Delegate {
WINDOW_CLOSED, // Window closed by user.
INVALID_REDIRECT, // Redirect parse error.
SERVICE_AUTH_ERROR, // Non-OAuth related authentication error
- OAUTH_ERROR, // Flow reached final redirect, which contained an error.
- LOAD_FAILED // An auth flow page failed to load.
+ OAUTH_ERROR // Flow reached final redirect, which contained an error.
};
class Delegate {
public:
// Called when the flow fails prior to the final OAuth redirect,
- // TODO(courage): LOAD_FAILURE descriptions?
virtual void OnGaiaFlowFailure(Failure failure,
GoogleServiceAuthError service_error,
const std::string& oauth_error) = 0;
@@ -60,6 +58,7 @@ class GaiaWebAuthFlow : public UbertokenConsumer, public WebAuthFlow::Delegate {
GaiaWebAuthFlow(Delegate* delegate,
Profile* profile,
+ chrome::HostDesktopType host_desktop_type,
const std::string& extension_id,
const OAuth2Info& oauth2_info);
virtual ~GaiaWebAuthFlow();
diff --git a/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc b/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc
index 01fed2d..787351fd 100644
--- a/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc
+++ b/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc
@@ -20,7 +20,9 @@ class FakeWebAuthFlow : public WebAuthFlow {
: WebAuthFlow(delegate,
NULL,
GURL(),
- WebAuthFlow::INTERACTIVE) {}
+ WebAuthFlow::INTERACTIVE,
+ gfx::Rect(),
+ chrome::GetActiveDesktop()) {}
virtual void Start() OVERRIDE {}
};
@@ -33,6 +35,7 @@ class TestGaiaWebAuthFlow : public GaiaWebAuthFlow {
GoogleServiceAuthError::State ubertoken_error_state)
: GaiaWebAuthFlow(delegate,
NULL,
+ chrome::GetActiveDesktop(),
"extension_id",
oauth2_info),
ubertoken_error_(ubertoken_error_state) {}
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index ce648c6..e8f0aaf 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -15,19 +15,24 @@
#include "base/values.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/extensions/extension_function_dispatcher.h"
+#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/permissions_updater.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/signin/token_service.h"
#include "chrome/browser/signin/token_service_factory.h"
+#include "chrome/browser/ui/browser.h"
#include "chrome/common/extensions/api/identity.h"
#include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
#include "chrome/common/url_constants.h"
+#include "content/public/common/page_transition_types.h"
#include "google_apis/gaia/gaia_constants.h"
#include "googleurl/src/gurl.h"
+#include "ui/base/window_open_disposition.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/user_manager.h"
@@ -45,7 +50,6 @@ const char kUserNotSignedIn[] = "The user is not signed in.";
const char kInteractionRequired[] = "User interaction required.";
const char kInvalidRedirect[] = "Did not redirect to the right URL.";
const char kOffTheRecord[] = "Identity API is disabled in incognito windows.";
-const char kPageLoadFailure[] = "Authorization page could not be loaded.";
const int kCachedIssueAdviceTTLSeconds = 1;
} // namespace identity_constants
@@ -313,12 +317,6 @@ void IdentityGetAuthTokenFunction::OnGaiaFlowFailure(
error = MapOAuth2ErrorToDescription(oauth_error);
break;
- // TODO(courage): load failure tests
-
- case GaiaWebAuthFlow::LOAD_FAILED:
- error = identity_constants::kPageLoadFailure;
- break;
-
default:
NOTREACHED() << "Unexpected error from gaia web auth flow: " << failure;
error = identity_constants::kInvalidRedirect;
@@ -358,10 +356,14 @@ void IdentityGetAuthTokenFunction::ShowLoginPopup() {
void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog(
const IssueAdviceInfo& issue_advice) {
+ Browser* current_browser = this->GetCurrentBrowser();
+ chrome::HostDesktopType host_desktop_type =
+ current_browser ? current_browser->host_desktop_type()
+ : chrome::GetActiveDesktop();
const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
gaia_web_auth_flow_.reset(new GaiaWebAuthFlow(
- this, profile(), GetExtension()->id(), oauth2_info));
+ this, profile(), host_desktop_type, GetExtension()->id(), oauth2_info));
gaia_web_auth_flow_->Start();
}
@@ -457,9 +459,16 @@ bool IdentityLaunchWebAuthFlowFunction::RunImpl() {
// scheme for this version of the API.)
InitFinalRedirectURLPrefix(GetExtension()->id());
+ gfx::Rect initial_bounds;
+
AddRef(); // Balanced in OnAuthFlowSuccess/Failure.
- auth_flow_.reset(new WebAuthFlow(this, profile(), auth_url, mode));
+ Browser* current_browser = this->GetCurrentBrowser();
+ chrome::HostDesktopType host_desktop_type = current_browser ?
+ current_browser->host_desktop_type() : chrome::GetActiveDesktop();
+ auth_flow_.reset(new WebAuthFlow(
+ this, profile(), auth_url, mode, initial_bounds,
+ host_desktop_type));
auth_flow_->Start();
return true;
}
@@ -486,9 +495,6 @@ void IdentityLaunchWebAuthFlowFunction::OnAuthFlowFailure(
case WebAuthFlow::INTERACTION_REQUIRED:
error_ = identity_constants::kInteractionRequired;
break;
- case WebAuthFlow::LOAD_FAILED:
- error_ = identity_constants::kPageLoadFailure;
- break;
default:
NOTREACHED() << "Unexpected error from web auth flow: " << failure;
error_ = identity_constants::kInvalidRedirect;
diff --git a/chrome/browser/extensions/api/identity/identity_api.h b/chrome/browser/extensions/api/identity/identity_api.h
index b2b85c3..dc63c42 100644
--- a/chrome/browser/extensions/api/identity/identity_api.h
+++ b/chrome/browser/extensions/api/identity/identity_api.h
@@ -41,7 +41,6 @@ extern const char kUserNotSignedIn[];
extern const char kInteractionRequired[];
extern const char kInvalidRedirect[];
extern const char kOffTheRecord[];
-extern const char kPageLoadFailure[];
} // namespace identity_constants
// identity.getAuthToken fetches an OAuth 2 function for the
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index 1ca9740..6514e1e 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -6,7 +6,6 @@
#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/identity/identity_api.h"
-#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
@@ -190,37 +189,6 @@ BrowserContextKeyedService* IdentityAPITestFactory(
return new IdentityAPI(static_cast<Profile*>(profile));
}
-// Waits for a specific GURL to generate a NOTIFICATION_LOAD_STOP
-// event, and closes the window embedding the webcontents.
-class WaitForGURLAndCloseWindow : public content::WindowedNotificationObserver {
- public:
- explicit WaitForGURLAndCloseWindow(GURL url)
- : WindowedNotificationObserver(
- content::NOTIFICATION_LOAD_STOP,
- content::NotificationService::AllSources()),
- url_(url) {}
-
- // NotificationObserver:
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE {
- content::NavigationController* web_auth_flow_controller =
- content::Source<content::NavigationController>(source).ptr();
- content::WebContents* web_contents =
- web_auth_flow_controller->GetWebContents();
-
- if (web_contents->GetURL() == url_) {
- web_contents->GetEmbedderWebContents()->Close();
- // Condtionally invoke parent class so that Wait will not exit
- // until the target URL arrives.
- content::WindowedNotificationObserver::Observe(type, source, details);
- }
- }
-
- private:
- GURL url_;
-};
-
} // namespace
class MockGetAuthTokenFunction : public IdentityGetAuthTokenFunction {
@@ -577,23 +545,6 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
- InteractiveApprovalLoadFailed) {
- scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
- func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- EXPECT_CALL(*func.get(), HasLoginToken())
- .WillOnce(Return(true));
- TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
- TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
- EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
- func->set_scope_ui_failure(GaiaWebAuthFlow::LOAD_FAILED);
- std::string error = utils::RunFunctionAndReturnError(
- func.get(), "[{\"interactive\": true}]", browser());
- EXPECT_EQ(std::string(errors::kPageLoadFailure), error);
- EXPECT_FALSE(func->login_ui_shown());
- EXPECT_TRUE(func->scope_ui_shown());
-}
-
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
InteractiveApprovalInvalidRedirect) {
scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
@@ -1010,13 +961,16 @@ IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, UserCloseWindow) {
utils::CreateEmptyExtension());
function->set_extension(empty_extension.get());
- WaitForGURLAndCloseWindow popup_observer(auth_url);
+ content::WindowedNotificationObserver popup_observer(
+ chrome::NOTIFICATION_BROWSER_WINDOW_READY,
+ content::NotificationService::AllSources());
std::string args = "[{\"interactive\": true, \"url\": \"" +
auth_url.spec() + "\"}]";
RunFunctionAsync(function, args);
popup_observer.Wait();
+ content::Source<Browser>(popup_observer.source())->window()->Close();
EXPECT_EQ(std::string(errors::kUserRejected), WaitForError(function));
}
@@ -1044,29 +998,6 @@ IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, InteractionRequired) {
EXPECT_EQ(std::string(errors::kInteractionRequired), error);
}
-IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, LoadFailed) {
- net::SpawnedTestServer https_server(
- net::SpawnedTestServer::TYPE_HTTPS,
- net::SpawnedTestServer::kLocalhost,
- base::FilePath(FILE_PATH_LITERAL(
- "chrome/test/data/extensions/api_test/identity")));
- ASSERT_TRUE(https_server.Start());
- GURL auth_url(https_server.GetURL("files/five_hundred.html"));
-
- scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
- new IdentityLaunchWebAuthFlowFunction());
- scoped_refptr<Extension> empty_extension(
- utils::CreateEmptyExtension());
- function->set_extension(empty_extension.get());
-
- std::string args = "[{\"interactive\": true, \"url\": \"" +
- auth_url.spec() + "\"}]";
- std::string error = utils::RunFunctionAndReturnError(function, args,
- browser());
-
- EXPECT_EQ(std::string(errors::kPageLoadFailure), error);
-}
-
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, NonInteractiveSuccess) {
scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
new IdentityLaunchWebAuthFlowFunction());
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.cc b/chrome/browser/extensions/api/identity/web_auth_flow.cc
index fc14858..d4347d4 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.cc
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.cc
@@ -4,31 +4,26 @@
#include "chrome/browser/extensions/api/identity/web_auth_flow.h"
-#include "base/base64.h"
#include "base/location.h"
#include "base/message_loop.h"
-#include "base/string_util.h"
#include "base/utf_string_conversions.h"
-#include "chrome/browser/extensions/component_loader.h"
-#include "chrome/browser/extensions/event_router.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/extensions/shell_window.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "content/public/browser/navigation_details.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "content/public/browser/load_notification_details.h"
+#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_view_host.h"
#include "content/public/browser/resource_request_details.h"
#include "content/public/browser/web_contents.h"
-#include "crypto/random.h"
+#include "content/public/common/page_transition_types.h"
#include "googleurl/src/gurl.h"
-#include "grit/browser_resources.h"
+#include "ui/base/window_open_disposition.h"
+using content::LoadNotificationDetails;
+using content::NavigationController;
using content::RenderViewHost;
using content::ResourceRedirectDetails;
using content::WebContents;
@@ -40,12 +35,17 @@ WebAuthFlow::WebAuthFlow(
Delegate* delegate,
Profile* profile,
const GURL& provider_url,
- Mode mode)
+ Mode mode,
+ const gfx::Rect& initial_bounds,
+ chrome::HostDesktopType host_desktop_type)
: delegate_(delegate),
profile_(profile),
provider_url_(provider_url),
mode_(mode),
- embedded_window_created_(false) {
+ initial_bounds_(initial_bounds),
+ host_desktop_type_(host_desktop_type),
+ popup_shown_(false),
+ contents_(NULL) {
}
WebAuthFlow::~WebAuthFlow() {
@@ -56,53 +56,37 @@ WebAuthFlow::~WebAuthFlow() {
registrar_.RemoveAll();
WebContentsObserver::Observe(NULL);
- if (!shell_window_key_.empty()) {
- ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
-
- if (shell_window_ && shell_window_->web_contents())
- shell_window_->web_contents()->Close();
+ if (contents_) {
+ // The popup owns the contents if it was displayed.
+ if (popup_shown_)
+ contents_->Close();
+ else
+ delete contents_;
}
}
void WebAuthFlow::Start() {
- ShellWindowRegistry::Get(profile_)->AddObserver(this);
-
- // Attach a random ID string to the window so we can recoginize it
- // in OnShellWindowAdded.
- std::string random_bytes;
- crypto::RandBytes(WriteInto(&random_bytes, 33), 32);
- std::string key;
- bool success = base::Base64Encode(random_bytes, &shell_window_key_);
- DCHECK(success);
-
- // identityPrivate.onWebFlowRequest(shell_window_key, provider_url_, mode_)
- scoped_ptr<ListValue> args(new ListValue());
- args->AppendString(shell_window_key_);
- args->AppendString(provider_url_.spec());
- if (mode_ == WebAuthFlow::INTERACTIVE)
- args->AppendString("interactive");
- else
- args->AppendString("silent");
-
- scoped_ptr<Event> event(
- new Event("identityPrivate.onWebFlowRequest", args.Pass()));
- event->restrict_to_profile = profile_;
- ExtensionSystem* system = ExtensionSystem::Get(profile_);
-
- extensions::ComponentLoader* component_loader =
- system->extension_service()->component_loader();
- if (!component_loader->Exists(extension_misc::kIdentityApiUiAppId)) {
- component_loader->Add(
- IDR_IDENTITY_API_SCOPE_APPROVAL_MANIFEST,
- base::FilePath(FILE_PATH_LITERAL("identity_scope_approval_dialog")));
- }
-
- system->event_router()->AddLazyEventListener(
- "identityPrivate.onWebFlowRequest", extension_misc::kIdentityApiUiAppId);
- system->event_router()->DispatchEventToExtension(
- extension_misc::kIdentityApiUiAppId, event.Pass());
- system->event_router()->RemoveLazyEventListener(
- "identityPrivate.onWebFlowRequest", extension_misc::kIdentityApiUiAppId);
+ contents_ = CreateWebContents();
+ WebContentsObserver::Observe(contents_);
+
+ NavigationController* controller = &(contents_->GetController());
+
+ // Register for appropriate notifications to intercept navigation to the
+ // redirect URLs.
+ registrar_.Add(
+ this,
+ content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
+ content::Source<WebContents>(contents_));
+ registrar_.Add(
+ this,
+ content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
+ content::Source<WebContents>(contents_));
+
+ controller->LoadURL(
+ provider_url_,
+ content::Referrer(),
+ content::PAGE_TRANSITION_AUTO_TOPLEVEL,
+ std::string());
}
void WebAuthFlow::DetachDelegateAndDelete() {
@@ -110,135 +94,87 @@ void WebAuthFlow::DetachDelegateAndDelete() {
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
-void WebAuthFlow::OnShellWindowAdded(ShellWindow* shell_window) {
- if (shell_window->window_key() == shell_window_key_ &&
- shell_window->extension()->id() == extension_misc::kIdentityApiUiAppId) {
- shell_window_ = shell_window;
- WebContentsObserver::Observe(shell_window->web_contents());
-
- registrar_.Add(
- this,
- content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
- content::NotificationService::AllBrowserContextsAndSources());
- }
+WebContents* WebAuthFlow::CreateWebContents() {
+ return WebContents::Create(WebContents::CreateParams(profile_));
}
-void WebAuthFlow::OnShellWindowRemoved(ShellWindow* shell_window) {
- if (shell_window->window_key() == shell_window_key_ &&
- shell_window->extension()->id() == extension_misc::kIdentityApiUiAppId) {
- shell_window_ = NULL;
- registrar_.RemoveAll();
-
- if (delegate_)
- delegate_->OnAuthFlowFailure(WebAuthFlow::WINDOW_CLOSED);
- }
+void WebAuthFlow::ShowAuthFlowPopup() {
+ Browser::CreateParams browser_params(Browser::TYPE_POPUP, profile_,
+ host_desktop_type_);
+ browser_params.initial_bounds = initial_bounds_;
+ Browser* browser = new Browser(browser_params);
+ chrome::NavigateParams params(browser, contents_);
+ params.disposition = CURRENT_TAB;
+ params.window_action = chrome::NavigateParams::SHOW_WINDOW;
+ chrome::Navigate(&params);
+ // Observe method and WebContentsObserver::* methods will be called
+ // for varous navigation events. That is where we check for redirect
+ // to the right URL.
+ popup_shown_ = true;
}
void WebAuthFlow::BeforeUrlLoaded(const GURL& url) {
- if (delegate_ && embedded_window_created_)
+ if (delegate_)
delegate_->OnAuthFlowURLChange(url);
}
void WebAuthFlow::AfterUrlLoaded() {
- if (delegate_ && embedded_window_created_ && mode_ == WebAuthFlow::SILENT)
- delegate_->OnAuthFlowFailure(WebAuthFlow::INTERACTION_REQUIRED);
+ // Do nothing if a popup is already created.
+ if (popup_shown_)
+ return;
+
+ // Report results directly if not in interactive mode.
+ if (mode_ != WebAuthFlow::INTERACTIVE) {
+ if (delegate_)
+ delegate_->OnAuthFlowFailure(WebAuthFlow::INTERACTION_REQUIRED);
+ return;
+ }
+
+ // We are in interactive mode and window is not shown yet; show the window.
+ ShowAuthFlowPopup();
}
void WebAuthFlow::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- DCHECK(shell_window_);
-
- if (!delegate_)
- return;
-
- if (!embedded_window_created_) {
- DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED);
-
- RenderViewHost* render_view(
- content::Details<RenderViewHost>(details).ptr());
- WebContents* web_contents = WebContents::FromRenderViewHost(render_view);
-
- if (web_contents &&
- (web_contents->GetEmbedderWebContents() ==
- WebContentsObserver::web_contents())) {
- // Switch from watching the shell window to the guest inside it.
- embedded_window_created_ = true;
- WebContentsObserver::Observe(web_contents);
-
- registrar_.RemoveAll();
- registrar_.Add(this,
- content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
- content::Source<WebContents>(web_contents));
- registrar_.Add(this,
- content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
- content::Source<WebContents>(web_contents));
+ switch (type) {
+ case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
+ ResourceRedirectDetails* redirect_details =
+ content::Details<ResourceRedirectDetails>(details).ptr();
+ if (redirect_details != NULL)
+ BeforeUrlLoaded(redirect_details->new_url);
}
- } else {
- // embedded_window_created_
- switch (type) {
- case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
- ResourceRedirectDetails* redirect_details =
- content::Details<ResourceRedirectDetails>(details).ptr();
- if (redirect_details != NULL)
- BeforeUrlLoaded(redirect_details->new_url);
- break;
- }
- case content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED: {
- std::pair<content::NavigationEntry*, bool>* title =
- content::Details<std::pair<content::NavigationEntry*, bool> >(
- details).ptr();
-
- if (title->first) {
- delegate_->OnAuthFlowTitleChange(
- UTF16ToUTF8(title->first->GetTitle()));
- }
- break;
- }
- default:
- NOTREACHED()
- << "Got a notification that we did not register for: " << type;
- break;
+ break;
+ case content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED: {
+ std::pair<content::NavigationEntry*, bool>* title =
+ content::Details<
+ std::pair<content::NavigationEntry*, bool> >(details).ptr();
+
+ if (title->first)
+ delegate_->OnAuthFlowTitleChange(UTF16ToUTF8(title->first->GetTitle()));
}
+ break;
+ default:
+ NOTREACHED() << "Got a notification that we did not register for: "
+ << type;
+ break;
}
}
-void WebAuthFlow::RenderViewGone(base::TerminationStatus status) {
- if (delegate_)
- delegate_->OnAuthFlowFailure(WebAuthFlow::WINDOW_CLOSED);
-}
-
-void WebAuthFlow::DidStartProvisionalLoadForFrame(
- int64 frame_id,
- int64 parent_frame_id,
- bool is_main_frame,
- const GURL& validated_url,
- bool is_error_page,
- bool is_iframe_srcdoc,
+void WebAuthFlow::ProvisionalChangeToMainFrameUrl(
+ const GURL& url,
RenderViewHost* render_view_host) {
- if (is_main_frame)
- BeforeUrlLoaded(validated_url);
-}
-
-void WebAuthFlow::DidFailProvisionalLoad(int64 frame_id,
- bool is_main_frame,
- const GURL& validated_url,
- int error_code,
- const string16& error_description,
- RenderViewHost* render_view_host) {
- if (delegate_)
- delegate_->OnAuthFlowFailure(LOAD_FAILED);
+ BeforeUrlLoaded(url);
}
void WebAuthFlow::DidStopLoading(RenderViewHost* render_view_host) {
AfterUrlLoaded();
}
-void WebAuthFlow::DidNavigateMainFrame(
- const content::LoadCommittedDetails& details,
- const content::FrameNavigateParams& params) {
- if (delegate_ && details.http_status_code >= 400)
- delegate_->OnAuthFlowFailure(LOAD_FAILED);
+void WebAuthFlow::WebContentsDestroyed(WebContents* web_contents) {
+ contents_ = NULL;
+ if (delegate_)
+ delegate_->OnAuthFlowFailure(WebAuthFlow::WINDOW_CLOSED);
}
} // namespace extensions
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.h b/chrome/browser/extensions/api/identity/web_auth_flow.h
index df6c0f9..e2e945b 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.h
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.h
@@ -5,9 +5,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_WEB_AUTH_FLOW_H_
#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_WEB_AUTH_FLOW_H_
-#include <string>
-
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "chrome/browser/ui/host_desktop.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_observer.h"
@@ -26,17 +24,13 @@ class WebContents;
namespace extensions {
-// Controller class for web based auth flows. The WebAuthFlow creates
-// a dialog window in the scope approval component app by firing an
-// event. A webview embedded in the dialog will navigate to the
-// |provider_url| passed to the WebAuthFlow constructor.
-//
-// The WebAuthFlow monitors the WebContents of the webview, and
-// notifies its delegate interface any time the WebContents navigates
-// to a new URL or changes title. The delegate is expected to delete
-// the flow when navigation reaches a known target location.
+// Controller class for web based auth flows. The WebAuthFlow starts
+// by navigating a WebContents to a URL specificed by the caller. Any
+// time the WebContents navigates to a new URL, the flow's delegate is
+// notified. The delegate is expected to delete the flow when
+// navigation reaches a known target URL.
//
-// The window is not displayed until the first page load
+// The WebContents is not displayed until the first page load
// completes. This allows the flow to complete without flashing a
// window on screen if the provider immediately redirects to the
// target URL.
@@ -44,8 +38,7 @@ namespace extensions {
// A WebAuthFlow can be started in Mode::SILENT, which never displays
// a window. If a window would be required, the flow fails.
class WebAuthFlow : public content::NotificationObserver,
- public content::WebContentsObserver,
- public ShellWindowRegistry::Observer {
+ public content::WebContentsObserver {
public:
enum Mode {
INTERACTIVE, // Show UI to the user if necessary.
@@ -54,8 +47,7 @@ class WebAuthFlow : public content::NotificationObserver,
enum Failure {
WINDOW_CLOSED, // Window closed by user.
- INTERACTION_REQUIRED, // Non-redirect page load in silent mode.
- LOAD_FAILED
+ INTERACTION_REQUIRED // Non-redirect page load in silent mode.
};
class Delegate {
@@ -78,7 +70,9 @@ class WebAuthFlow : public content::NotificationObserver,
WebAuthFlow(Delegate* delegate,
Profile* profile,
const GURL& provider_url,
- Mode mode);
+ Mode mode,
+ const gfx::Rect& initial_bounds,
+ chrome::HostDesktopType host_desktop_type);
virtual ~WebAuthFlow();
@@ -88,41 +82,27 @@ class WebAuthFlow : public content::NotificationObserver,
// Prevents further calls to the delegate and deletes the flow.
void DetachDelegateAndDelete();
+ protected:
+ // Overridable for testing.
+ virtual content::WebContents* CreateWebContents();
+ virtual void ShowAuthFlowPopup();
+
private:
friend class ::WebAuthFlowTest;
- // ShellWindowRegistry::Observer implementation.
- virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE;
- virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE {}
- virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE;
-
// NotificationObserver implementation.
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
// WebContentsObserver implementation.
- virtual void DidStopLoading(content::RenderViewHost* render_view_host)
- OVERRIDE;
- virtual void DidNavigateMainFrame(
- const content::LoadCommittedDetails& details,
- const content::FrameNavigateParams& params) OVERRIDE;
- virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE;
- virtual void DidStartProvisionalLoadForFrame(
- int64 frame_id,
- int64 parent_frame_id,
- bool is_main_frame,
- const GURL& validated_url,
- bool is_error_page,
- bool is_iframe_srcdoc,
+ virtual void ProvisionalChangeToMainFrameUrl(
+ const GURL& url,
+ content::RenderViewHost* render_view_host) OVERRIDE;
+ virtual void DidStopLoading(
content::RenderViewHost* render_view_host) OVERRIDE;
- virtual void DidFailProvisionalLoad(int64 frame_id,
- bool is_main_frame,
- const GURL& validated_url,
- int error_code,
- const string16& error_description,
- content::RenderViewHost* render_view_host)
- OVERRIDE;
+ virtual void WebContentsDestroyed(
+ content::WebContents* web_contents) OVERRIDE;
void BeforeUrlLoaded(const GURL& url);
void AfterUrlLoaded();
@@ -131,11 +111,11 @@ class WebAuthFlow : public content::NotificationObserver,
Profile* profile_;
GURL provider_url_;
Mode mode_;
+ gfx::Rect initial_bounds_;
+ chrome::HostDesktopType host_desktop_type_;
+ bool popup_shown_;
- ShellWindow* shell_window_;
- std::string shell_window_key_;
- bool embedded_window_created_;
-
+ content::WebContents* contents_;
content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(WebAuthFlow);
diff --git a/chrome/test/data/extensions/api_test/identity/five_hundred.html b/chrome/test/data/extensions/api_test/identity/five_hundred.html
deleted file mode 100644
index 70db0f2..0000000
--- a/chrome/test/data/extensions/api_test/identity/five_hundred.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<html>
-<head><title>OK</title></head>
-<body></body>
-</html>
diff --git a/chrome/test/data/extensions/api_test/identity/five_hundred.html.mock-http-headers b/chrome/test/data/extensions/api_test/identity/five_hundred.html.mock-http-headers
deleted file mode 100644
index f7c3201..0000000
--- a/chrome/test/data/extensions/api_test/identity/five_hundred.html.mock-http-headers
+++ /dev/null
@@ -1,2 +0,0 @@
-HTTP/1.1 500 Internal Server Error
-