1 // Copyright (c) 2012 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.
5 #include "chrome/browser/extensions/api/identity/experimental_web_auth_flow.h"
7 #include "base/location.h"
8 #include "base/message_loop/message_loop.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/browser_navigator.h"
12 #include "content/public/browser/load_notification_details.h"
13 #include "content/public/browser/navigation_controller.h"
14 #include "content/public/browser/notification_details.h"
15 #include "content/public/browser/notification_source.h"
16 #include "content/public/browser/notification_types.h"
17 #include "content/public/browser/resource_request_details.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/common/page_transition_types.h"
20 #include "ui/base/window_open_disposition.h"
23 using content::LoadNotificationDetails;
24 using content::NavigationController;
25 using content::RenderViewHost;
26 using content::ResourceRedirectDetails;
27 using content::WebContents;
28 using content::WebContentsObserver;
30 namespace extensions {
32 ExperimentalWebAuthFlow::ExperimentalWebAuthFlow(
35 const GURL& provider_url,
37 const gfx::Rect& initial_bounds,
38 chrome::HostDesktopType host_desktop_type)
39 : delegate_(delegate),
41 provider_url_(provider_url),
43 initial_bounds_(initial_bounds),
44 host_desktop_type_(host_desktop_type),
49 ExperimentalWebAuthFlow::~ExperimentalWebAuthFlow() {
50 DCHECK(delegate_ == NULL);
52 // Stop listening to notifications first since some of the code
53 // below may generate notifications.
54 registrar_.RemoveAll();
55 WebContentsObserver::Observe(NULL);
58 // The popup owns the contents if it was displayed.
66 void ExperimentalWebAuthFlow::Start() {
67 contents_ = CreateWebContents();
68 WebContentsObserver::Observe(contents_);
70 NavigationController* controller = &(contents_->GetController());
72 // Register for appropriate notifications to intercept navigation to the
76 content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
77 content::Source<WebContents>(contents_));
82 content::PAGE_TRANSITION_AUTO_TOPLEVEL,
86 void ExperimentalWebAuthFlow::DetachDelegateAndDelete() {
88 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
91 WebContents* ExperimentalWebAuthFlow::CreateWebContents() {
92 return WebContents::Create(WebContents::CreateParams(profile_));
95 void ExperimentalWebAuthFlow::ShowAuthFlowPopup() {
96 Browser::CreateParams browser_params(Browser::TYPE_POPUP, profile_,
98 browser_params.initial_bounds = initial_bounds_;
99 Browser* browser = new Browser(browser_params);
100 chrome::NavigateParams params(browser, contents_);
101 params.disposition = CURRENT_TAB;
102 params.window_action = chrome::NavigateParams::SHOW_WINDOW;
103 chrome::Navigate(¶ms);
104 // Observe method and WebContentsObserver::* methods will be called
105 // for varous navigation events. That is where we check for redirect
110 void ExperimentalWebAuthFlow::BeforeUrlLoaded(const GURL& url) {
112 delegate_->OnAuthFlowURLChange(url);
115 void ExperimentalWebAuthFlow::AfterUrlLoaded() {
116 // Do nothing if a popup is already created.
120 // Report results directly if not in interactive mode.
121 if (mode_ != ExperimentalWebAuthFlow::INTERACTIVE) {
123 delegate_->OnAuthFlowFailure(
124 ExperimentalWebAuthFlow::INTERACTION_REQUIRED);
129 // We are in interactive mode and window is not shown yet; show the window.
133 void ExperimentalWebAuthFlow::Observe(int type,
134 const content::NotificationSource& source,
135 const content::NotificationDetails& details) {
137 case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
138 ResourceRedirectDetails* redirect_details =
139 content::Details<ResourceRedirectDetails>(details).ptr();
140 if (redirect_details != NULL)
141 BeforeUrlLoaded(redirect_details->new_url);
145 NOTREACHED() << "Got a notification that we did not register for: "
151 void ExperimentalWebAuthFlow::ProvisionalChangeToMainFrameUrl(
153 RenderViewHost* render_view_host) {
154 BeforeUrlLoaded(url);
157 void ExperimentalWebAuthFlow::DidStopLoading(RenderViewHost* render_view_host) {
161 void ExperimentalWebAuthFlow::WebContentsDestroyed(WebContents* web_contents) {
164 delegate_->OnAuthFlowFailure(ExperimentalWebAuthFlow::WINDOW_CLOSED);
167 } // namespace extensions