File: web_auth_flow.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (187 lines) | stat: -rw-r--r-- 6,644 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_WEB_AUTH_FLOW_H_
#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_WEB_AUTH_FLOW_H_

#include <optional>
#include <string>

#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"

class Profile;

namespace base {
class OneShotTimer;
class TickClock;
}  // namespace base

namespace extensions {

class WebAuthFlowInfoBarDelegate;

// Controller class for web based auth flows. The WebAuthFlow creates
// a browser popup window (or a new tab based on the feature setting)
// with a webview that 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.
//
// The window 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.
//
// 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::WebContentsObserver {
 public:
  enum Mode {
    INTERACTIVE,  // Show UI to the user if necessary.
    SILENT        // No UI should be shown.
  };

  enum Failure {
    WINDOW_CLOSED,         // Window closed by user (app or tab).
    INTERACTION_REQUIRED,  // Non-redirect page load in silent mode.
    LOAD_FAILED,
    TIMED_OUT,
    CANNOT_CREATE_WINDOW,  // Couldn't create a browser window.
  };

  enum class AbortOnLoad {
    kYes,
    kNo,
  };

  // Maximum time on the total `WebAuthFlow` execution in silent node. This is
  // the default if timeout is not specified.
  static constexpr base::TimeDelta kNonInteractiveMaxTimeout = base::Minutes(1);

  class Delegate {
   public:
    // Called when the auth flow fails. This means that the flow did not result
    // in a successful redirect to a valid redirect URL.
    virtual void OnAuthFlowFailure(Failure failure) = 0;
    // Called on redirects and other navigations to see if the URL should stop
    // the flow.
    virtual void OnAuthFlowURLChange(const GURL& redirect_url) {}
    // Called when the title of the current page changes.
    virtual void OnAuthFlowTitleChange(const std::string& title) {}
    // Called when the web_contents associated with the flow has finished
    // navigation.
    virtual void OnNavigationFinished(
        content::NavigationHandle* navigation_handle) {}

   protected:
    virtual ~Delegate() = default;
  };

  // Creates an instance with the given parameters.
  // Caller owns `delegate`.
  WebAuthFlow(
      Delegate* delegate,
      Profile* profile,
      const GURL& provider_url,
      Mode mode,
      bool user_gesture,
      AbortOnLoad abort_on_load_for_non_interactive = AbortOnLoad::kYes,
      std::optional<base::TimeDelta> timeout_for_non_interactive = std::nullopt,
      std::optional<gfx::Rect> popup_bounds = std::nullopt);

  WebAuthFlow(const WebAuthFlow&) = delete;
  WebAuthFlow& operator=(const WebAuthFlow&) = delete;

  ~WebAuthFlow() override;

  // Testing clock used to test the effect of load timeout.
  void SetClockForTesting(const base::TickClock* clock,
                          scoped_refptr<base::SequencedTaskRunner> task_runner);

  // Starts the flow.
  virtual void Start();

  // Prevents further calls to the delegate and deletes the flow.
  void DetachDelegateAndDelete();

  // Immediately closes the webview and prevents further delegate calls. Can be
  // called before `DetachDelegateAndDelete()` to release resources immediately.
  void Stop();

  // This call will make the interactive mode, that opens up a browser tab for
  // auth, display an Infobar that shows the extension name.
  void SetShouldShowInfoBar(const std::string& extension_display_name);

  // Returns nullptr if the InfoBar is not displayed.
  base::WeakPtr<WebAuthFlowInfoBarDelegate> GetInfoBarDelegateForTesting();

 private:
  // WebContentsObserver implementation.
  void DidStopLoading() override;
  void WebContentsDestroyed() override;
  void TitleWasSet(content::NavigationEntry* entry) override;
  void DidStartNavigation(
      content::NavigationHandle* navigation_handle) override;
  void DidRedirectNavigation(
      content::NavigationHandle* navigation_handle) override;
  void DidFinishNavigation(
      content::NavigationHandle* navigation_handle) override;

  void BeforeUrlLoaded(const GURL& url);
  void AfterUrlLoaded();

  void MaybeStartTimeout();
  void OnTimeout();

  bool DisplayAuthPageInPopupWindow();

  void DisplayInfoBar();
  void CloseInfoBar();

  raw_ptr<Delegate> delegate_ = nullptr;
  raw_ptr<Profile> profile_;
  const GURL provider_url_;
  const Mode mode_;
  const bool user_gesture_;

  // WebContents used to initialize the authentication. It is not displayed
  // and not owned by browser window. This WebContents is observed by
  // `this`. When this value becomes nullptr, this means that the browser tab
  // has taken ownership and the interactive tab was opened.
  std::unique_ptr<content::WebContents> web_contents_;

  // Internal struct to manage infobar parameters, external calls can only set
  // the extension display name which will force show the info bar through
  // `SetShouldShowInfoBar()`.
  struct InfoBarParameters {
    bool should_show = false;
    std::string extension_display_name;
  };
  InfoBarParameters info_bar_parameters_;

  // WeakPtr to the info bar delegate attached to the auth tab when opened. Used
  // to close the info bar when closing the flow if still valid.
  base::WeakPtr<WebAuthFlowInfoBarDelegate> info_bar_delegate_ = nullptr;

  const AbortOnLoad abort_on_load_for_non_interactive_;
  const std::optional<base::TimeDelta> timeout_for_non_interactive_;
  std::unique_ptr<base::OneShotTimer> non_interactive_timeout_timer_;
  const std::optional<gfx::Rect> popup_bounds_;
  // Flag indicating that the initial URL was successfully loaded. Influences
  // the error code when the flow times out.
  bool initial_url_loaded_ = false;
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_WEB_AUTH_FLOW_H_