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