OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/password_manager/content/browser/credential_manager_dispatc
her.h" | 5 #include "components/password_manager/content/browser/credential_manager_impl.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/strings/string16.h" | 10 #include "base/strings/string16.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "components/autofill/core/common/password_form.h" | 12 #include "components/autofill/core/common/password_form.h" |
13 #include "components/password_manager/content/browser/content_password_manager_d
river.h" | 13 #include "components/password_manager/content/browser/content_password_manager_d
river.h" |
14 #include "components/password_manager/content/browser/content_password_manager_d
river_factory.h" | 14 #include "components/password_manager/content/browser/content_password_manager_d
river_factory.h" |
15 #include "components/password_manager/content/common/credential_manager_messages
.h" | 15 #include "components/password_manager/content/public/cpp/type_converters.h" |
16 #include "components/password_manager/core/browser/affiliated_match_helper.h" | 16 #include "components/password_manager/core/browser/affiliated_match_helper.h" |
17 #include "components/password_manager/core/browser/password_manager_client.h" | 17 #include "components/password_manager/core/browser/password_manager_client.h" |
18 #include "components/password_manager/core/browser/password_store.h" | 18 #include "components/password_manager/core/browser/password_store.h" |
19 #include "components/password_manager/core/common/credential_manager_types.h" | 19 #include "components/password_manager/core/common/credential_manager_types.h" |
20 #include "components/password_manager/core/common/password_manager_pref_names.h" | 20 #include "components/password_manager/core/common/password_manager_pref_names.h" |
21 #include "content/public/browser/render_view_host.h" | |
22 #include "content/public/browser/web_contents.h" | 21 #include "content/public/browser/web_contents.h" |
23 #include "ipc/ipc_message_macros.h" | 22 #include "mojo/common/url_type_converters.h" |
24 | 23 |
25 namespace password_manager { | 24 namespace password_manager { |
26 | 25 |
27 // CredentialManagerDispatcher ------------------------------------------------- | 26 namespace { |
28 | 27 |
29 CredentialManagerDispatcher::CredentialManagerDispatcher( | 28 void RunMojoGetCallback(const mojom::CredentialManager::GetCallback& callback, |
30 content::WebContents* web_contents, | 29 const CredentialInfo& info) { |
31 PasswordManagerClient* client) | 30 mojom::CredentialInfoPtr credential = mojom::CredentialInfo::From(info); |
| 31 callback.Run(mojom::CredentialManagerError::SUCCESS, std::move(credential)); |
| 32 } |
| 33 |
| 34 } // namespace |
| 35 |
| 36 // CredentialManagerImpl ------------------------------------------------- |
| 37 |
| 38 CredentialManagerImpl::CredentialManagerImpl(content::WebContents* web_contents, |
| 39 PasswordManagerClient* client) |
32 : WebContentsObserver(web_contents), client_(client), weak_factory_(this) { | 40 : WebContentsObserver(web_contents), client_(client), weak_factory_(this) { |
33 DCHECK(web_contents); | 41 DCHECK(web_contents); |
34 auto_signin_enabled_.Init(prefs::kCredentialsEnableAutosignin, | 42 auto_signin_enabled_.Init(prefs::kCredentialsEnableAutosignin, |
35 client_->GetPrefs()); | 43 client_->GetPrefs()); |
36 } | 44 } |
37 | 45 |
38 CredentialManagerDispatcher::~CredentialManagerDispatcher() { | 46 CredentialManagerImpl::~CredentialManagerImpl() {} |
| 47 |
| 48 void CredentialManagerImpl::BindRequest( |
| 49 mojom::CredentialManagerRequest request) { |
| 50 bindings_.AddBinding(this, std::move(request)); |
39 } | 51 } |
40 | 52 |
41 bool CredentialManagerDispatcher::OnMessageReceived( | 53 void CredentialManagerImpl::Store(mojom::CredentialInfoPtr credential, |
42 const IPC::Message& message) { | 54 const StoreCallback& callback) { |
43 bool handled = true; | 55 CredentialInfo info = credential.To<CredentialInfo>(); |
44 IPC_BEGIN_MESSAGE_MAP(CredentialManagerDispatcher, message) | 56 DCHECK_NE(CredentialType::CREDENTIAL_TYPE_EMPTY, info.type); |
45 IPC_MESSAGE_HANDLER(CredentialManagerHostMsg_Store, OnStore); | |
46 IPC_MESSAGE_HANDLER(CredentialManagerHostMsg_RequireUserMediation, | |
47 OnRequireUserMediation); | |
48 IPC_MESSAGE_HANDLER(CredentialManagerHostMsg_RequestCredential, | |
49 OnRequestCredential); | |
50 IPC_MESSAGE_UNHANDLED(handled = false) | |
51 IPC_END_MESSAGE_MAP() | |
52 return handled; | |
53 } | |
54 | 57 |
55 void CredentialManagerDispatcher::OnStore( | 58 // Send acknowledge response back. |
56 int request_id, | 59 callback.Run(); |
57 const password_manager::CredentialInfo& credential) { | |
58 DCHECK(credential.type != CredentialType::CREDENTIAL_TYPE_EMPTY); | |
59 DCHECK(request_id); | |
60 web_contents()->GetRenderViewHost()->Send( | |
61 new CredentialManagerMsg_AcknowledgeStore( | |
62 web_contents()->GetRenderViewHost()->GetRoutingID(), request_id)); | |
63 | 60 |
64 if (!client_->IsSavingAndFillingEnabledForCurrentPage()) | 61 if (!client_->IsSavingAndFillingEnabledForCurrentPage()) |
65 return; | 62 return; |
66 | 63 |
67 std::unique_ptr<autofill::PasswordForm> form( | 64 std::unique_ptr<autofill::PasswordForm> form( |
68 CreatePasswordFormFromCredentialInfo( | 65 CreatePasswordFormFromCredentialInfo( |
69 credential, web_contents()->GetLastCommittedURL().GetOrigin())); | 66 info, web_contents()->GetLastCommittedURL().GetOrigin())); |
70 form->skip_zero_click = !IsZeroClickAllowed(); | 67 form->skip_zero_click = !IsZeroClickAllowed(); |
71 | 68 |
72 form_manager_.reset(new CredentialManagerPasswordFormManager( | 69 form_manager_.reset(new CredentialManagerPasswordFormManager( |
73 client_, GetDriver(), *form, this)); | 70 client_, GetDriver(), *form, this)); |
74 } | 71 } |
75 | 72 |
76 void CredentialManagerDispatcher::OnProvisionalSaveComplete() { | 73 void CredentialManagerImpl::OnProvisionalSaveComplete() { |
77 DCHECK(form_manager_); | 74 DCHECK(form_manager_); |
78 DCHECK(client_->IsSavingAndFillingEnabledForCurrentPage()); | 75 DCHECK(client_->IsSavingAndFillingEnabledForCurrentPage()); |
79 const autofill::PasswordForm& form = form_manager_->pending_credentials(); | 76 const autofill::PasswordForm& form = form_manager_->pending_credentials(); |
80 | 77 |
81 if (!form.federation_origin.unique()) { | 78 if (!form.federation_origin.unique()) { |
82 // If this is a federated credential, check it against the federated matches | 79 // If this is a federated credential, check it against the federated matches |
83 // produced by the PasswordFormManager. If a match is found, update it and | 80 // produced by the PasswordFormManager. If a match is found, update it and |
84 // return. | 81 // return. |
85 for (const auto& match : form_manager_->federated_matches()) { | 82 for (const auto& match : form_manager_->federated_matches()) { |
86 if (match->username_value == form.username_value && | 83 if (match->username_value == form.username_value && |
(...skipping 11 matching lines...) Expand all Loading... |
98 form_manager_->Update(*form_manager_->preferred_match()); | 95 form_manager_->Update(*form_manager_->preferred_match()); |
99 return; | 96 return; |
100 } | 97 } |
101 | 98 |
102 // Otherwise, this is a new form, so as the user if they'd like to save. | 99 // Otherwise, this is a new form, so as the user if they'd like to save. |
103 client_->PromptUserToSaveOrUpdatePassword( | 100 client_->PromptUserToSaveOrUpdatePassword( |
104 std::move(form_manager_), CredentialSourceType::CREDENTIAL_SOURCE_API, | 101 std::move(form_manager_), CredentialSourceType::CREDENTIAL_SOURCE_API, |
105 false); | 102 false); |
106 } | 103 } |
107 | 104 |
108 void CredentialManagerDispatcher::OnRequireUserMediation(int request_id) { | 105 void CredentialManagerImpl::RequireUserMediation( |
109 DCHECK(request_id); | 106 const RequireUserMediationCallback& callback) { |
110 | |
111 PasswordStore* store = GetPasswordStore(); | 107 PasswordStore* store = GetPasswordStore(); |
112 if (!store || !IsUpdatingCredentialAllowed()) { | 108 if (!store || !IsUpdatingCredentialAllowed()) { |
113 web_contents()->GetRenderViewHost()->Send( | 109 callback.Run(); |
114 new CredentialManagerMsg_AcknowledgeRequireUserMediation( | |
115 web_contents()->GetRenderViewHost()->GetRoutingID(), request_id)); | |
116 return; | 110 return; |
117 } | 111 } |
118 | 112 |
119 if (store->affiliated_match_helper()) { | 113 if (store->affiliated_match_helper()) { |
120 store->affiliated_match_helper()->GetAffiliatedAndroidRealms( | 114 store->affiliated_match_helper()->GetAffiliatedAndroidRealms( |
121 GetSynthesizedFormForOrigin(), | 115 GetSynthesizedFormForOrigin(), |
122 base::Bind(&CredentialManagerDispatcher::ScheduleRequireMediationTask, | 116 base::Bind(&CredentialManagerImpl::ScheduleRequireMediationTask, |
123 weak_factory_.GetWeakPtr(), request_id)); | 117 weak_factory_.GetWeakPtr(), callback)); |
124 } else { | 118 } else { |
125 std::vector<std::string> no_affiliated_realms; | 119 std::vector<std::string> no_affiliated_realms; |
126 ScheduleRequireMediationTask(request_id, no_affiliated_realms); | 120 ScheduleRequireMediationTask(callback, no_affiliated_realms); |
127 } | 121 } |
128 } | 122 } |
129 | 123 |
130 void CredentialManagerDispatcher::ScheduleRequireMediationTask( | 124 void CredentialManagerImpl::ScheduleRequireMediationTask( |
131 int request_id, | 125 const RequireUserMediationCallback& callback, |
132 const std::vector<std::string>& android_realms) { | 126 const std::vector<std::string>& android_realms) { |
133 DCHECK(GetPasswordStore()); | 127 DCHECK(GetPasswordStore()); |
134 if (!pending_require_user_mediation_) { | 128 if (!pending_require_user_mediation_) { |
135 pending_require_user_mediation_.reset( | 129 pending_require_user_mediation_.reset( |
136 new CredentialManagerPendingRequireUserMediationTask( | 130 new CredentialManagerPendingRequireUserMediationTask( |
137 this, web_contents()->GetLastCommittedURL().GetOrigin(), | 131 this, web_contents()->GetLastCommittedURL().GetOrigin(), |
138 android_realms)); | 132 android_realms)); |
139 | 133 |
140 // This will result in a callback to | 134 // This will result in a callback to |
141 // CredentialManagerPendingRequireUserMediationTask::OnGetPasswordStoreResul
ts(). | 135 // CredentialManagerPendingRequireUserMediationTask:: |
| 136 // OnGetPasswordStoreResults(). |
142 GetPasswordStore()->GetAutofillableLogins( | 137 GetPasswordStore()->GetAutofillableLogins( |
143 pending_require_user_mediation_.get()); | 138 pending_require_user_mediation_.get()); |
144 } else { | 139 } else { |
145 pending_require_user_mediation_->AddOrigin( | 140 pending_require_user_mediation_->AddOrigin( |
146 web_contents()->GetLastCommittedURL().GetOrigin()); | 141 web_contents()->GetLastCommittedURL().GetOrigin()); |
147 } | 142 } |
148 | 143 |
149 web_contents()->GetRenderViewHost()->Send( | 144 // Send acknowledge response back. |
150 new CredentialManagerMsg_AcknowledgeRequireUserMediation( | 145 callback.Run(); |
151 web_contents()->GetRenderViewHost()->GetRoutingID(), request_id)); | |
152 } | 146 } |
153 | 147 |
154 void CredentialManagerDispatcher::OnRequestCredential( | 148 void CredentialManagerImpl::Get(bool zero_click_only, |
155 int request_id, | 149 bool include_passwords, |
156 bool zero_click_only, | 150 mojo::Array<mojo::String> federations, |
157 bool include_passwords, | 151 const GetCallback& callback) { |
158 const std::vector<GURL>& federations) { | |
159 DCHECK(request_id); | |
160 PasswordStore* store = GetPasswordStore(); | 152 PasswordStore* store = GetPasswordStore(); |
161 if (pending_request_ || !store) { | 153 if (pending_request_ || !store) { |
162 web_contents()->GetRenderViewHost()->Send( | 154 // Callback error. |
163 new CredentialManagerMsg_RejectCredentialRequest( | 155 callback.Run(pending_request_ |
164 web_contents()->GetRenderViewHost()->GetRoutingID(), request_id, | 156 ? mojom::CredentialManagerError::PENDINGREQUEST |
165 pending_request_ | 157 : mojom::CredentialManagerError::PASSWORDSTOREUNAVAILABLE, |
166 ? blink::WebCredentialManagerPendingRequestError | 158 nullptr); |
167 : blink::WebCredentialManagerPasswordStoreUnavailableError)); | |
168 return; | 159 return; |
169 } | 160 } |
170 | 161 |
171 // Return an empty credential if zero-click is required but disabled, or if | 162 // Return an empty credential if zero-click is required but disabled, or if |
172 // the current page has TLS errors. | 163 // the current page has TLS errors. |
173 if ((zero_click_only && !IsZeroClickAllowed()) || | 164 if ((zero_click_only && !IsZeroClickAllowed()) || |
174 client_->DidLastPageLoadEncounterSSLErrors()) { | 165 client_->DidLastPageLoadEncounterSSLErrors()) { |
175 web_contents()->GetRenderViewHost()->Send( | 166 // Callback with empty credential info. |
176 new CredentialManagerMsg_SendCredential( | 167 callback.Run(mojom::CredentialManagerError::SUCCESS, |
177 web_contents()->GetRenderViewHost()->GetRoutingID(), request_id, | 168 mojom::CredentialInfo::New()); |
178 CredentialInfo())); | |
179 return; | 169 return; |
180 } | 170 } |
181 | 171 |
182 if (store->affiliated_match_helper()) { | 172 if (store->affiliated_match_helper()) { |
183 store->affiliated_match_helper()->GetAffiliatedAndroidRealms( | 173 store->affiliated_match_helper()->GetAffiliatedAndroidRealms( |
184 GetSynthesizedFormForOrigin(), | 174 GetSynthesizedFormForOrigin(), |
185 base::Bind(&CredentialManagerDispatcher::ScheduleRequestTask, | 175 base::Bind(&CredentialManagerImpl::ScheduleRequestTask, |
186 weak_factory_.GetWeakPtr(), request_id, zero_click_only, | 176 weak_factory_.GetWeakPtr(), callback, zero_click_only, |
187 include_passwords, federations)); | 177 include_passwords, federations.To<std::vector<GURL>>())); |
188 } else { | 178 } else { |
189 std::vector<std::string> no_affiliated_realms; | 179 std::vector<std::string> no_affiliated_realms; |
190 ScheduleRequestTask(request_id, zero_click_only, include_passwords, | 180 ScheduleRequestTask(callback, zero_click_only, include_passwords, |
191 federations, no_affiliated_realms); | 181 federations.To<std::vector<GURL>>(), |
| 182 no_affiliated_realms); |
192 } | 183 } |
193 } | 184 } |
194 | 185 |
195 void CredentialManagerDispatcher::ScheduleRequestTask( | 186 void CredentialManagerImpl::ScheduleRequestTask( |
196 int request_id, | 187 const GetCallback& callback, |
197 bool zero_click_only, | 188 bool zero_click_only, |
198 bool include_passwords, | 189 bool include_passwords, |
199 const std::vector<GURL>& federations, | 190 const std::vector<GURL>& federations, |
200 const std::vector<std::string>& android_realms) { | 191 const std::vector<std::string>& android_realms) { |
201 DCHECK(GetPasswordStore()); | 192 DCHECK(GetPasswordStore()); |
202 pending_request_.reset(new CredentialManagerPendingRequestTask( | 193 pending_request_.reset(new CredentialManagerPendingRequestTask( |
203 this, request_id, zero_click_only, | 194 this, base::Bind(&RunMojoGetCallback, callback), zero_click_only, |
204 web_contents()->GetLastCommittedURL().GetOrigin(), include_passwords, | 195 web_contents()->GetLastCommittedURL().GetOrigin(), include_passwords, |
205 federations, android_realms)); | 196 federations, android_realms)); |
206 | 197 |
207 // This will result in a callback to | 198 // This will result in a callback to |
208 // PendingRequestTask::OnGetPasswordStoreResults(). | 199 // PendingRequestTask::OnGetPasswordStoreResults(). |
209 GetPasswordStore()->GetAutofillableLogins(pending_request_.get()); | 200 GetPasswordStore()->GetAutofillableLogins(pending_request_.get()); |
210 } | 201 } |
211 | 202 |
212 PasswordStore* CredentialManagerDispatcher::GetPasswordStore() { | 203 PasswordStore* CredentialManagerImpl::GetPasswordStore() { |
213 return client_ ? client_->GetPasswordStore() : nullptr; | 204 return client_ ? client_->GetPasswordStore() : nullptr; |
214 } | 205 } |
215 | 206 |
216 bool CredentialManagerDispatcher::IsZeroClickAllowed() const { | 207 bool CredentialManagerImpl::IsZeroClickAllowed() const { |
217 return *auto_signin_enabled_ && !client_->IsOffTheRecord(); | 208 return *auto_signin_enabled_ && !client_->IsOffTheRecord(); |
218 } | 209 } |
219 | 210 |
220 GURL CredentialManagerDispatcher::GetOrigin() const { | 211 GURL CredentialManagerImpl::GetOrigin() const { |
221 return web_contents()->GetLastCommittedURL().GetOrigin(); | 212 return web_contents()->GetLastCommittedURL().GetOrigin(); |
222 } | 213 } |
223 | 214 |
224 base::WeakPtr<PasswordManagerDriver> CredentialManagerDispatcher::GetDriver() { | 215 base::WeakPtr<PasswordManagerDriver> CredentialManagerImpl::GetDriver() { |
225 ContentPasswordManagerDriverFactory* driver_factory = | 216 ContentPasswordManagerDriverFactory* driver_factory = |
226 ContentPasswordManagerDriverFactory::FromWebContents(web_contents()); | 217 ContentPasswordManagerDriverFactory::FromWebContents(web_contents()); |
227 DCHECK(driver_factory); | 218 DCHECK(driver_factory); |
228 PasswordManagerDriver* driver = | 219 PasswordManagerDriver* driver = |
229 driver_factory->GetDriverForFrame(web_contents()->GetMainFrame()); | 220 driver_factory->GetDriverForFrame(web_contents()->GetMainFrame()); |
230 return driver->AsWeakPtr(); | 221 return driver->AsWeakPtr(); |
231 } | 222 } |
232 | 223 |
233 void CredentialManagerDispatcher::SendCredential(int request_id, | 224 void CredentialManagerImpl::SendCredential( |
234 const CredentialInfo& info) { | 225 const SendCredentialCallback& send_callback, |
| 226 const CredentialInfo& info) { |
235 DCHECK(pending_request_); | 227 DCHECK(pending_request_); |
236 DCHECK_EQ(pending_request_->id(), request_id); | 228 DCHECK(send_callback.Equals(pending_request_->send_callback())); |
237 | 229 |
238 web_contents()->GetRenderViewHost()->Send( | 230 send_callback.Run(info); |
239 new CredentialManagerMsg_SendCredential( | |
240 web_contents()->GetRenderViewHost()->GetRoutingID(), | |
241 pending_request_->id(), info)); | |
242 pending_request_.reset(); | 231 pending_request_.reset(); |
243 } | 232 } |
244 | 233 |
245 void CredentialManagerDispatcher::SendPasswordForm( | 234 void CredentialManagerImpl::SendPasswordForm( |
246 int request_id, | 235 const SendCredentialCallback& send_callback, |
247 const autofill::PasswordForm* form) { | 236 const autofill::PasswordForm* form) { |
248 CredentialInfo info; | 237 CredentialInfo info; |
249 if (form) { | 238 if (form) { |
250 password_manager::CredentialType type_to_return = | 239 password_manager::CredentialType type_to_return = |
251 form->federation_origin.unique() | 240 form->federation_origin.unique() |
252 ? CredentialType::CREDENTIAL_TYPE_PASSWORD | 241 ? CredentialType::CREDENTIAL_TYPE_PASSWORD |
253 : CredentialType::CREDENTIAL_TYPE_FEDERATED; | 242 : CredentialType::CREDENTIAL_TYPE_FEDERATED; |
254 info = CredentialInfo(*form, type_to_return); | 243 info = CredentialInfo(*form, type_to_return); |
255 if (PasswordStore* store = GetPasswordStore()) { | 244 if (PasswordStore* store = GetPasswordStore()) { |
256 if (form->skip_zero_click && IsZeroClickAllowed()) { | 245 if (form->skip_zero_click && IsZeroClickAllowed()) { |
257 DCHECK(IsUpdatingCredentialAllowed()); | 246 DCHECK(IsUpdatingCredentialAllowed()); |
258 autofill::PasswordForm update_form = *form; | 247 autofill::PasswordForm update_form = *form; |
259 update_form.skip_zero_click = false; | 248 update_form.skip_zero_click = false; |
260 store->UpdateLogin(update_form); | 249 store->UpdateLogin(update_form); |
261 } | 250 } |
262 } | 251 } |
263 } | 252 } |
264 SendCredential(request_id, info); | 253 SendCredential(send_callback, info); |
265 } | 254 } |
266 | 255 |
267 PasswordManagerClient* CredentialManagerDispatcher::client() const { | 256 PasswordManagerClient* CredentialManagerImpl::client() const { |
268 return client_; | 257 return client_; |
269 } | 258 } |
270 | 259 |
271 autofill::PasswordForm | 260 autofill::PasswordForm CredentialManagerImpl::GetSynthesizedFormForOrigin() |
272 CredentialManagerDispatcher::GetSynthesizedFormForOrigin() const { | 261 const { |
273 autofill::PasswordForm synthetic_form; | 262 autofill::PasswordForm synthetic_form; |
274 synthetic_form.origin = web_contents()->GetLastCommittedURL().GetOrigin(); | 263 synthetic_form.origin = web_contents()->GetLastCommittedURL().GetOrigin(); |
275 synthetic_form.signon_realm = synthetic_form.origin.spec(); | 264 synthetic_form.signon_realm = synthetic_form.origin.spec(); |
276 synthetic_form.scheme = autofill::PasswordForm::SCHEME_HTML; | 265 synthetic_form.scheme = autofill::PasswordForm::SCHEME_HTML; |
277 synthetic_form.ssl_valid = synthetic_form.origin.SchemeIsCryptographic() && | 266 synthetic_form.ssl_valid = synthetic_form.origin.SchemeIsCryptographic() && |
278 !client_->DidLastPageLoadEncounterSSLErrors(); | 267 !client_->DidLastPageLoadEncounterSSLErrors(); |
279 return synthetic_form; | 268 return synthetic_form; |
280 } | 269 } |
281 | 270 |
282 void CredentialManagerDispatcher::DoneRequiringUserMediation() { | 271 void CredentialManagerImpl::DoneRequiringUserMediation() { |
283 DCHECK(pending_require_user_mediation_); | 272 DCHECK(pending_require_user_mediation_); |
284 pending_require_user_mediation_.reset(); | 273 pending_require_user_mediation_.reset(); |
285 } | 274 } |
286 | 275 |
287 bool CredentialManagerDispatcher::IsUpdatingCredentialAllowed() const { | 276 bool CredentialManagerImpl::IsUpdatingCredentialAllowed() const { |
288 return !client_->DidLastPageLoadEncounterSSLErrors() && | 277 return !client_->DidLastPageLoadEncounterSSLErrors() && |
289 !client_->IsOffTheRecord(); | 278 !client_->IsOffTheRecord(); |
290 } | 279 } |
291 | 280 |
292 } // namespace password_manager | 281 } // namespace password_manager |
OLD | NEW |