Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp

Issue 2966523002: Blink-layer update to match WebAuthN spec (Closed)
Patch Set: Add ContectLifecycleObserver... part2 Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "modules/webauth/WebAuthentication.h" 5 #include "modules/webauth/WebAuthentication.h"
6 6
7 #include <stdint.h> 7 #include "bindings/core/v8/ArrayBufferOrArrayBufferView.h"
8
9 #include "bindings/core/v8/ScriptPromise.h" 8 #include "bindings/core/v8/ScriptPromise.h"
10 #include "bindings/core/v8/ScriptPromiseResolver.h" 9 #include "bindings/core/v8/ScriptPromiseResolver.h"
10 #include "core/dom/DOMArrayBuffer.h"
11 #include "core/dom/DOMException.h" 11 #include "core/dom/DOMException.h"
12 #include "core/dom/Document.h" 12 #include "core/dom/Document.h"
13 #include "core/dom/ExceptionCode.h" 13 #include "core/dom/ExceptionCode.h"
14 #include "core/frame/LocalFrame.h" 14 #include "core/frame/LocalFrame.h"
15 #include "modules/webauth/RelyingPartyAccount.h" 15 #include "modules/webauth/AuthenticatorAttestationResponse.h"
16 #include "modules/webauth/ScopedCredential.h" 16 #include "modules/webauth/MakeCredentialOptions.h"
17 #include "modules/webauth/ScopedCredentialOptions.h" 17 #include "public/platform/InterfaceProvider.h"
18 #include "modules/webauth/ScopedCredentialParameters.h"
19 #include "services/service_manager/public/cpp/interface_provider.h" 18 #include "services/service_manager/public/cpp/interface_provider.h"
20 19
20 namespace blink {
21 typedef ArrayBufferOrArrayBufferView BufferSource;
22 } // namespace blink
23
21 namespace { 24 namespace {
22 const char kNoAuthenticatorError[] = "Authenticator unavailable."; 25 constexpr char kNoAuthenticatorError[] = "Authenticator unavailable.";
23 // Time to wait for an authenticator to successfully complete an operation. 26 // Time to wait for an authenticator to successfully complete an operation.
24 const int kAdjustedTimeoutLowerInSeconds = 60; 27 constexpr WTF::TimeDelta kAdjustedTimeoutLower = WTF::TimeDelta::FromMinutes(1);
25 const int kAdjustedTimeoutUpperInSeconds = 120; 28 constexpr WTF::TimeDelta kAdjustedTimeoutUpper = WTF::TimeDelta::FromMinutes(2);
26 } // anonymous namespace 29 } // anonymous namespace
27 30
28 namespace mojo { 31 namespace mojo {
29 using webauth::mojom::blink::RelyingPartyAccount;
30 using webauth::mojom::blink::RelyingPartyAccountPtr;
31 using webauth::mojom::blink::AuthenticatorStatus; 32 using webauth::mojom::blink::AuthenticatorStatus;
32 using webauth::mojom::blink::ScopedCredentialDescriptor; 33 using webauth::mojom::blink::MakeCredentialOptionsPtr;
33 using webauth::mojom::blink::ScopedCredentialOptions; 34 using webauth::mojom::blink::PublicKeyCredentialEntityPtr;
34 using webauth::mojom::blink::ScopedCredentialOptionsPtr; 35 using webauth::mojom::blink::PublicKeyCredentialParametersPtr;
35 using webauth::mojom::blink::ScopedCredentialParameters; 36 using webauth::mojom::blink::PublicKeyCredentialType;
36 using webauth::mojom::blink::ScopedCredentialParametersPtr; 37 using webauth::mojom::blink::AuthenticatorTransport;
37 using webauth::mojom::blink::ScopedCredentialType;
38 using webauth::mojom::blink::Transport;
39 38
40 // TODO(kpaulhamus): Make this a TypeConverter 39 // TODO(kpaulhamus): Make this a TypeConverter
41 Vector<uint8_t> ConvertBufferSource(const blink::BufferSource& buffer) { 40 Vector<uint8_t> ConvertBufferSource(const blink::BufferSource& buffer) {
42 DCHECK(!buffer.isNull()); 41 DCHECK(!buffer.isNull());
43 Vector<uint8_t> vector; 42 Vector<uint8_t> vector;
44 if (buffer.isArrayBuffer()) { 43 if (buffer.isArrayBuffer()) {
45 vector.Append(static_cast<uint8_t*>(buffer.getAsArrayBuffer()->Data()), 44 vector.Append(static_cast<uint8_t*>(buffer.getAsArrayBuffer()->Data()),
46 buffer.getAsArrayBuffer()->ByteLength()); 45 buffer.getAsArrayBuffer()->ByteLength());
47 } else { 46 } else {
47 DCHECK(buffer.isArrayBufferView());
48 vector.Append(static_cast<uint8_t*>( 48 vector.Append(static_cast<uint8_t*>(
49 buffer.getAsArrayBufferView().View()->BaseAddress()), 49 buffer.getAsArrayBufferView().View()->BaseAddress()),
50 buffer.getAsArrayBufferView().View()->byteLength()); 50 buffer.getAsArrayBufferView().View()->byteLength());
51 } 51 }
52 return vector; 52 return vector;
53 } 53 }
54 54
55 // TODO(kpaulhamus): Make this a TypeConverter 55 // TODO(kpaulhamus): Make this a TypeConverter
56 ScopedCredentialType ConvertScopedCredentialType(const String& cred_type) { 56 PublicKeyCredentialType ConvertPublicKeyCredentialType(const String& type) {
57 if (cred_type == "ScopedCred") 57 if (type == "public-key")
58 return ScopedCredentialType::SCOPEDCRED; 58 return PublicKeyCredentialType::PUBLIC_KEY;
59 NOTREACHED(); 59 NOTREACHED();
60 return ScopedCredentialType::SCOPEDCRED; 60 return PublicKeyCredentialType::PUBLIC_KEY;
61 } 61 }
62 62
63 // TODO(kpaulhamus): Make this a TypeConverter 63 // TODO(kpaulhamus): Make this a TypeConverter
64 Transport ConvertTransport(const String& transport) { 64 AuthenticatorTransport ConvertTransport(const String& transport) {
65 if (transport == "usb") 65 if (transport == "usb")
66 return Transport::USB; 66 return AuthenticatorTransport::USB;
67 if (transport == "nfc") 67 if (transport == "nfc")
68 return Transport::NFC; 68 return AuthenticatorTransport::NFC;
69 if (transport == "ble") 69 if (transport == "ble")
70 return Transport::BLE; 70 return AuthenticatorTransport::BLE;
71 NOTREACHED(); 71 NOTREACHED();
72 return Transport::USB; 72 return AuthenticatorTransport::USB;
73 } 73 }
74 74
75 // TODO(kpaulhamus): Make this a TypeConverter 75 // TODO(kpaulhamus): Make this a TypeConverter
76 RelyingPartyAccountPtr ConvertRelyingPartyAccount( 76 PublicKeyCredentialEntityPtr ConvertPublicKeyCredentialUserEntity(
77 const blink::RelyingPartyAccount& account_information, 77 const blink::PublicKeyCredentialUserEntity& user) {
78 blink::ScriptPromiseResolver* resolver) { 78 auto entity = webauth::mojom::blink::PublicKeyCredentialEntity::New();
79 auto mojo_account = RelyingPartyAccount::New(); 79 entity->id = user.id();
80 80 entity->name = user.name();
81 mojo_account->relying_party_display_name = 81 if (user.hasIcon()) {
82 account_information.rpDisplayName(); 82 entity->icon = blink::KURL(blink::KURL(), user.icon());
83 mojo_account->display_name = account_information.displayName(); 83 }
84 mojo_account->id = account_information.id(); 84 entity->display_name = user.displayName();
85 mojo_account->name = account_information.name(); 85 return entity;
86 mojo_account->image_url = account_information.imageURL();
87 return mojo_account;
88 } 86 }
89 87
90 // TODO(kpaulhamus): Make this a TypeConverter 88 // TODO(kpaulhamus): Make this a TypeConverter
91 ScopedCredentialOptionsPtr ConvertScopedCredentialOptions( 89 PublicKeyCredentialEntityPtr ConvertPublicKeyCredentialEntity(
92 const blink::ScopedCredentialOptions options, 90 const blink::PublicKeyCredentialEntity& rp) {
93 blink::ScriptPromiseResolver* resolver) { 91 auto entity = webauth::mojom::blink::PublicKeyCredentialEntity::New();
94 auto mojo_options = ScopedCredentialOptions::New(); 92 entity->id = rp.id();
95 if (options.hasRpId()) { 93 entity->name = rp.name();
96 // if rpID is missing, it will later be set to the origin of the page 94 if (rp.hasIcon()) {
97 // in the secure browser process. 95 entity->icon = blink::KURL(blink::KURL(), rp.icon());
98 mojo_options->relying_party_id = options.rpId(); 96 }
97 return entity;
98 }
99
100 // TODO(kpaulhamus): Make this a TypeConverter
101 PublicKeyCredentialParametersPtr ConvertPublicKeyCredentialParameters(
102 const blink::PublicKeyCredentialParameters parameter) {
103 auto mojo_parameter =
104 webauth::mojom::blink::PublicKeyCredentialParameters::New();
105 mojo_parameter->type = ConvertPublicKeyCredentialType(parameter.type());
106 // TODO(kpaulhamus): add AlgorithmIdentifier
107 return mojo_parameter;
108 }
109
110 // TODO(kpaulhamus): Make this a TypeConverter
111 MakeCredentialOptionsPtr ConvertMakeCredentialOptions(
112 const blink::MakeCredentialOptions options) {
113 auto mojo_options = webauth::mojom::blink::MakeCredentialOptions::New();
114 mojo_options->relying_party = ConvertPublicKeyCredentialEntity(options.rp());
115 mojo_options->user = ConvertPublicKeyCredentialUserEntity(options.user());
116 mojo_options->challenge = ConvertBufferSource(options.challenge());
117
118 Vector<webauth::mojom::blink::PublicKeyCredentialParametersPtr> parameters;
119 for (const auto& parameter : options.parameters()) {
120 parameters.push_back(ConvertPublicKeyCredentialParameters(parameter));
121 }
122 mojo_options->crypto_parameters = std::move(parameters);
123
124 // Step 4 of https://w3c.github.io/webauthn/#createCredential
125 WTF::TimeDelta adjusted_timeout;
126 if (options.hasTimeout()) {
127 adjusted_timeout = WTF::TimeDelta::FromMilliseconds(options.timeout());
128 } else {
129 adjusted_timeout = kAdjustedTimeoutLower;
99 } 130 }
100 131
101 // Step 4 of https://w3c.github.io/webauthn/#createCredential 132 mojo_options->adjusted_timeout = std::max(
102 int predicted_timeout = kAdjustedTimeoutLowerInSeconds; 133 kAdjustedTimeoutLower, std::min(kAdjustedTimeoutUpper, adjusted_timeout));
103 if (options.hasTimeoutSeconds()) {
104 predicted_timeout = static_cast<int>(options.timeoutSeconds());
105 }
106 134
107 mojo_options->adjusted_timeout = static_cast<double>( 135 if (options.hasExcludeCredentials()) {
108 std::max(kAdjustedTimeoutLowerInSeconds, 136 // Adds the excludeCredentials members
109 std::min(kAdjustedTimeoutUpperInSeconds, predicted_timeout))); 137 // (which are PublicKeyCredentialDescriptors)
110 138 for (const auto& descriptor : options.excludeCredentials()) {
111 if (options.hasExcludeList()) { 139 auto mojo_descriptor =
112 // Adds the excludeList members (which are ScopedCredentialDescriptors) 140 webauth::mojom::blink::PublicKeyCredentialDescriptor::New();
113 for (const auto& descriptor : options.excludeList()) { 141 mojo_descriptor->type = ConvertPublicKeyCredentialType(descriptor.type());
114 auto mojo_descriptor = ScopedCredentialDescriptor::New();
115 mojo_descriptor->type = ConvertScopedCredentialType(descriptor.type());
116 mojo_descriptor->id = ConvertBufferSource(descriptor.id()); 142 mojo_descriptor->id = ConvertBufferSource(descriptor.id());
117 for (const auto& transport : descriptor.transports()) 143 for (const auto& transport : descriptor.transports())
118 mojo_descriptor->transports.push_back(ConvertTransport(transport)); 144 mojo_descriptor->transports.push_back(ConvertTransport(transport));
119 mojo_options->exclude_list.push_back(std::move(mojo_descriptor)); 145 mojo_options->exclude_credentials.push_back(std::move(mojo_descriptor));
120 } 146 }
121 } 147 }
122 // TODO(kpaulhamus): add AuthenticationExtensions;
123 return mojo_options; 148 return mojo_options;
124 } 149 }
125 150
126 // TODO(kpaulhamus): Make this a TypeConverter
127 ScopedCredentialParametersPtr ConvertScopedCredentialParameter(
128 const blink::ScopedCredentialParameters parameter,
129 blink::ScriptPromiseResolver* resolver) {
130 auto mojo_parameter = ScopedCredentialParameters::New();
131 mojo_parameter->type = ConvertScopedCredentialType(parameter.type());
132 // TODO(kpaulhamus): add AlgorithmIdentifier
133 return mojo_parameter;
134 }
135
136 blink::DOMException* CreateExceptionFromStatus(AuthenticatorStatus status) { 151 blink::DOMException* CreateExceptionFromStatus(AuthenticatorStatus status) {
137 switch (status) { 152 switch (status) {
138 case AuthenticatorStatus::NOT_IMPLEMENTED: 153 case AuthenticatorStatus::NOT_IMPLEMENTED:
139 return blink::DOMException::Create(blink::kNotSupportedError, 154 return blink::DOMException::Create(blink::kNotSupportedError,
140 "Not implemented."); 155 "Not implemented.");
141 case AuthenticatorStatus::NOT_ALLOWED_ERROR: 156 case AuthenticatorStatus::NOT_ALLOWED_ERROR:
142 return blink::DOMException::Create(blink::kNotAllowedError, 157 return blink::DOMException::Create(blink::kNotAllowedError,
143 "Not allowed."); 158 "Not allowed.");
144 case AuthenticatorStatus::NOT_SUPPORTED_ERROR: 159 case AuthenticatorStatus::NOT_SUPPORTED_ERROR:
145 return blink::DOMException::Create( 160 return blink::DOMException::Create(
146 blink::kNotSupportedError, 161 blink::kNotSupportedError,
147 "Parameters for this operation are not supported."); 162 "Parameters for this operation are not supported.");
148 case AuthenticatorStatus::SECURITY_ERROR: 163 case AuthenticatorStatus::SECURITY_ERROR:
149 return blink::DOMException::Create(blink::kSecurityError, 164 return blink::DOMException::Create(blink::kSecurityError,
150 "The operation was not allowed."); 165 "The operation was not allowed.");
151 case AuthenticatorStatus::UNKNOWN_ERROR: 166 case AuthenticatorStatus::UNKNOWN_ERROR:
152 return blink::DOMException::Create(blink::kUnknownError, 167 return blink::DOMException::Create(blink::kUnknownError,
153 "Request failed."); 168 "Request failed.");
154 case AuthenticatorStatus::CANCELLED: 169 case AuthenticatorStatus::CANCELLED:
155 return blink::DOMException::Create(blink::kNotAllowedError, 170 return blink::DOMException::Create(blink::kNotAllowedError,
156 "User canceled the operation."); 171 "User canceled the operation.");
157 case AuthenticatorStatus::SUCCESS: 172 case AuthenticatorStatus::SUCCESS:
158 return nullptr; 173 return nullptr;
159 default: 174 default:
160 NOTREACHED(); 175 NOTREACHED();
161 return nullptr; 176 return nullptr;
162 } 177 }
163 } 178 }
179
164 } // namespace mojo 180 } // namespace mojo
165 181
166 namespace blink { 182 namespace blink {
183
167 WebAuthentication::WebAuthentication(LocalFrame& frame) 184 WebAuthentication::WebAuthentication(LocalFrame& frame)
168 : ContextLifecycleObserver(frame.GetDocument()) {} 185 : ContextLifecycleObserver(frame.GetDocument()) {
186 frame.GetInterfaceProvider().GetInterface(mojo::MakeRequest(&authenticator_));
187 authenticator_.set_connection_error_handler(ConvertToBaseCallback(
188 WTF::Bind(&WebAuthentication::OnAuthenticatorConnectionError,
189 WrapWeakPersistent(this))));
190 }
169 191
170 WebAuthentication::~WebAuthentication() { 192 WebAuthentication::~WebAuthentication() {
171 // |authenticator_| may still be valid but there should be no more 193 // |authenticator_| may still be valid but there should be no more
172 // outstanding requests because each holds a persistent handle to this object. 194 // outstanding requests because each holds a persistent handle to this object.
173 DCHECK(authenticator_requests_.IsEmpty()); 195 DCHECK(authenticator_requests_.IsEmpty());
174 } 196 }
175 197
176 ScriptPromise WebAuthentication::makeCredential( 198 ScriptPromise WebAuthentication::makeCredential(
177 ScriptState* script_state, 199 ScriptState* script_state,
178 const RelyingPartyAccount& account_information, 200 const MakeCredentialOptions& publicKey) {
179 const HeapVector<ScopedCredentialParameters> crypto_parameters,
180 const BufferSource& attestation_challenge,
181 ScopedCredentialOptions& options) {
182 ScriptPromise promise = RejectIfNotSupported(script_state); 201 ScriptPromise promise = RejectIfNotSupported(script_state);
183 if (!promise.IsEmpty()) 202 if (!promise.IsEmpty())
184 return promise; 203 return promise;
185 204
186 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); 205 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
187 206
188 Vector<uint8_t> buffer = mojo::ConvertBufferSource(attestation_challenge); 207 auto options = mojo::ConvertMakeCredentialOptions(publicKey);
189 auto opts = mojo::ConvertScopedCredentialOptions(options, resolver);
190 Vector<webauth::mojom::blink::ScopedCredentialParametersPtr> parameters;
191 for (const auto& parameter : crypto_parameters) {
192 if (parameter.hasType()) {
193 parameters.push_back(
194 mojo::ConvertScopedCredentialParameter(parameter, resolver));
195 }
196 }
197 auto account =
198 mojo::ConvertRelyingPartyAccount(account_information, resolver);
199 authenticator_requests_.insert(resolver); 208 authenticator_requests_.insert(resolver);
200 authenticator_->MakeCredential( 209 authenticator_->MakeCredential(
201 std::move(account), std::move(parameters), buffer, std::move(opts), 210 std::move(options), ConvertToBaseCallback(WTF::Bind(
202 ConvertToBaseCallback(WTF::Bind(&WebAuthentication::OnMakeCredential, 211 &WebAuthentication::OnMakeCredential,
203 WrapPersistent(this), 212 WrapPersistent(this), WrapPersistent(resolver))));
204 WrapPersistent(resolver))));
205 return resolver->Promise(); 213 return resolver->Promise();
206 } 214 }
207 215
208 ScriptPromise WebAuthentication::getAssertion( 216 ScriptPromise WebAuthentication::getAssertion(
209 ScriptState* script_state, 217 ScriptState* script_state,
210 const BufferSource& assertion_challenge, 218 const PublicKeyCredentialRequestOptions& publicKey) {
211 const AuthenticationAssertionOptions& options) {
212 NOTREACHED(); 219 NOTREACHED();
213 return ScriptPromise(); 220 return ScriptPromise();
214 } 221 }
215 222
216 void WebAuthentication::ContextDestroyed(ExecutionContext*) { 223 void WebAuthentication::ContextDestroyed(ExecutionContext*) {
217 Cleanup(); 224 Cleanup();
218 } 225 }
219 226
220 void WebAuthentication::OnMakeCredential( 227 void WebAuthentication::OnMakeCredential(
221 ScriptPromiseResolver* resolver, 228 ScriptPromiseResolver* resolver,
222 webauth::mojom::blink::AuthenticatorStatus status, 229 webauth::mojom::blink::AuthenticatorStatus status,
223 webauth::mojom::blink::ScopedCredentialInfoPtr credential) { 230 webauth::mojom::blink::PublicKeyCredentialInfoPtr credential) {
224 if (!MarkRequestComplete(resolver)) 231 if (!MarkRequestComplete(resolver))
225 return; 232 return;
226 233
227 DOMException* error = mojo::CreateExceptionFromStatus(status); 234 DOMException* error = mojo::CreateExceptionFromStatus(status);
228 if (error) { 235 if (error) {
229 DCHECK(!credential); 236 DCHECK(!credential);
230 resolver->Reject(error); 237 resolver->Reject(error);
231 Cleanup(); 238 Cleanup();
232 return; 239 return;
233 } 240 }
234 241
235 if (credential->client_data.IsEmpty() || credential->attestation.IsEmpty()) { 242 if (credential->client_data_json.IsEmpty() ||
243 credential->response->attestation_object.IsEmpty()) {
236 resolver->Reject( 244 resolver->Reject(
237 DOMException::Create(kNotFoundError, "No credential returned.")); 245 DOMException::Create(kNotFoundError, "No credentials returned."));
238 return;
239 } 246 }
240 247
241 DOMArrayBuffer* clientDataBuffer = DOMArrayBuffer::Create( 248 DOMArrayBuffer* client_data_buffer = DOMArrayBuffer::Create(
242 static_cast<void*>(&credential->client_data.front()), 249 static_cast<void*>(&credential->client_data_json.front()),
243 credential->client_data.size()); 250 credential->client_data_json.size());
244 251
245 DOMArrayBuffer* attestationBuffer = DOMArrayBuffer::Create( 252 // Return AuthenticatorAttestationResponse
246 static_cast<void*>(&credential->attestation.front()), 253 DOMArrayBuffer* attestation_buffer = DOMArrayBuffer::Create(
247 credential->attestation.size()); 254 static_cast<void*>(&credential->response->attestation_object.front()),
255 credential->response->attestation_object.size());
248 256
249 ScopedCredentialInfo* scopedCredential = 257 AuthenticatorAttestationResponse* attestation_response =
250 ScopedCredentialInfo::Create(clientDataBuffer, attestationBuffer); 258 AuthenticatorAttestationResponse::Create(client_data_buffer,
251 resolver->Resolve(scopedCredential); 259 attestation_buffer);
260 resolver->Resolve(attestation_response);
252 } 261 }
253 262
254 ScriptPromise WebAuthentication::RejectIfNotSupported( 263 ScriptPromise WebAuthentication::RejectIfNotSupported(
255 ScriptState* script_state) { 264 ScriptState* script_state) {
265 LocalFrame* frame =
266 ToDocument(ExecutionContext::From(script_state))->GetFrame();
256 if (!authenticator_) { 267 if (!authenticator_) {
257 if (!GetFrame()) { 268 if (!frame) {
258 return ScriptPromise::RejectWithDOMException( 269 return ScriptPromise::RejectWithDOMException(
259 script_state, DOMException::Create(kNotSupportedError)); 270 script_state, DOMException::Create(kNotSupportedError));
260 } 271 }
261 GetFrame()->GetInterfaceProvider().GetInterface( 272 frame->GetInterfaceProvider().GetInterface(
262 mojo::MakeRequest(&authenticator_)); 273 mojo::MakeRequest(&authenticator_));
263 274
264 authenticator_.set_connection_error_handler(ConvertToBaseCallback( 275 authenticator_.set_connection_error_handler(ConvertToBaseCallback(
265 WTF::Bind(&WebAuthentication::OnAuthenticatorConnectionError, 276 WTF::Bind(&WebAuthentication::OnAuthenticatorConnectionError,
266 WrapWeakPersistent(this)))); 277 WrapWeakPersistent(this))));
267 } 278 }
268 return ScriptPromise(); 279 return ScriptPromise();
269 } 280 }
270 281
271 void WebAuthentication::OnAuthenticatorConnectionError() { 282 void WebAuthentication::OnAuthenticatorConnectionError() {
(...skipping 17 matching lines...) Expand all
289 ContextLifecycleObserver::Trace(visitor); 300 ContextLifecycleObserver::Trace(visitor);
290 } 301 }
291 302
292 // Clears the promise resolver, timer, and closes the Mojo connection. 303 // Clears the promise resolver, timer, and closes the Mojo connection.
293 void WebAuthentication::Cleanup() { 304 void WebAuthentication::Cleanup() {
294 authenticator_.reset(); 305 authenticator_.reset();
295 authenticator_requests_.clear(); 306 authenticator_requests_.clear();
296 } 307 }
297 308
298 } // namespace blink 309 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698