summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormkwst@chromium.org <mkwst@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-22 12:56:50 +0000
committermkwst@chromium.org <mkwst@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-22 12:58:34 +0000
commite08e2f502b4dafd1c2574011c3dde43c5709524b (patch)
tree8e272c00b28c003e3fb536e04ab30e52a827f286
parent73902b67c97fda182d22991a9e7faa110f926531 (diff)
downloadchromium_src-e08e2f502b4dafd1c2574011c3dde43c5709524b.zip
chromium_src-e08e2f502b4dafd1c2574011c3dde43c5709524b.tar.gz
chromium_src-e08e2f502b4dafd1c2574011c3dde43c5709524b.tar.bz2
Credential Manager: Renderer-side implementation.
This patch does three things: 1. Implements the Blink platform interface WebCredentialManagerClient by adding a CredentialManagerClient class to the password manager component. 2. Wires that implementation up to Blink's platform layer by creating an instance of the new client, held in ChromeContentRendererClient, and setting it as each new RenderView's client. 3. Stubs out IPCs for the renderer to pass messages up to the browser in order to do the heavy lifting of actually answering Blink's requests by generating and delivering Credential objects. BUG=400674 TBR=tkent@chromium.org Review URL: https://codereview.chromium.org/464883002 Cr-Commit-Position: refs/heads/master@{#291390} git-svn-id: svn://svn.chromium.org/chrome/trunk/src@291390 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/chrome_common.gypi1
-rw-r--r--chrome/chrome_renderer.gypi1
-rw-r--r--chrome/common/BUILD.gn1
-rw-r--r--chrome/renderer/BUILD.gn1
-rw-r--r--chrome/renderer/DEPS1
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc8
-rw-r--r--chrome/renderer/chrome_content_renderer_client.h6
-rw-r--r--components/components_tests.gyp5
-rw-r--r--components/password_manager.gypi73
-rw-r--r--components/password_manager/content/common/BUILD.gn21
-rw-r--r--components/password_manager/content/common/DEPS4
-rw-r--r--components/password_manager/content/common/OWNERS12
-rw-r--r--components/password_manager/content/common/credential_manager_message_generator.cc33
-rw-r--r--components/password_manager/content/common/credential_manager_message_generator.h7
-rw-r--r--components/password_manager/content/common/credential_manager_messages.h93
-rw-r--r--components/password_manager/content/common/credential_manager_types.cc24
-rw-r--r--components/password_manager/content/common/credential_manager_types.h59
-rw-r--r--components/password_manager/content/renderer/BUILD.gn45
-rw-r--r--components/password_manager/content/renderer/DEPS7
-rw-r--r--components/password_manager/content/renderer/credential_manager_client.cc173
-rw-r--r--components/password_manager/content/renderer/credential_manager_client.h114
-rw-r--r--components/password_manager/content/renderer/credential_manager_client_unittest.cc215
-rw-r--r--components/password_manager/content/renderer/test_credential_manager_client.cc20
-rw-r--r--components/password_manager/content/renderer/test_credential_manager_client.h27
-rw-r--r--ipc/ipc_message_start.h1
25 files changed, 947 insertions, 5 deletions
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index e41ab38..ddf250a 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -369,6 +369,7 @@
'<(DEPTH)/components/components.gyp:autofill_core_common',
'<(DEPTH)/components/components.gyp:autofill_content_common',
'<(DEPTH)/components/components.gyp:password_manager_core_common',
+ '<(DEPTH)/components/components.gyp:password_manager_content_common',
'<(DEPTH)/components/components.gyp:signin_core_common',
'<(DEPTH)/components/components.gyp:translate_content_common',
'<(DEPTH)/components/components.gyp:visitedlink_common',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 583ffea..151e5bc 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -279,6 +279,7 @@
'../components/components.gyp:cdm_renderer',
'../components/components.gyp:data_reduction_proxy_common',
'../components/components.gyp:startup_metric_utils',
+ '../components/components.gyp:password_manager_content_renderer',
'../components/components.gyp:plugins_renderer',
'../components/components.gyp:translate_content_renderer',
'../components/components.gyp:translate_core_common',
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 1903837..d489c05 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -87,6 +87,7 @@ static_library("common") {
"//components/visitedlink/common",
"//components/autofill/content/common",
"//components/autofill/core/common",
+ "//components/password_manager/content/common",
"//components/password_manager/core/common",
"//components/signin/core/common",
"//components/translate/content/common",
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index 634570d..c1d9e42 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -38,6 +38,7 @@ static_library("renderer") {
"//components/autofill/content/renderer",
"//components/cdm/renderer",
"//components/data_reduction_proxy/common",
+ "//components/password_manager/content/renderer",
"//components/plugins/renderer",
"//components/startup_metric_utils",
"//components/translate/core/common",
diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS
index b455951..83f3464 100644
--- a/chrome/renderer/DEPS
+++ b/chrome/renderer/DEPS
@@ -11,6 +11,7 @@ include_rules = [
"+components/dom_distiller/core",
"+components/nacl/common",
"+components/nacl/renderer",
+ "+components/password_manager/content/renderer",
"+components/plugins/renderer",
"+components/signin/core/common",
"+components/translate/content/common",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 2aa64c2..b122262 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -74,6 +74,7 @@
#include "components/autofill/content/renderer/password_generation_agent.h"
#include "components/dom_distiller/core/url_constants.h"
#include "components/nacl/renderer/ppb_nacl_private_impl.h"
+#include "components/password_manager/content/renderer/credential_manager_client.h"
#include "components/plugins/renderer/mobile_youtube_plugin.h"
#include "components/signin/core/common/profile_management_switches.h"
#include "components/visitedlink/renderer/visitedlink_slave.h"
@@ -314,6 +315,9 @@ void ChromeContentRendererClient::RenderThreadStarted() {
#endif
search_bouncer_.reset(new SearchBouncer());
+ credential_manager_client_.reset(
+ new password_manager::CredentialManagerClient());
+
thread->AddObserver(chrome_observer_.get());
thread->AddObserver(extension_dispatcher_.get());
#if defined(FULL_SAFE_BROWSING)
@@ -322,6 +326,7 @@ void ChromeContentRendererClient::RenderThreadStarted() {
thread->AddObserver(visited_link_slave_.get());
thread->AddObserver(prerender_dispatcher_.get());
thread->AddObserver(search_bouncer_.get());
+ thread->AddObserver(credential_manager_client_.get());
#if defined(ENABLE_WEBRTC)
thread->AddFilter(webrtc_logging_message_filter_.get());
@@ -493,6 +498,9 @@ void ChromeContentRendererClient::RenderViewCreated(
new SearchBox(render_view);
new ChromeRenderViewObserver(render_view, chrome_observer_.get());
+
+ if (credential_manager_client_)
+ credential_manager_client_->OnRenderViewCreated(render_view);
}
void ChromeContentRendererClient::SetNumberOfViews(int number_of_views) {
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index 32bf76f..748c7df 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -54,6 +54,10 @@ namespace blink {
class WebSecurityOrigin;
}
+namespace password_manager {
+class CredentialManagerClient;
+}
+
#if defined(ENABLE_WEBRTC)
class WebRtcLoggingMessageFilter;
#endif
@@ -191,6 +195,8 @@ class ChromeContentRendererClient : public content::ContentRendererClient {
permissions_policy_delegate_;
scoped_ptr<PrescientNetworkingDispatcher> prescient_networking_dispatcher_;
scoped_ptr<RendererNetPredictor> net_predictor_;
+ scoped_ptr<password_manager::CredentialManagerClient>
+ credential_manager_client_;
#if defined(ENABLE_SPELLCHECK)
scoped_ptr<SpellCheck> spellcheck_;
#endif
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 11c0131..3d3478d 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -411,6 +411,7 @@
'sources': [
'autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc',
'dom_distiller/content/dom_distiller_viewer_source_unittest.cc',
+ 'password_manager/content/renderer/credential_manager_client_unittest.cc',
'power/origin_power_map_unittest.cc',
'usb_service/usb_context_unittest.cc',
'usb_service/usb_device_filter_unittest.cc',
@@ -435,6 +436,10 @@
# Dependencies of precache/content
'components.gyp:precache_content',
+ # Dependencies of password_manager
+ 'components.gyp:password_manager_content_renderer',
+ 'components.gyp:password_manager_content_renderer_test_support',
+
# Dependencies of power
'components.gyp:power',
diff --git a/components/password_manager.gypi b/components/password_manager.gypi
index f77e98f..62be18a 100644
--- a/components/password_manager.gypi
+++ b/components/password_manager.gypi
@@ -157,20 +157,83 @@
['OS != "ios"', {
'targets': [
{
+ # GN version: //components/password_manager/content/common
+ 'target_name': 'password_manager_content_common',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../content/content.gyp:content_common',
+ '../ipc/ipc.gyp:ipc',
+ '../third_party/WebKit/public/blink.gyp:blink_minimal',
+ 'password_manager_core_common',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'password_manager/content/common/credential_manager_message_generator.cc',
+ 'password_manager/content/common/credential_manager_message_generator.h',
+ 'password_manager/content/common/credential_manager_messages.h',
+ 'password_manager/content/common/credential_manager_types.cc',
+ 'password_manager/content/common/credential_manager_types.h',
+ ],
+ },
+ {
+ # GN version: //components/password_manager/content/renderer
+ 'target_name': 'password_manager_content_renderer',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../content/content.gyp:content_common',
+ '../ipc/ipc.gyp:ipc',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ 'password_manager_core_common',
+ 'password_manager_content_common',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'password_manager/content/renderer/credential_manager_client.cc',
+ 'password_manager/content/renderer/credential_manager_client.h',
+ ],
+ },
+ {
+ # GN version: //components/password_manager/core/browser:test_support
+ 'target_name': 'password_manager_content_renderer_test_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'password_manager_content_common',
+ '../base/base.gyp:base',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ # Note: sources list duplicated in GN build.
+ 'password_manager/content/renderer/test_credential_manager_client.cc',
+ 'password_manager/content/renderer/test_credential_manager_client.h',
+ ],
+ },
+ {
# GN version: //components/password_manager/content/browser
'target_name': 'password_manager_content_browser',
'type': 'static_library',
'dependencies': [
- 'autofill_content_browser',
- 'autofill_content_common',
- 'autofill_core_common',
- 'keyed_service_content',
- 'password_manager_core_browser',
'../base/base.gyp:base',
'../content/content.gyp:content_browser',
'../content/content.gyp:content_common',
'../ipc/ipc.gyp:ipc',
'../net/net.gyp:net',
+ 'autofill_content_browser',
+ 'autofill_content_common',
+ 'autofill_core_common',
+ 'keyed_service_content',
+ 'password_manager_core_browser',
+ 'password_manager_content_common',
],
'include_dirs': [
'..',
diff --git a/components/password_manager/content/common/BUILD.gn b/components/password_manager/content/common/BUILD.gn
new file mode 100644
index 0000000..88d4d12
--- /dev/null
+++ b/components/password_manager/content/common/BUILD.gn
@@ -0,0 +1,21 @@
+# 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.
+
+static_library("common") {
+ sources = [
+ "credential_manager_message_generator.cc",
+ "credential_manager_message_generator.h",
+ "credential_manager_messages.h",
+ "credential_manager_types.cc",
+ "credential_manager_types.h",
+ ]
+
+ deps = [
+ "//base",
+ "//content/public/common",
+ "//ipc",
+ "//third_party/WebKit/public:blink",
+ "//url",
+ ]
+}
diff --git a/components/password_manager/content/common/DEPS b/components/password_manager/content/common/DEPS
new file mode 100644
index 0000000..c3505fa
--- /dev/null
+++ b/components/password_manager/content/common/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+content/public/common",
+ "+ipc",
+]
diff --git a/components/password_manager/content/common/OWNERS b/components/password_manager/content/common/OWNERS
new file mode 100644
index 0000000..d222cc3
--- /dev/null
+++ b/components/password_manager/content/common/OWNERS
@@ -0,0 +1,12 @@
+# Changes to IPC messages require a security review to avoid introducing
+# new sandbox escapes.
+per-file credential_manager_messages*.h=set noparent
+per-file credential_manager_messages*.h=cevans@chromium.org
+per-file credential_manager_messages*.h=dcheng@chromium.org
+per-file credential_manager_messages*.h=inferno@chromium.org
+per-file credential_manager_messages*.h=jln@chromium.org
+per-file credential_manager_messages*.h=jschuh@chromium.org
+per-file credential_manager_messages*.h=kenrb@chromium.org
+per-file credential_manager_messages*.h=nasko@chromium.org
+per-file credential_manager_messages*.h=palmer@chromium.org
+per-file credential_manager_messages*.h=tsepez@chromium.org
diff --git a/components/password_manager/content/common/credential_manager_message_generator.cc b/components/password_manager/content/common/credential_manager_message_generator.cc
new file mode 100644
index 0000000..55eaf88
--- /dev/null
+++ b/components/password_manager/content/common/credential_manager_message_generator.cc
@@ -0,0 +1,33 @@
+// 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.
+
+// Get basic type definitions.
+#define IPC_MESSAGE_IMPL
+#include "components/password_manager/content/common/credential_manager_message_generator.h"
+
+// Generate constructors.
+#include "ipc/struct_constructor_macros.h"
+#include "components/password_manager/content/common/credential_manager_message_generator.h"
+
+// Generate destructors.
+#include "ipc/struct_destructor_macros.h"
+#include "components/password_manager/content/common/credential_manager_message_generator.h"
+
+// Generate param traits write methods.
+#include "ipc/param_traits_write_macros.h"
+namespace IPC {
+#include "components/password_manager/content/common/credential_manager_message_generator.h"
+} // namespace IPC
+
+// Generate param traits read methods.
+#include "ipc/param_traits_read_macros.h"
+namespace IPC {
+#include "components/password_manager/content/common/credential_manager_message_generator.h"
+} // namespace IPC
+
+// Generate param traits log methods.
+#include "ipc/param_traits_log_macros.h"
+namespace IPC {
+#include "components/password_manager/content/common/credential_manager_message_generator.h"
+} // namespace IPC
diff --git a/components/password_manager/content/common/credential_manager_message_generator.h b/components/password_manager/content/common/credential_manager_message_generator.h
new file mode 100644
index 0000000..c818a13
--- /dev/null
+++ b/components/password_manager/content/common/credential_manager_message_generator.h
@@ -0,0 +1,7 @@
+// 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.
+
+// Multiply-included file, hence no include guard.
+
+#include "components/password_manager/content/common/credential_manager_messages.h"
diff --git a/components/password_manager/content/common/credential_manager_messages.h b/components/password_manager/content/common/credential_manager_messages.h
new file mode 100644
index 0000000..e496b94
--- /dev/null
+++ b/components/password_manager/content/common/credential_manager_messages.h
@@ -0,0 +1,93 @@
+// 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.
+
+// Message definition file, included multiple times, hence no include guard.
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "components/password_manager/content/common/credential_manager_types.h"
+#include "content/public/common/common_param_traits.h"
+#include "content/public/common/common_param_traits_macros.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_utils.h"
+#include "third_party/WebKit/public/platform/WebCredentialManagerError.h"
+#include "url/gurl.h"
+
+#define IPC_MESSAGE_START CredentialManagerMsgStart
+
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebCredentialManagerError::ErrorType,
+ blink::WebCredentialManagerError::ErrorTypeLast);
+
+IPC_ENUM_TRAITS_MAX_VALUE(password_manager::CredentialType,
+ password_manager::CREDENTIAL_TYPE_LAST);
+
+IPC_STRUCT_TRAITS_BEGIN(password_manager::CredentialInfo)
+ IPC_STRUCT_TRAITS_MEMBER(type)
+ IPC_STRUCT_TRAITS_MEMBER(id)
+ IPC_STRUCT_TRAITS_MEMBER(name)
+ IPC_STRUCT_TRAITS_MEMBER(avatar)
+ IPC_STRUCT_TRAITS_MEMBER(password)
+ IPC_STRUCT_TRAITS_MEMBER(federation)
+IPC_STRUCT_TRAITS_END()
+
+// ----------------------------------------------------------------------------
+// Messages sent from the renderer to the browser
+
+// Passes the notification from 'navigator.credentials.notifyFailedSignIn()' up
+// to the browser process in order to suppress the automatic bubble which would
+// pop up in order to prompt the user to save the credential she used for
+// signin. The browser process will respond with a
+// CredentialManagerMsg_AcknowledgeFailedSignedIn message.
+IPC_MESSAGE_ROUTED2(CredentialManagerHostMsg_NotifyFailedSignIn,
+ int /* request_id */,
+ password_manager::CredentialInfo /* credential */)
+
+// Passes the notification from 'navigator.credentials.notifySignedIn()' up to
+// the browser process in order to (among other things) prompt the user to save
+// the credential she used for signin. The browser process will respond with a
+// CredentialManagerMsg_AcknowledgeSignedIn message.
+IPC_MESSAGE_ROUTED2(CredentialManagerHostMsg_NotifySignedIn,
+ int /* request_id */,
+ password_manager::CredentialInfo /* credential */)
+
+// Passes the notification from 'navigator.credentials.notifySignedOut()' up to
+// the browser process in order to clear the "zeroclick" bit on that origin's
+// stored credentials. The browser process will respond with a
+// CredentialManagerMsg_AcknowledgeSignedOut message.
+IPC_MESSAGE_ROUTED1(CredentialManagerHostMsg_NotifySignedOut,
+ int /* request_id */)
+
+// Requests a credential from the browser process in response to a page calling
+// 'navigator.credentials.request()'. The browser process will respond with a
+// CredentialManagerMsg_SendCredential message.
+IPC_MESSAGE_ROUTED3(CredentialManagerHostMsg_RequestCredential,
+ int /* request_id */,
+ bool /* zero_click_only */,
+ std::vector<GURL> /* federations */)
+
+// ----------------------------------------------------------------------------
+// Messages sent from the browser to the renderer
+
+// Notify the renderer that the browser process has finished processing a
+// CredentialManagerHostMsg_NotifyFailedSignedIn message.
+IPC_MESSAGE_ROUTED1(CredentialManagerMsg_AcknowledgeFailedSignIn,
+ int /* request_id */);
+
+// Notify the renderer that the browser process has finished processing a
+// CredentialManagerHostMsg_NotifySignedIn message.
+IPC_MESSAGE_ROUTED1(CredentialManagerMsg_AcknowledgeSignedIn,
+ int /* request_id */);
+
+// Notify the renderer that the browser process has finished processing a
+// CredentialManagerHostMsg_NotifySignedOut message.
+IPC_MESSAGE_ROUTED1(CredentialManagerMsg_AcknowledgeSignedOut,
+ int /* request_id */);
+
+// Send a credential to the renderer in response to a
+// CredentialManagerHostMsg_RequestCredential message.
+IPC_MESSAGE_ROUTED2(CredentialManagerMsg_SendCredential,
+ int /* request_id */,
+ password_manager::CredentialInfo /* credential */)
diff --git a/components/password_manager/content/common/credential_manager_types.cc b/components/password_manager/content/common/credential_manager_types.cc
new file mode 100644
index 0000000..6d14d18
--- /dev/null
+++ b/components/password_manager/content/common/credential_manager_types.cc
@@ -0,0 +1,24 @@
+// 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/common/credential_manager_types.h"
+
+namespace password_manager {
+
+CredentialInfo::CredentialInfo() : type(CREDENTIAL_TYPE_UNKNOWN) {
+}
+
+CredentialInfo::CredentialInfo(const base::string16& id,
+ const base::string16& name,
+ const GURL& avatar)
+ : type(CREDENTIAL_TYPE_UNKNOWN),
+ id(id),
+ name(name),
+ avatar(avatar) {
+}
+
+CredentialInfo::~CredentialInfo() {
+}
+
+} // namespace password_manager
diff --git a/components/password_manager/content/common/credential_manager_types.h b/components/password_manager/content/common/credential_manager_types.h
new file mode 100644
index 0000000..68242c9
--- /dev/null
+++ b/components/password_manager/content/common/credential_manager_types.h
@@ -0,0 +1,59 @@
+// 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.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_CREDENTIAL_MANAGER_TYPES_H_
+#define COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_CREDENTIAL_MANAGER_TYPES_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/strings/string16.h"
+#include "url/gurl.h"
+
+namespace password_manager {
+
+// Limit the size of the federations array that we pass to the browser to
+// something reasonably sane.
+const size_t kMaxFederations = 50u;
+
+enum CredentialType {
+ CREDENTIAL_TYPE_UNKNOWN = 0,
+ CREDENTIAL_TYPE_LOCAL,
+ CREDENTIAL_TYPE_FEDERATED,
+ CREDENTIAL_TYPE_LAST = CREDENTIAL_TYPE_FEDERATED
+};
+
+struct CredentialInfo {
+ CredentialInfo();
+ CredentialInfo(const base::string16& id,
+ const base::string16& name,
+ const GURL& avatar);
+ ~CredentialInfo();
+
+ CredentialType type;
+
+ // An identifier (username, email address, etc). Corresponds to
+ // WebCredential's id property.
+ base::string16 id;
+
+ // An user-friendly name ("John Doe"). Corresponds to WebCredential's name
+ // property.
+ base::string16 name;
+
+ // The address of a user's avatar. Corresponds to WebCredential's avatar
+ // property.
+ GURL avatar;
+
+ // Corresponds to WebLocalCredential's password property.
+ base::string16 password;
+
+ // Corresponds to WebFederatedCredential's federation property, which is an
+ // origin serialized as a URL (e.g. "https://example.com/").
+ GURL federation;
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_CREDENTIAL_MANAGER_TYPES_H_
diff --git a/components/password_manager/content/renderer/BUILD.gn b/components/password_manager/content/renderer/BUILD.gn
new file mode 100644
index 0000000..137a2fb
--- /dev/null
+++ b/components/password_manager/content/renderer/BUILD.gn
@@ -0,0 +1,45 @@
+# 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.
+
+static_library("renderer") {
+ sources = [
+ "credential_manager_client.cc",
+ "credential_manager_client.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/strings",
+ "//ipc",
+ "//third_party/WebKit/public:blink",
+ "//url",
+ ]
+}
+
+static_library("test_support") {
+ sources = [
+ "test_credential_manager_client.cc",
+ "test_credential_manager_client.h",
+ ]
+
+ deps = [
+ "//testing/gmock",
+ "//third_party/WebKit/public:blink",
+ ]
+}
+
+source_set("unit_tests") {
+ sources = [
+ "credential_manager_client_unittest.cc"
+ ]
+
+ deps = [
+ ":renderer",
+ ":test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ "//third_party/WebKit/public:blink",
+ ]
+}
+
diff --git a/components/password_manager/content/renderer/DEPS b/components/password_manager/content/renderer/DEPS
new file mode 100644
index 0000000..0c6d17a
--- /dev/null
+++ b/components/password_manager/content/renderer/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+ "+content/public/common",
+ "+content/public/renderer",
+ "+content/test",
+ "+third_party/WebKit/public/platform",
+ "+third_party/WebKit/public/web",
+]
diff --git a/components/password_manager/content/renderer/credential_manager_client.cc b/components/password_manager/content/renderer/credential_manager_client.cc
new file mode 100644
index 0000000..8dd3f53
--- /dev/null
+++ b/components/password_manager/content/renderer/credential_manager_client.cc
@@ -0,0 +1,173 @@
+// 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 "components/password_manager/content/common/credential_manager_messages.h"
+#include "components/password_manager/content/common/credential_manager_types.h"
+#include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/render_view.h"
+#include "third_party/WebKit/public/platform/WebCredential.h"
+#include "third_party/WebKit/public/platform/WebCredentialManagerError.h"
+#include "third_party/WebKit/public/web/WebView.h"
+
+namespace password_manager {
+
+namespace {
+
+template <typename T>
+void ClearCallbacksMapWithErrors(T* callbacks_map) {
+ typename T::iterator iter(callbacks_map);
+ while (!iter.IsAtEnd()) {
+ blink::WebCredentialManagerError reason(
+ blink::WebCredentialManagerError::ErrorTypeUnknown,
+ "An unknown error occurred.");
+ iter.GetCurrentValue()->onError(&reason);
+ callbacks_map->Remove(iter.GetCurrentKey());
+ iter.Advance();
+ }
+}
+
+} // namespace
+
+CredentialManagerClient::CredentialManagerClient()
+ : routing_id_(MSG_ROUTING_NONE),
+ render_thread_(content::RenderThread::Get()) {
+ DCHECK(render_thread_);
+}
+
+CredentialManagerClient::~CredentialManagerClient() {
+ DisconnectFromRenderThread();
+
+ ClearCallbacksMapWithErrors(&failed_sign_in_callbacks_);
+ ClearCallbacksMapWithErrors(&signed_in_callbacks_);
+ ClearCallbacksMapWithErrors(&signed_out_callbacks_);
+ ClearCallbacksMapWithErrors(&request_callbacks_);
+}
+
+void CredentialManagerClient::OnRenderViewCreated(
+ content::RenderView* render_view) {
+ render_view->GetWebView()->setCredentialManagerClient(this);
+}
+
+void CredentialManagerClient::OnRenderProcessShutdown() {
+ DisconnectFromRenderThread();
+}
+
+int CredentialManagerClient::GetRoutingID() {
+ if (render_thread_ && routing_id_ == MSG_ROUTING_NONE) {
+ routing_id_ = render_thread_->GenerateRoutingID();
+ render_thread_->AddRoute(routing_id_, this);
+ }
+ return routing_id_;
+}
+
+void CredentialManagerClient::DisconnectFromRenderThread() {
+ if (render_thread_ && routing_id_ != MSG_ROUTING_NONE)
+ render_thread_->RemoveRoute(routing_id_);
+ render_thread_ = NULL;
+ routing_id_ = MSG_ROUTING_NONE;
+}
+
+// -----------------------------------------------------------------------------
+// Handle messages from the browser.
+
+bool CredentialManagerClient::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(CredentialManagerClient, message)
+ IPC_MESSAGE_HANDLER(CredentialManagerMsg_AcknowledgeFailedSignIn,
+ OnAcknowledgeFailedSignIn)
+ IPC_MESSAGE_HANDLER(CredentialManagerMsg_AcknowledgeSignedIn,
+ OnAcknowledgeSignedIn)
+ IPC_MESSAGE_HANDLER(CredentialManagerMsg_AcknowledgeSignedOut,
+ OnAcknowledgeSignedOut)
+ IPC_MESSAGE_HANDLER(CredentialManagerMsg_SendCredential, OnSendCredential)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void CredentialManagerClient::OnAcknowledgeFailedSignIn(int request_id) {
+ RespondToNotificationCallback(request_id, &failed_sign_in_callbacks_);
+}
+
+void CredentialManagerClient::OnAcknowledgeSignedIn(int request_id) {
+ RespondToNotificationCallback(request_id, &signed_in_callbacks_);
+}
+
+void CredentialManagerClient::OnAcknowledgeSignedOut(int request_id) {
+ RespondToNotificationCallback(request_id, &signed_out_callbacks_);
+}
+
+void CredentialManagerClient::OnSendCredential(int request_id,
+ const CredentialInfo& info) {
+ RequestCallbacks* callbacks = request_callbacks_.Lookup(request_id);
+ DCHECK(callbacks);
+ // TODO(mkwst): Split into local/federated credentials.
+ blink::WebCredential credential(info.id, info.name, info.avatar);
+ callbacks->onSuccess(&credential);
+ request_callbacks_.Remove(request_id);
+}
+
+// -----------------------------------------------------------------------------
+// Dispatch messages from the renderer to the browser.
+
+void CredentialManagerClient::dispatchFailedSignIn(
+ const blink::WebCredential& credential,
+ blink::WebCredentialManagerClient::NotificationCallbacks* callbacks) {
+ int request_id = failed_sign_in_callbacks_.Add(callbacks);
+ CredentialInfo info(
+ credential.id(), credential.name(), credential.avatarURL());
+ if (render_thread_) {
+ render_thread_->Send(new CredentialManagerHostMsg_NotifyFailedSignIn(
+ GetRoutingID(), request_id, info));
+ }
+}
+
+void CredentialManagerClient::dispatchSignedIn(
+ const blink::WebCredential& credential,
+ blink::WebCredentialManagerClient::NotificationCallbacks* callbacks) {
+ int request_id = signed_in_callbacks_.Add(callbacks);
+ CredentialInfo info(
+ credential.id(), credential.name(), credential.avatarURL());
+ if (render_thread_) {
+ render_thread_->Send(new CredentialManagerHostMsg_NotifySignedIn(
+ GetRoutingID(), request_id, info));
+ }
+}
+
+void CredentialManagerClient::dispatchSignedOut(
+ NotificationCallbacks* callbacks) {
+ int request_id = signed_out_callbacks_.Add(callbacks);
+ if (render_thread_) {
+ render_thread_->Send(new CredentialManagerHostMsg_NotifySignedOut(
+ GetRoutingID(), request_id));
+ }
+}
+
+void CredentialManagerClient::dispatchRequest(
+ bool zeroClickOnly,
+ const blink::WebVector<blink::WebURL>& federations,
+ RequestCallbacks* callbacks) {
+ int request_id = request_callbacks_.Add(callbacks);
+ std::vector<GURL> federation_vector;
+ for (size_t i = 0; i < std::min(federations.size(), kMaxFederations); ++i)
+ federation_vector.push_back(federations[i]);
+ if (render_thread_) {
+ render_thread_->Send(new CredentialManagerHostMsg_RequestCredential(
+ GetRoutingID(), request_id, zeroClickOnly, federation_vector));
+ }
+}
+
+void CredentialManagerClient::RespondToNotificationCallback(
+ int request_id,
+ CredentialManagerClient::NotificationCallbacksMap* map) {
+ blink::WebCredentialManagerClient::NotificationCallbacks* callbacks =
+ map->Lookup(request_id);
+ DCHECK(callbacks);
+ callbacks->onSuccess();
+ map->Remove(request_id);
+}
+
+} // namespace password_manager
diff --git a/components/password_manager/content/renderer/credential_manager_client.h b/components/password_manager/content/renderer/credential_manager_client.h
new file mode 100644
index 0000000..5e681e2
--- /dev/null
+++ b/components/password_manager/content/renderer/credential_manager_client.h
@@ -0,0 +1,114 @@
+// 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.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CONTENT_RENDERER_CREDENTIAL_MANAGER_CLIENT_H_
+#define COMPONENTS_PASSWORD_MANAGER_CONTENT_RENDERER_CREDENTIAL_MANAGER_CLIENT_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/id_map.h"
+#include "content/public/renderer/render_process_observer.h"
+#include "ipc/ipc_listener.h"
+#include "third_party/WebKit/public/platform/WebCredentialManagerClient.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+
+namespace blink {
+class WebCredential;
+class WebURL;
+}
+
+namespace content {
+class RenderThread;
+class RenderView;
+}
+
+namespace password_manager {
+
+struct CredentialInfo;
+
+// The CredentialManagerClient implements the Blink platform interface
+// WebCredentialManagerClient, and acts as an intermediary between Blink-side
+// calls to 'navigator.credential.*' and the password manager internals which
+// live in the browser process.
+//
+// One instance of CredentialManagerClient is created per RenderThread,
+// held in a scoped_ptr on ChromeContentRendererClient. The client holds
+// a raw pointer to the RenderThread on which it lives, and uses that pointer
+// to send messages to the browser process, and to route responses to itself.
+//
+// When the render thread is shut down (or the client is destructed), the
+// routing is removed, the pointer is cleared, and any pending responses are
+// rejected.
+//
+// Note that each RenderView's WebView holds a pointer to the
+// CredentialManagerClient (set in 'OnRenderViewCreated()'). The client is
+// guaranteed to outlive the views that point to it.
+class CredentialManagerClient : public blink::WebCredentialManagerClient,
+ public content::RenderProcessObserver,
+ public IPC::Listener {
+ public:
+ CredentialManagerClient();
+ virtual ~CredentialManagerClient();
+
+ // When a RenderView is created, we need to set this object as its client.
+ void OnRenderViewCreated(content::RenderView*);
+
+ // content::RenderProcessObserver:
+ virtual void OnRenderProcessShutdown() OVERRIDE;
+
+ // IPC::Listener:
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ // Message handlers for messages from the browser process:
+ virtual void OnAcknowledgeFailedSignIn(int request_id);
+ virtual void OnAcknowledgeSignedIn(int request_id);
+ virtual void OnAcknowledgeSignedOut(int request_id);
+ virtual void OnSendCredential(int request_id,
+ const CredentialInfo& credential_info);
+
+ // blink::WebCredentialManager:
+ virtual void dispatchFailedSignIn(
+ const blink::WebCredential& credential,
+ WebCredentialManagerClient::NotificationCallbacks* callbacks) OVERRIDE;
+ virtual void dispatchSignedIn(
+ const blink::WebCredential& credential,
+ WebCredentialManagerClient::NotificationCallbacks* callbacks) OVERRIDE;
+ virtual void dispatchSignedOut(NotificationCallbacks* callbacks) OVERRIDE;
+ virtual void dispatchRequest(
+ bool zero_click_only,
+ const blink::WebVector<blink::WebURL>& federations,
+ RequestCallbacks* callbacks) OVERRIDE;
+
+ protected:
+ virtual int GetRoutingID();
+
+ private:
+ typedef IDMap<blink::WebCredentialManagerClient::RequestCallbacks,
+ IDMapOwnPointer> RequestCallbacksMap;
+ typedef IDMap<blink::WebCredentialManagerClient::NotificationCallbacks,
+ IDMapOwnPointer> NotificationCallbacksMap;
+
+ void RespondToNotificationCallback(int request_id,
+ NotificationCallbacksMap* map);
+
+ // Nulls out the raw pointer to |render_thread_| after ensuring that any
+ // message routing is removed.
+ void DisconnectFromRenderThread();
+
+ int routing_id_;
+ content::RenderThread* render_thread_;
+
+ // Track the various blink::WebCredentialManagerClient::*Callbacks objects
+ // generated from Blink. This class takes ownership of these objects.
+ NotificationCallbacksMap failed_sign_in_callbacks_;
+ NotificationCallbacksMap signed_in_callbacks_;
+ NotificationCallbacksMap signed_out_callbacks_;
+ RequestCallbacksMap request_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(CredentialManagerClient);
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CONTENT_RENDERER_CREDENTIAL_MANAGER_CLIENT_H_
diff --git a/components/password_manager/content/renderer/credential_manager_client_unittest.cc b/components/password_manager/content/renderer/credential_manager_client_unittest.cc
new file mode 100644
index 0000000..92f6a6e
--- /dev/null
+++ b/components/password_manager/content/renderer/credential_manager_client_unittest.cc
@@ -0,0 +1,215 @@
+// 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/common/credential_manager_messages.h"
+#include "components/password_manager/content/renderer/credential_manager_client.h"
+#include "components/password_manager/content/renderer/test_credential_manager_client.h"
+#include "content/public/test/mock_render_thread.h"
+#include "content/test/blink_test_environment.h"
+#include "ipc/ipc_test_sink.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebCredential.h"
+#include "third_party/WebKit/public/platform/WebCredentialManagerClient.h"
+#include "third_party/WebKit/public/platform/WebCredentialManagerError.h"
+
+namespace password_manager {
+
+namespace {
+
+class CredentialManagerClientTest : public testing::Test {
+ public:
+ CredentialManagerClientTest()
+ : callback_errored_(false),
+ callback_succeeded_(false) {}
+ virtual ~CredentialManagerClientTest() {}
+
+ static void SetUpTestCase() { content::SetUpBlinkTestEnvironment(); }
+
+ static void TearDownTestCase() { content::TearDownBlinkTestEnvironment(); }
+
+ IPC::TestSink& sink() { return render_thread_.sink(); }
+
+ // The browser's response to any of the messages the client sends must contain
+ // a request ID so that the client knows which request is being serviced. This
+ // method grabs the ID from an outgoing |message_id| message, and sets the
+ // |request_id| param to its value. If no request ID can be found, the method
+ // returns false, and the |request_id| is set to -1.
+ //
+ // Clears any pending messages upon return.
+ bool ExtractRequestId(uint32 message_id, int& request_id) {
+ request_id = -1;
+ const IPC::Message* message = sink().GetFirstMessageMatching(message_id);
+ if (!message)
+ return false;
+
+ switch (message_id) {
+ case CredentialManagerHostMsg_NotifyFailedSignIn::ID: {
+ Tuple2<int, CredentialInfo> param;
+ CredentialManagerHostMsg_NotifyFailedSignIn::Read(message, &param);
+ request_id = param.a;
+ break;
+ }
+
+ case CredentialManagerHostMsg_NotifySignedIn::ID: {
+ Tuple2<int, CredentialInfo> param;
+ CredentialManagerHostMsg_NotifySignedIn::Read(message, &param);
+ request_id = param.a;
+ break;
+ }
+
+ case CredentialManagerHostMsg_NotifySignedOut::ID: {
+ Tuple1<int> param;
+ CredentialManagerHostMsg_NotifySignedOut::Read(message, &param);
+ request_id = param.a;
+ break;
+ }
+
+ case CredentialManagerHostMsg_RequestCredential::ID: {
+ Tuple3<int, bool, std::vector<GURL> > param;
+ CredentialManagerHostMsg_RequestCredential::Read(message, &param);
+ request_id = param.a;
+ break;
+ }
+
+ default:
+ break;
+ }
+ sink().ClearMessages();
+ return request_id != -1;
+ }
+
+ bool callback_errored() const { return callback_errored_; }
+ void set_callback_errored(bool state) { callback_errored_ = state; }
+ bool callback_succeeded() const { return callback_succeeded_; }
+ void set_callback_succeeded(bool state) { callback_succeeded_ = state; }
+
+ protected:
+ content::MockRenderThread render_thread_;
+ TestCredentialManagerClient client_;
+
+ // True if a message's callback's 'onSuccess'/'onError' methods were called,
+ // false otherwise. We put these on the test object rather than on the
+ // Test*Callbacks objects because ownership of those objects passes into the
+ // client, which destroys the callbacks after calling them to resolve the
+ // pending Blink-side Promise.
+ bool callback_errored_;
+ bool callback_succeeded_;
+};
+
+class TestNotificationCallbacks
+ : public blink::WebCredentialManagerClient::NotificationCallbacks {
+ public:
+ explicit TestNotificationCallbacks(CredentialManagerClientTest* test)
+ : test_(test) {
+ }
+
+ virtual ~TestNotificationCallbacks() {}
+
+ virtual void onSuccess() OVERRIDE { test_->set_callback_succeeded(true); }
+
+ virtual void onError(blink::WebCredentialManagerError* reason) OVERRIDE {
+ test_->set_callback_errored(true);
+ }
+
+ private:
+ CredentialManagerClientTest* test_;
+};
+
+class TestRequestCallbacks
+ : public blink::WebCredentialManagerClient::RequestCallbacks {
+ public:
+ explicit TestRequestCallbacks(CredentialManagerClientTest* test)
+ : test_(test) {
+ }
+
+ virtual ~TestRequestCallbacks() {}
+
+ virtual void onSuccess(blink::WebCredential*) OVERRIDE {
+ test_->set_callback_succeeded(true);
+ }
+
+ virtual void onError(blink::WebCredentialManagerError* reason) OVERRIDE {
+ test_->set_callback_errored(true);
+ }
+
+ private:
+ CredentialManagerClientTest* test_;
+};
+
+} // namespace
+
+TEST_F(CredentialManagerClientTest, SendNotifyFailedSignIn) {
+ int request_id;
+ EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_NotifyFailedSignIn::ID,
+ request_id));
+
+ blink::WebCredential credential(
+ "id", "user", GURL("https://example.com/img.png"));
+ scoped_ptr<TestNotificationCallbacks> callbacks(
+ new TestNotificationCallbacks(this));
+ client_.dispatchFailedSignIn(credential, callbacks.release());
+
+ EXPECT_TRUE(ExtractRequestId(CredentialManagerHostMsg_NotifyFailedSignIn::ID,
+ request_id));
+
+ client_.OnAcknowledgeFailedSignIn(request_id);
+ EXPECT_TRUE(callback_succeeded());
+ EXPECT_FALSE(callback_errored());
+}
+
+TEST_F(CredentialManagerClientTest, SendNotifySignedIn) {
+ int request_id;
+ EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_NotifySignedIn::ID,
+ request_id));
+
+ blink::WebCredential credential(
+ "id", "user", GURL("https://example.com/img.png"));
+ scoped_ptr<TestNotificationCallbacks> callbacks(
+ new TestNotificationCallbacks(this));
+ client_.dispatchSignedIn(credential, callbacks.release());
+
+ EXPECT_TRUE(ExtractRequestId(CredentialManagerHostMsg_NotifySignedIn::ID,
+ request_id));
+
+ client_.OnAcknowledgeSignedIn(request_id);
+ EXPECT_TRUE(callback_succeeded());
+ EXPECT_FALSE(callback_errored());
+}
+
+TEST_F(CredentialManagerClientTest, SendNotifySignedOut) {
+ int request_id;
+ EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_NotifySignedOut::ID,
+ request_id));
+
+ scoped_ptr<TestNotificationCallbacks> callbacks(
+ new TestNotificationCallbacks(this));
+ client_.dispatchSignedOut(callbacks.release());
+
+ EXPECT_TRUE(ExtractRequestId(CredentialManagerHostMsg_NotifySignedOut::ID,
+ request_id));
+
+ client_.OnAcknowledgeSignedOut(request_id);
+ EXPECT_TRUE(callback_succeeded());
+ EXPECT_FALSE(callback_errored());
+}
+
+TEST_F(CredentialManagerClientTest, SendRequestCredential) {
+ int request_id;
+ EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_RequestCredential::ID,
+ request_id));
+
+ scoped_ptr<TestRequestCallbacks> callbacks(new TestRequestCallbacks(this));
+ std::vector<GURL> federations;
+ client_.dispatchRequest(false, federations, callbacks.release());
+
+ EXPECT_TRUE(ExtractRequestId(CredentialManagerHostMsg_RequestCredential::ID,
+ request_id));
+
+ CredentialInfo info;
+ client_.OnSendCredential(request_id, info);
+ EXPECT_TRUE(callback_succeeded());
+ EXPECT_FALSE(callback_errored());
+}
+
+} // namespace password_manager
diff --git a/components/password_manager/content/renderer/test_credential_manager_client.cc b/components/password_manager/content/renderer/test_credential_manager_client.cc
new file mode 100644
index 0000000..96584db
--- /dev/null
+++ b/components/password_manager/content/renderer/test_credential_manager_client.cc
@@ -0,0 +1,20 @@
+// 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/test_credential_manager_client.h"
+
+namespace password_manager {
+
+TestCredentialManagerClient::TestCredentialManagerClient() {
+}
+
+TestCredentialManagerClient::~TestCredentialManagerClient() {
+}
+
+int TestCredentialManagerClient::GetRoutingID() {
+ // Chosen by fair dice roll.
+ return 4;
+}
+
+} // namespace password_manager
diff --git a/components/password_manager/content/renderer/test_credential_manager_client.h b/components/password_manager/content/renderer/test_credential_manager_client.h
new file mode 100644
index 0000000..17c1a89
--- /dev/null
+++ b/components/password_manager/content/renderer/test_credential_manager_client.h
@@ -0,0 +1,27 @@
+// 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.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CONTENT_RENDERER_TEST_CREDENTIAL_MANAGER_CLIENT_H_
+#define COMPONENTS_PASSWORD_MANAGER_CONTENT_RENDERER_TEST_CREDENTIAL_MANAGER_CLIENT_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "components/password_manager/content/renderer/credential_manager_client.h"
+
+namespace password_manager {
+
+class TestCredentialManagerClient : public CredentialManagerClient {
+ public:
+ TestCredentialManagerClient();
+ virtual ~TestCredentialManagerClient();
+
+ virtual int GetRoutingID() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestCredentialManagerClient);
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CONTENT_RENDERER_TEST_CREDENTIAL_MANAGER_CLIENT_H_
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index bcfcf7c..57f6dcc 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -106,6 +106,7 @@ enum IPCMessageStart {
OzoneGpuMsgStart,
ChromeUtilityExtensionsMsgStart,
PlatformNotificationMsgStart,
+ CredentialManagerMsgStart,
LastIPCMsgStart // Must come last.
};