summaryrefslogtreecommitdiff
path: root/chromium/components/safe_browsing/password_protection/password_protection_request.h
blob: 701b8fedb58c12c738cf04bd8019177ca9d0477e (plain)
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_SAFE_BROWSING_PASSWORD_PROTECTION_PASSWORD_PROTECTION_REQUEST_H_
#define COMPONENTS_SAFE_BROWSING_PASSWORD_PROTECTION_PASSWORD_PROTECTION_REQUEST_H_

#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/task/cancelable_task_tracker.h"
#include "components/safe_browsing/password_protection/password_protection_service.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_status.h"

#include <vector>

class GURL;

namespace safe_browsing {

class PasswordProtectionNavigationThrottle;

// UMA metrics
extern const char kPasswordOnFocusVerdictHistogram[];
extern const char kAnyPasswordEntryVerdictHistogram[];
extern const char kSyncPasswordEntryVerdictHistogram[];
extern const char kProtectedPasswordEntryVerdictHistogram[];

// A request for checking if an unfamiliar login form or a password reuse event
// is safe. PasswordProtectionRequest objects are owned by
// PasswordProtectionService indicated by |password_protection_service_|.
// PasswordProtectionService is RefCountedThreadSafe such that it can post task
// safely between IO and UI threads. It can only be destroyed on UI thread.
//
// PasswordProtectionRequest flow:
// Step| Thread |                    Task
// (1) |   UI   | If incognito or !SBER, quit request.
// (2) |   UI   | Add task to IO thread for whitelist checking.
// (3) |   IO   | Check whitelist and return the result back to UI thread.
// (4) |   UI   | If whitelisted, check verdict cache; else quit request.
// (5) |   UI   | If verdict cached, quit request; else prepare request proto.
// (6) |   UI   | Start a timeout task, and send network request.
// (7) |   UI   | On receiving response, handle response and finish.
//     |        | On request timeout, cancel request.
//     |        | On deletion of |password_protection_service_|, cancel request.
class PasswordProtectionRequest : public base::RefCountedThreadSafe<
                                      PasswordProtectionRequest,
                                      content::BrowserThread::DeleteOnUIThread>,
                                  public net::URLFetcherDelegate {
 public:
  PasswordProtectionRequest(content::WebContents* web_contents,
                            const GURL& main_frame_url,
                            const GURL& password_form_action,
                            const GURL& password_form_frame_url,
                            bool matches_sync_password,
                            const std::vector<std::string>& matching_origins,
                            LoginReputationClientRequest::TriggerType type,
                            bool password_field_exists,
                            PasswordProtectionService* pps,
                            int request_timeout_in_ms);

  base::WeakPtr<PasswordProtectionRequest> GetWeakPtr() {
    return weakptr_factory_.GetWeakPtr();
  }

  // Starts processing request by checking extended reporting and incognito
  // conditions.
  void Start();

  // Cancels the current request. |timed_out| indicates if this cancellation is
  // due to timeout. This function will call Finish() to destroy |this|.
  void Cancel(bool timed_out);

  // net::URLFetcherDelegate override.
  // Processes the received response.
  void OnURLFetchComplete(const net::URLFetcher* source) override;

  GURL main_frame_url() const { return main_frame_url_; }

  const LoginReputationClientRequest* request_proto() const {
    return request_proto_.get();
  }

  content::WebContents* web_contents() const { return web_contents_; }

  LoginReputationClientRequest::TriggerType trigger_type() const {
    return trigger_type_;
  }

  bool matches_sync_password() { return matches_sync_password_; }

  bool is_modal_warning_showing() const { return is_modal_warning_showing_; }

  void set_is_modal_warning_showing(bool is_warning_showing) {
    is_modal_warning_showing_ = is_warning_showing;
  }

  // Keeps track of created navigation throttle.
  void AddThrottle(PasswordProtectionNavigationThrottle* throttle) {
    throttles_.insert(throttle);
  }

  // Cancels navigation if there is modal warning showing, resumes it otherwise.
  void HandleDeferredNavigations();

 protected:
  friend class base::RefCountedThreadSafe<PasswordProtectionRequest>;

 private:
  friend struct content::BrowserThread::DeleteOnThread<
      content::BrowserThread::UI>;
  friend class base::DeleteHelper<PasswordProtectionRequest>;
  ~PasswordProtectionRequest() override;

  // Start checking the whitelist.
  void CheckWhitelist();

  static void OnWhitelistCheckDoneOnIO(
      base::WeakPtr<PasswordProtectionRequest> weak_request,
      bool match_whitelist);

  // If |main_frame_url_| matches whitelist, call Finish() immediately;
  // otherwise call CheckCachedVerdicts().
  void OnWhitelistCheckDone(bool match_whitelist);

  // Looks up cached verdicts. If verdict is already cached, call SendRequest();
  // otherwise call Finish().
  void CheckCachedVerdicts();

  // Fill |request_proto_| with appropriate values.
  void FillRequestProto();

  // Initiates network request to Safe Browsing backend.
  void SendRequest();

  // Start a timer to cancel the request if it takes too long.
  void StartTimeout();

  // |this| will be destroyed after calling this function.
  void Finish(PasswordProtectionService::RequestOutcome outcome,
              std::unique_ptr<LoginReputationClientResponse> response);

  // WebContents of the password protection event.
  content::WebContents* web_contents_;

  // Main frame URL of the login form.
  const GURL main_frame_url_;

  // The action URL of the password form.
  const GURL password_form_action_;

  // Frame url of the detected password form.
  const GURL password_form_frame_url_;

  // True if the password is the sync/Google password.
  const bool matches_sync_password_;

  // Domains from the Password Manager that match this password.
  // Should be non-empty if |matches_sync_password_| == false. Otherwise,
  // may or may not be empty.
  const std::vector<std::string> matching_domains_;

  // If this request is for unfamiliar login page or for a password reuse event.
  const LoginReputationClientRequest::TriggerType trigger_type_;

  // If there is a password field on the page.
  const bool password_field_exists_;

  // When request is sent.
  base::TimeTicks request_start_time_;

  // URLFetcher instance for sending request and receiving response.
  std::unique_ptr<net::URLFetcher> fetcher_;

  // The PasswordProtectionService instance owns |this|.
  // Can only be accessed on UI thread.
  PasswordProtectionService* password_protection_service_;

  // If we haven't receive response after this period of time, we cancel this
  // request.
  const int request_timeout_in_ms_;

  std::unique_ptr<LoginReputationClientRequest> request_proto_;

  // Needed for canceling tasks posted to different threads.
  base::CancelableTaskTracker tracker_;

  // Navigation throttles created for this |web_contents_| during |this|'s
  // lifetime. These throttles are owned by their corresponding
  // NavigationHandler instances.
  std::set<PasswordProtectionNavigationThrottle*> throttles_;

  // Whether there is a modal warning triggered by this request.
  bool is_modal_warning_showing_;

  base::WeakPtrFactory<PasswordProtectionRequest> weakptr_factory_;
  DISALLOW_COPY_AND_ASSIGN(PasswordProtectionRequest);
};

}  // namespace safe_browsing

#endif  // COMPONENTS_SAFE_BROWSING_PASSWORD_PROTECTION_PASSWORD_PROTECTION_REQUEST_H_