blob: c3791bc636ad1c496b351bb81d39bd024233bf73 [file] [log] [blame]
// Copyright 2014 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.
#include "components/password_manager/content/renderer/credential_manager_client.h"
#include <stddef.h>
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/logging.h"
#include "components/password_manager/content/public/cpp/type_converters.h"
#include "components/password_manager/core/common/credential_manager_types.h"
#include "content/public/common/service_registry.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "mojo/common/url_type_converters.h"
#include "third_party/WebKit/public/platform/WebCredential.h"
#include "third_party/WebKit/public/platform/WebCredentialManagerError.h"
#include "third_party/WebKit/public/platform/WebFederatedCredential.h"
#include "third_party/WebKit/public/platform/WebPasswordCredential.h"
#include "third_party/WebKit/public/web/WebView.h"
namespace password_manager {
namespace {
blink::WebCredentialManagerError GetWebCredentialManagerErrorFromMojo(
mojom::CredentialManagerError error) {
switch (error) {
case mojom::CredentialManagerError::DISABLED:
return blink::WebCredentialManagerError::
WebCredentialManagerDisabledError;
case mojom::CredentialManagerError::PENDINGREQUEST:
return blink::WebCredentialManagerError::
WebCredentialManagerPendingRequestError;
case mojom::CredentialManagerError::PASSWORDSTOREUNAVAILABLE:
return blink::WebCredentialManagerError::
WebCredentialManagerPasswordStoreUnavailableError;
case mojom::CredentialManagerError::UNKNOWN:
return blink::WebCredentialManagerError::WebCredentialManagerUnknownError;
case mojom::CredentialManagerError::SUCCESS:
NOTREACHED();
break;
}
NOTREACHED();
return blink::WebCredentialManagerError::WebCredentialManagerUnknownError;
}
// Takes ownership of blink::WebCredentialManagerClient::NotificationCallbacks
// pointer. When the wrapper is destroyed, if |callbacks| is still alive
// its onError() will get called.
class NotificationCallbacksWrapper {
public:
explicit NotificationCallbacksWrapper(
blink::WebCredentialManagerClient::NotificationCallbacks* callbacks);
~NotificationCallbacksWrapper();
void NotifySuccess();
private:
std::unique_ptr<blink::WebCredentialManagerClient::NotificationCallbacks>
callbacks_;
DISALLOW_COPY_AND_ASSIGN(NotificationCallbacksWrapper);
};
NotificationCallbacksWrapper::NotificationCallbacksWrapper(
blink::WebCredentialManagerClient::NotificationCallbacks* callbacks)
: callbacks_(callbacks) {}
NotificationCallbacksWrapper::~NotificationCallbacksWrapper() {
if (callbacks_)
callbacks_->onError(blink::WebCredentialManagerUnknownError);
}
void NotificationCallbacksWrapper::NotifySuccess() {
// Call onSuccess() and reset callbacks to avoid calling onError() in
// destructor.
if (callbacks_) {
callbacks_->onSuccess();
callbacks_.reset();
}
}
// Takes ownership of blink::WebCredentialManagerClient::RequestCallbacks
// pointer. When the wrapper is destroied, if |callbacks| is still alive
// its onError() will get called.
class RequestCallbacksWrapper {
public:
explicit RequestCallbacksWrapper(
blink::WebCredentialManagerClient::RequestCallbacks* callbacks);
~RequestCallbacksWrapper();
void NotifySuccess(mojom::CredentialInfoPtr info);
void NotifyError(mojom::CredentialManagerError error);
private:
std::unique_ptr<blink::WebCredentialManagerClient::RequestCallbacks>
callbacks_;
DISALLOW_COPY_AND_ASSIGN(RequestCallbacksWrapper);
};
RequestCallbacksWrapper::RequestCallbacksWrapper(
blink::WebCredentialManagerClient::RequestCallbacks* callbacks)
: callbacks_(callbacks) {}
RequestCallbacksWrapper::~RequestCallbacksWrapper() {
if (callbacks_)
callbacks_->onError(blink::WebCredentialManagerUnknownError);
}
void RequestCallbacksWrapper::NotifySuccess(mojom::CredentialInfoPtr info) {
// Call onSuccess() and reset callbacks to avoid calling onError() in
// destructor.
if (callbacks_) {
std::unique_ptr<blink::WebCredential> credential =
info.To<std::unique_ptr<blink::WebCredential>>();
callbacks_->onSuccess(std::move(credential));
callbacks_.reset();
}
}
void RequestCallbacksWrapper::NotifyError(mojom::CredentialManagerError error) {
if (callbacks_) {
callbacks_->onError(GetWebCredentialManagerErrorFromMojo(error));
callbacks_.reset();
}
}
void RespondToNotificationCallback(
NotificationCallbacksWrapper* callbacks_wrapper) {
callbacks_wrapper->NotifySuccess();
}
void RespondToRequestCallback(RequestCallbacksWrapper* callbacks_wrapper,
mojom::CredentialManagerError error,
mojom::CredentialInfoPtr info) {
if (error == mojom::CredentialManagerError::SUCCESS) {
DCHECK(!info.is_null());
callbacks_wrapper->NotifySuccess(std::move(info));
} else {
DCHECK(info.is_null());
callbacks_wrapper->NotifyError(error);
}
}
} // namespace
CredentialManagerClient::CredentialManagerClient(
content::RenderView* render_view)
: content::RenderViewObserver(render_view) {
render_view->GetWebView()->setCredentialManagerClient(this);
}
CredentialManagerClient::~CredentialManagerClient() {}
// -----------------------------------------------------------------------------
// Access mojo CredentialManagerService.
void CredentialManagerClient::dispatchStore(
const blink::WebCredential& credential,
blink::WebCredentialManagerClient::NotificationCallbacks* callbacks) {
DCHECK(callbacks);
ConnectToMojoCMIfNeeded();
mojom::CredentialInfoPtr info = mojom::CredentialInfo::From(credential);
mojo_cm_service_->Store(
std::move(info),
base::Bind(&RespondToNotificationCallback,
base::Owned(new NotificationCallbacksWrapper(callbacks))));
}
void CredentialManagerClient::dispatchRequireUserMediation(
blink::WebCredentialManagerClient::NotificationCallbacks* callbacks) {
DCHECK(callbacks);
ConnectToMojoCMIfNeeded();
mojo_cm_service_->RequireUserMediation(
base::Bind(&RespondToNotificationCallback,
base::Owned(new NotificationCallbacksWrapper(callbacks))));
}
void CredentialManagerClient::dispatchGet(
bool zero_click_only,
bool include_passwords,
const blink::WebVector<blink::WebURL>& federations,
RequestCallbacks* callbacks) {
DCHECK(callbacks);
ConnectToMojoCMIfNeeded();
std::vector<GURL> federation_vector;
for (size_t i = 0; i < std::min(federations.size(), kMaxFederations); ++i)
federation_vector.push_back(federations[i]);
mojo_cm_service_->Get(
zero_click_only, include_passwords,
mojo::Array<mojo::String>::From(federation_vector),
base::Bind(&RespondToRequestCallback,
base::Owned(new RequestCallbacksWrapper(callbacks))));
}
void CredentialManagerClient::ConnectToMojoCMIfNeeded() {
if (mojo_cm_service_)
return;
content::RenderFrame* main_frame = render_view()->GetMainRenderFrame();
main_frame->GetServiceRegistry()->ConnectToRemoteService(
mojo::GetProxy(&mojo_cm_service_));
}
} // namespace password_manager