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.
4
5#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_WEB_AUTH_FLOW_H_
6#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_WEB_AUTH_FLOW_H_
7
8#include <string>
9
10#include "content/public/browser/notification_observer.h"
11#include "content/public/browser/notification_registrar.h"
12#include "content/public/browser/web_contents_observer.h"
13#include "extensions/browser/app_window/app_window_registry.h"
14#include "ui/gfx/rect.h"
15#include "url/gurl.h"
16
17class Profile;
18class WebAuthFlowTest;
19
20namespace content {
21class NotificationDetails;
22class NotificationSource;
23class RenderViewHost;
24class WebContents;
25}
26
27namespace extensions {
28
29// Controller class for web based auth flows. The WebAuthFlow creates
30// a dialog window in the scope approval component app by firing an
31// event. A webview embedded in the dialog will navigate to the
32// |provider_url| passed to the WebAuthFlow constructor.
33//
34// The WebAuthFlow monitors the WebContents of the webview, and
35// notifies its delegate interface any time the WebContents navigates
36// to a new URL or changes title. The delegate is expected to delete
37// the flow when navigation reaches a known target location.
38//
39// The window is not displayed until the first page load
40// completes. This allows the flow to complete without flashing a
41// window on screen if the provider immediately redirects to the
42// target URL.
43//
44// A WebAuthFlow can be started in Mode::SILENT, which never displays
45// a window. If a window would be required, the flow fails.
46class WebAuthFlow : public content::NotificationObserver,
47                    public content::WebContentsObserver,
48                    public AppWindowRegistry::Observer {
49 public:
50  enum Mode {
51    INTERACTIVE,  // Show UI to the user if necessary.
52    SILENT        // No UI should be shown.
53  };
54
55  enum Failure {
56    WINDOW_CLOSED,  // Window closed by user.
57    INTERACTION_REQUIRED,  // Non-redirect page load in silent mode.
58    LOAD_FAILED
59  };
60
61  class Delegate {
62   public:
63    // Called when the auth flow fails. This means that the flow did not result
64    // in a successful redirect to a valid redirect URL.
65    virtual void OnAuthFlowFailure(Failure failure) = 0;
66    // Called on redirects and other navigations to see if the URL should stop
67    // the flow.
68    virtual void OnAuthFlowURLChange(const GURL& redirect_url) = 0;
69    // Called when the title of the current page changes.
70    virtual void OnAuthFlowTitleChange(const std::string& title) = 0;
71
72   protected:
73    virtual ~Delegate() {}
74  };
75
76  // Creates an instance with the given parameters.
77  // Caller owns |delegate|.
78  WebAuthFlow(Delegate* delegate,
79              Profile* profile,
80              const GURL& provider_url,
81              Mode mode);
82
83  virtual ~WebAuthFlow();
84
85  // Starts the flow.
86  virtual void Start();
87
88  // Prevents further calls to the delegate and deletes the flow.
89  void DetachDelegateAndDelete();
90
91 private:
92  friend class ::WebAuthFlowTest;
93
94  // ::AppWindowRegistry::Observer implementation.
95  virtual void OnAppWindowAdded(AppWindow* app_window) OVERRIDE;
96  virtual void OnAppWindowRemoved(AppWindow* app_window) OVERRIDE;
97
98  // NotificationObserver implementation.
99  virtual void Observe(int type,
100                       const content::NotificationSource& source,
101                       const content::NotificationDetails& details) OVERRIDE;
102
103  // WebContentsObserver implementation.
104  virtual void DidStopLoading(content::RenderViewHost* render_view_host)
105      OVERRIDE;
106  virtual void DidNavigateMainFrame(
107      const content::LoadCommittedDetails& details,
108      const content::FrameNavigateParams& params) OVERRIDE;
109  virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
110  virtual void DidStartProvisionalLoadForFrame(
111      content::RenderFrameHost* render_frame_host,
112      const GURL& validated_url,
113      bool is_error_page,
114      bool is_iframe_srcdoc) OVERRIDE;
115  virtual void DidFailProvisionalLoad(
116      content::RenderFrameHost* render_frame_host,
117      const GURL& validated_url,
118      int error_code,
119      const base::string16& error_description) OVERRIDE;
120
121  void BeforeUrlLoaded(const GURL& url);
122  void AfterUrlLoaded();
123
124  Delegate* delegate_;
125  Profile* profile_;
126  GURL provider_url_;
127  Mode mode_;
128
129  AppWindow* app_window_;
130  std::string app_window_key_;
131  bool embedded_window_created_;
132
133  content::NotificationRegistrar registrar_;
134
135  DISALLOW_COPY_AND_ASSIGN(WebAuthFlow);
136};
137
138}  // namespace extensions
139
140#endif  // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_WEB_AUTH_FLOW_H_
141