summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriclelland <iclelland@chromium.org>2016-02-12 12:22:20 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-12 20:24:07 +0000
commit17b143af6e640744583640b405531b410569dd73 (patch)
tree786f367e854fee48ef918f5e7ff7a1072ee7200b
parentefa9ef721be99f95f420258e467ee44d46ce041d (diff)
downloadchromium_src-17b143af6e640744583640b405531b410569dd73.zip
chromium_src-17b143af6e640744583640b405531b410569dd73.tar.gz
chromium_src-17b143af6e640744583640b405531b410569dd73.tar.bz2
[Experimental Framework] Move the trial token public key out of content and into the embedder.
In order to make the code changes easier to reason about, this is now part 2 of a two-part commit. Part 1: https://codereview.chromium.org/1680873002/ BUG=543220 Review URL: https://codereview.chromium.org/1653263005 Cr-Commit-Position: refs/heads/master@{#375244}
-rw-r--r--chrome/chrome_renderer.gypi2
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc4
-rw-r--r--chrome/renderer/chrome_content_renderer_client.h4
-rw-r--r--chrome/renderer/origin_trials/origin_trial_key_manager.cc23
-rw-r--r--chrome/renderer/origin_trials/origin_trial_key_manager.h15
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/public/renderer/content_renderer_client.cc4
-rw-r--r--content/public/renderer/content_renderer_client.h4
-rw-r--r--content/renderer/origin_trials/trial_token.cc16
-rw-r--r--content/renderer/origin_trials/trial_token.h3
-rw-r--r--content/renderer/origin_trials/trial_token_unittest.cc48
-rw-r--r--content/renderer/origin_trials/trial_token_validator.cc17
-rw-r--r--content/renderer/origin_trials/trial_token_validator.h4
-rw-r--r--content/renderer/origin_trials/trial_token_validator_unittest.cc140
-rw-r--r--content/shell/renderer/shell_content_renderer_client.cc23
-rw-r--r--content/shell/renderer/shell_content_renderer_client.h2
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-enabled.html2
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-expired.html2
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-multiple-tokens.html6
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-stolen.html2
20 files changed, 286 insertions, 36 deletions
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index bef2b08..64299a9 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -33,6 +33,8 @@
'renderer/net/net_error_page_controller.h',
'renderer/net_benchmarking_extension.cc',
'renderer/net_benchmarking_extension.h',
+ 'renderer/origin_trials/origin_trial_key_manager.cc',
+ 'renderer/origin_trials/origin_trial_key_manager.h',
'renderer/page_load_histograms.cc',
'renderer/page_load_histograms.h',
'renderer/plugins/non_loadable_plugin_placeholder.cc',
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index d426b37..7d00445 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1416,3 +1416,7 @@ bool ChromeContentRendererClient::ShouldEnforceWebRTCRoutingPreferences() {
return true;
#endif
}
+
+base::StringPiece ChromeContentRendererClient::GetOriginTrialPublicKey() {
+ return origin_trial_key_manager_.GetPublicKey();
+}
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index b0bb7fb..58a702f 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -16,6 +16,7 @@
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
+#include "chrome/renderer/origin_trials/origin_trial_key_manager.h"
#include "content/public/renderer/content_renderer_client.h"
#include "ipc/ipc_channel_proxy.h"
#include "v8/include/v8.h"
@@ -156,6 +157,7 @@ class ChromeContentRendererClient : public content::ContentRendererClient {
v8::Local<v8::Context> context,
const GURL& url) override;
bool ShouldEnforceWebRTCRoutingPreferences() override;
+ base::StringPiece GetOriginTrialPublicKey() override;
#if defined(ENABLE_SPELLCHECK)
// Sets a new |spellcheck|. Used for testing only.
@@ -206,6 +208,8 @@ class ChromeContentRendererClient : public content::ContentRendererClient {
scoped_ptr<password_manager::CredentialManagerClient>
credential_manager_client_;
+ OriginTrialKeyManager origin_trial_key_manager_;
+
#if defined(ENABLE_SPELLCHECK)
scoped_ptr<SpellCheck> spellcheck_;
#endif
diff --git a/chrome/renderer/origin_trials/origin_trial_key_manager.cc b/chrome/renderer/origin_trials/origin_trial_key_manager.cc
new file mode 100644
index 0000000..e074f40
--- /dev/null
+++ b/chrome/renderer/origin_trials/origin_trial_key_manager.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2016 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 "chrome/renderer/origin_trials/origin_trial_key_manager.h"
+
+#include <stdint.h>
+
+// This is the default public key used for validating signatures.
+// TODO(iclelland): Provide a mechanism to allow for multiple signing keys.
+// https://crbug.com/584737
+// TODO(iclelland): Provide a mechanism to override, replace or disable this key
+// with field trials.
+static const uint8_t kPublicKey[] = {
+ 0x7c, 0xc4, 0xb8, 0x9a, 0x93, 0xba, 0x6e, 0xe2, 0xd0, 0xfd, 0x03,
+ 0x1d, 0xfb, 0x32, 0x66, 0xc7, 0x3b, 0x72, 0xfd, 0x54, 0x3a, 0x07,
+ 0x51, 0x14, 0x66, 0xaa, 0x02, 0x53, 0x4e, 0x33, 0xa1, 0x15,
+};
+
+base::StringPiece OriginTrialKeyManager::GetPublicKey() {
+ return base::StringPiece(reinterpret_cast<const char*>(kPublicKey),
+ arraysize(kPublicKey));
+}
diff --git a/chrome/renderer/origin_trials/origin_trial_key_manager.h b/chrome/renderer/origin_trials/origin_trial_key_manager.h
new file mode 100644
index 0000000..18b01d8
--- /dev/null
+++ b/chrome/renderer/origin_trials/origin_trial_key_manager.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2016 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 CHROME_RENDERER_ORIGIN_TRIALS_ORIGIN_TRIAL_KEY_MANAGER_H_
+#define CHROME_RENDERER_ORIGIN_TRIALS_ORIGIN_TRIAL_KEY_MANAGER_H_
+
+#include "base/strings/string_piece.h"
+
+class OriginTrialKeyManager {
+ public:
+ base::StringPiece GetPublicKey();
+};
+
+#endif // CHROME_RENDERER_ORIGIN_TRIALS_ORIGIN_TRIAL_KEY_MANAGER_H_
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 7452662..71f602b 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -718,6 +718,7 @@
'renderer/media/video_capture_message_filter_unittest.cc',
'renderer/media/webmediaplayer_ms_unittest.cc',
'renderer/origin_trials/trial_token_unittest.cc',
+ 'renderer/origin_trials/trial_token_validator_unittest.cc',
'renderer/peripheral_content_heuristic_unittest.cc',
'renderer/raster_worker_pool_unittest.cc',
'renderer/render_thread_impl_unittest.cc',
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index d32eccc..f928d33 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -225,4 +225,8 @@ bool ContentRendererClient::ShouldEnforceWebRTCRoutingPreferences() {
return true;
}
+base::StringPiece ContentRendererClient::GetOriginTrialPublicKey() {
+ return base::StringPiece();
+}
+
} // namespace content
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index 880550c..52b397f 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -327,6 +327,10 @@ class CONTENT_EXPORT ContentRendererClient {
// Whether this renderer should enforce preferences related to the WebRTC
// routing logic, i.e. allowing multiple routes and non-proxied UDP.
virtual bool ShouldEnforceWebRTCRoutingPreferences();
+
+ // Returns the public key to be used for origin trials, or an empty string if
+ // origin trials are not enabled in this context.
+ virtual base::StringPiece GetOriginTrialPublicKey();
};
} // namespace content
diff --git a/content/renderer/origin_trials/trial_token.cc b/content/renderer/origin_trials/trial_token.cc
index 46624b6..5cf69ac 100644
--- a/content/renderer/origin_trials/trial_token.cc
+++ b/content/renderer/origin_trials/trial_token.cc
@@ -24,15 +24,6 @@ namespace {
// Version 1 is the only token version currently supported
const uint8_t kVersion1 = 1;
-// This is the default public key used for validating signatures.
-// TODO(iclelland): Move this to the embedder, and provide a mechanism to allow
-// for multiple signing keys. https://crbug.com/543220
-static const uint8_t kPublicKey[] = {
- 0x7c, 0xc4, 0xb8, 0x9a, 0x93, 0xba, 0x6e, 0xe2, 0xd0, 0xfd, 0x03,
- 0x1d, 0xfb, 0x32, 0x66, 0xc7, 0x3b, 0x72, 0xfd, 0x54, 0x3a, 0x07,
- 0x51, 0x14, 0x66, 0xaa, 0x02, 0x53, 0x4e, 0x33, 0xa1, 0x15,
-};
-
const char* kFieldSeparator = "|";
} // namespace
@@ -116,12 +107,11 @@ bool TrialToken::IsAppropriate(const std::string& origin,
return ValidateOrigin(origin) && ValidateFeatureName(feature_name);
}
-bool TrialToken::IsValid(const base::Time& now) const {
+bool TrialToken::IsValid(const base::Time& now,
+ const base::StringPiece& public_key) const {
// TODO(iclelland): Allow for multiple signing keys, and iterate over all
// active keys here. https://crbug.com/543220
- return ValidateDate(now) &&
- ValidateSignature(base::StringPiece(
- reinterpret_cast<const char*>(kPublicKey), arraysize(kPublicKey)));
+ return ValidateDate(now) && ValidateSignature(public_key);
}
bool TrialToken::ValidateOrigin(const std::string& origin) const {
diff --git a/content/renderer/origin_trials/trial_token.h b/content/renderer/origin_trials/trial_token.h
index c133bbb..7ad75df 100644
--- a/content/renderer/origin_trials/trial_token.h
+++ b/content/renderer/origin_trials/trial_token.h
@@ -44,7 +44,8 @@ class CONTENT_EXPORT TrialToken {
const std::string& featureName) const;
// Returns true if this token has a valid signature, and has not expired.
- bool IsValid(const base::Time& now) const;
+ bool IsValid(const base::Time& now,
+ const base::StringPiece& public_key) const;
uint8_t version() { return version_; }
std::string signature() { return signature_; }
diff --git a/content/renderer/origin_trials/trial_token_unittest.cc b/content/renderer/origin_trials/trial_token_unittest.cc
index 2a19db7..2552152 100644
--- a/content/renderer/origin_trials/trial_token_unittest.cc
+++ b/content/renderer/origin_trials/trial_token_unittest.cc
@@ -6,6 +6,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
@@ -30,6 +31,21 @@ const uint8_t kTestPublicKey[] = {
0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
};
+// This is a valid, but incorrect, public key for testing signatures against.
+// The corresponding private key is:
+//
+// 0x21, 0xee, 0xfa, 0x81, 0x6a, 0xff, 0xdf, 0xb8, 0xc1, 0xdd, 0x75,
+// 0x05, 0x04, 0x29, 0x68, 0x67, 0x60, 0x85, 0x91, 0xd0, 0x50, 0x16,
+// 0x0a, 0xcf, 0xa2, 0x37, 0xa3, 0x2e, 0x11, 0x7a, 0x17, 0x96, 0x50,
+// 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c, 0x47,
+// 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51, 0x3e,
+// 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca
+const uint8_t kTestPublicKey2[] = {
+ 0x50, 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c,
+ 0x47, 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51,
+ 0x3e, 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca,
+};
+
// This is a good trial token, signed with the above test private key.
const char* kSampleToken =
"1|UsEO0cNxoUtBnHDJdGPWTlXuLENjXcEIPL7Bs7sbvicPCcvAtyqhQuTJ9h/u1R3VZpWigtI+"
@@ -97,9 +113,12 @@ const size_t kNumInvalidTokens = arraysize(kInvalidTokens);
class TrialTokenTest : public testing::Test {
public:
TrialTokenTest()
- : public_key_(
+ : correct_public_key_(
base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey),
- arraysize(kTestPublicKey))) {}
+ arraysize(kTestPublicKey))),
+ incorrect_public_key_(
+ base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey2),
+ arraysize(kTestPublicKey2))) {}
protected:
bool ValidateOrigin(TrialToken* token, const char* origin) {
@@ -119,10 +138,14 @@ class TrialTokenTest : public testing::Test {
return token->ValidateSignature(public_key);
}
- const base::StringPiece& public_key() { return public_key_; };
+ const base::StringPiece& correct_public_key() { return correct_public_key_; }
+ const base::StringPiece& incorrect_public_key() {
+ return incorrect_public_key_;
+ }
private:
- base::StringPiece public_key_;
+ base::StringPiece correct_public_key_;
+ base::StringPiece incorrect_public_key_;
};
TEST_F(TrialTokenTest, ParseEmptyString) {
@@ -183,20 +206,27 @@ TEST_F(TrialTokenTest, TokenIsAppropriateForOriginAndFeature) {
TEST_F(TrialTokenTest, ValidateValidSignature) {
scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
ASSERT_TRUE(token);
- EXPECT_TRUE(ValidateSignature(token.get(), public_key()));
+ EXPECT_TRUE(ValidateSignature(token.get(), correct_public_key()));
}
TEST_F(TrialTokenTest, ValidateInvalidSignature) {
scoped_ptr<TrialToken> token = TrialToken::Parse(kInvalidSignatureToken);
ASSERT_TRUE(token);
- EXPECT_FALSE(ValidateSignature(token.get(), public_key()));
+ EXPECT_FALSE(ValidateSignature(token.get(), correct_public_key()));
+}
+
+TEST_F(TrialTokenTest, ValidateTokenWithCorrectKey) {
+ scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
+ ASSERT_TRUE(token);
+ EXPECT_TRUE(token->IsValid(base::Time::FromDoubleT(kValidTimestamp),
+ correct_public_key()));
}
-TEST_F(TrialTokenTest, ValidateSignatureOnWrongKey) {
+TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectKey) {
scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
ASSERT_TRUE(token);
- // Signature will be invalid if tested against the real public key
- EXPECT_FALSE(token->IsValid(base::Time::FromDoubleT(kValidTimestamp)));
+ EXPECT_FALSE(token->IsValid(base::Time::FromDoubleT(kValidTimestamp),
+ incorrect_public_key()));
}
TEST_F(TrialTokenTest, ValidateWhenNotExpired) {
diff --git a/content/renderer/origin_trials/trial_token_validator.cc b/content/renderer/origin_trials/trial_token_validator.cc
index bbdd857..1df8dc78 100644
--- a/content/renderer/origin_trials/trial_token_validator.cc
+++ b/content/renderer/origin_trials/trial_token_validator.cc
@@ -5,6 +5,8 @@
#include "content/renderer/origin_trials/trial_token_validator.h"
#include "base/time/time.h"
+#include "content/public/common/content_client.h"
+#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/origin_trials/trial_token.h"
namespace content {
@@ -15,10 +17,17 @@ TrialTokenValidator::~TrialTokenValidator() {}
bool TrialTokenValidator::validateToken(const blink::WebString& token,
const blink::WebString& origin,
const blink::WebString& featureName) {
- scoped_ptr<TrialToken> trialToken = TrialToken::Parse(token.utf8());
- return trialToken &&
- trialToken->IsAppropriate(origin.utf8(), featureName.utf8()) &&
- trialToken->IsValid(base::Time::Now());
+ scoped_ptr<TrialToken> trial_token = TrialToken::Parse(token.utf8());
+
+ ContentClient* content_client = GetContentClient();
+ CHECK(content_client);
+
+ base::StringPiece public_key =
+ content_client->renderer()->GetOriginTrialPublicKey();
+
+ return !public_key.empty() && trial_token &&
+ trial_token->IsAppropriate(origin.utf8(), featureName.utf8()) &&
+ trial_token->IsValid(base::Time::Now(), public_key);
}
} // namespace content
diff --git a/content/renderer/origin_trials/trial_token_validator.h b/content/renderer/origin_trials/trial_token_validator.h
index 6afd01b..a0ce6c2 100644
--- a/content/renderer/origin_trials/trial_token_validator.h
+++ b/content/renderer/origin_trials/trial_token_validator.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_ORIGIN_TRIALS_TRIAL_TOKEN_VALIDATOR_H_
#include <string>
+#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebTrialTokenValidator.h"
namespace content {
@@ -14,7 +15,8 @@ namespace content {
// to validate tokens to enable experimental features.
//
// This class is thread-safe.
-class TrialTokenValidator : public blink::WebTrialTokenValidator {
+class CONTENT_EXPORT TrialTokenValidator
+ : public NON_EXPORTED_BASE(blink::WebTrialTokenValidator) {
public:
TrialTokenValidator();
~TrialTokenValidator() override;
diff --git a/content/renderer/origin_trials/trial_token_validator_unittest.cc b/content/renderer/origin_trials/trial_token_validator_unittest.cc
new file mode 100644
index 0000000..2bdb8883
--- /dev/null
+++ b/content/renderer/origin_trials/trial_token_validator_unittest.cc
@@ -0,0 +1,140 @@
+// Copyright 2016 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 "content/renderer/origin_trials/trial_token_validator.h"
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_util.h"
+#include "base/test/simple_test_clock.h"
+#include "base/time/time.h"
+#include "content/public/renderer/content_renderer_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+// This is a sample public key for testing the API. The corresponding private
+// key (use this to generate new samples for this test file) is:
+//
+// 0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13,
+// 0x4c, 0x67, 0xc4, 0xf4, 0x28, 0xc9, 0x90, 0x15, 0x02, 0xe2, 0xba,
+// 0xfd, 0xbb, 0xfa, 0xbc, 0x92, 0x76, 0x8a, 0x2c, 0x4b, 0xc7, 0x75,
+// 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2, 0x9a,
+// 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f, 0x64,
+// 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0
+const uint8_t kTestPublicKey[] = {
+ 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
+ 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
+ 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
+};
+
+// 0x21, 0xee, 0xfa, 0x81, 0x6a, 0xff, 0xdf, 0xb8, 0xc1, 0xdd, 0x75,
+// 0x05, 0x04, 0x29, 0x68, 0x67, 0x60, 0x85, 0x91, 0xd0, 0x50, 0x16,
+// 0x0a, 0xcf, 0xa2, 0x37, 0xa3, 0x2e, 0x11, 0x7a, 0x17, 0x96, 0x50,
+// 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c, 0x47,
+// 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51, 0x3e,
+// 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca
+const uint8_t kTestPublicKey2[] = {
+ 0x50, 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c,
+ 0x47, 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51,
+ 0x3e, 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca,
+};
+
+// This is a good trial token, signed with the above test private key.
+// TODO(iclelland): This token expires in 2033. Update it or find a way
+// to autogenerate it before then.
+const char kSampleToken[] =
+ "1|w694328Rl8l2vd96nkbAumpwvOOnvhWTj9/pfBRkvcWMDAsmiMEhZGEPzdBRy5Yao6il5qC"
+ "OyS6Ah7uuHf7JAQ==|https://valid.example.com|Frobulate|2000000000";
+
+// The token should be valid for this origin and for this feature.
+const char kAppropriateOrigin[] = "https://valid.example.com";
+const char kAppropriateFeatureName[] = "Frobulate";
+
+const char kInappropriateFeatureName[] = "Grokalyze";
+const char kInappropriateOrigin[] = "https://invalid.example.com";
+const char kInsecureOrigin[] = "http://valid.example.com";
+
+// Well-formed trial token with an invalid signature.
+const char kInvalidSignatureToken[] =
+ "1|CO8hDne98QeFeOJ0DbRZCBN3uE0nyaPgaLlkYhSWnbRoDfEAg+TXELaYfQPfEvKYFauBg/h"
+ "nxmba765hz0mXMc==|https://valid.example.com|Frobulate|2000000000";
+
+// Well-formed, but expired, trial token. (Expired in 2001)
+const char kExpiredToken[] =
+ "1|Vtzq/H0qMxsMXPThIgGEvI13d3Fd8K3W11/0E+FrJJXqBpx6n/dFkeFkEUsPaP3KeT8PCPF"
+ "1zpZ7kVgWYRLpAA==|https://valid.example.com|Frobulate|1000000000";
+
+const char kUnparsableToken[] = "abcde";
+
+class TestContentRendererClient : public content::ContentRendererClient {
+ public:
+ base::StringPiece GetOriginTrialPublicKey() override {
+ return base::StringPiece(reinterpret_cast<const char*>(key_),
+ arraysize(kTestPublicKey));
+ }
+ void SetOriginTrialPublicKey(const uint8_t* key) { key_ = key; }
+ const uint8_t* key_ = nullptr;
+};
+
+} // namespace
+
+class TrialTokenValidatorTest : public testing::Test {
+ public:
+ TrialTokenValidatorTest() {
+ SetPublicKey(kTestPublicKey);
+ SetRendererClientForTesting(&test_content_renderer_client_);
+ }
+
+ void SetPublicKey(const uint8_t* key) {
+ test_content_renderer_client_.SetOriginTrialPublicKey(key);
+ }
+
+ TrialTokenValidator trial_token_validator_;
+
+ private:
+ TestContentRendererClient test_content_renderer_client_;
+};
+
+TEST_F(TrialTokenValidatorTest, ValidateValidToken) {
+ EXPECT_TRUE(trial_token_validator_.validateToken(
+ kSampleToken, kAppropriateOrigin, kAppropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateInappropriateOrigin) {
+ EXPECT_FALSE(TrialTokenValidator().validateToken(
+ kSampleToken, kInappropriateOrigin, kAppropriateFeatureName));
+ EXPECT_FALSE(TrialTokenValidator().validateToken(
+ kSampleToken, kInsecureOrigin, kAppropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateInappropriateFeature) {
+ EXPECT_FALSE(TrialTokenValidator().validateToken(
+ kSampleToken, kAppropriateOrigin, kInappropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateInvalidSignature) {
+ EXPECT_FALSE(TrialTokenValidator().validateToken(
+ kInvalidSignatureToken, kAppropriateOrigin, kAppropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateUnparsableToken) {
+ EXPECT_FALSE(TrialTokenValidator().validateToken(
+ kUnparsableToken, kAppropriateOrigin, kAppropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateExpiredToken) {
+ EXPECT_FALSE(TrialTokenValidator().validateToken(
+ kExpiredToken, kAppropriateOrigin, kAppropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateValidTokenWithIncorrectKey) {
+ SetPublicKey(kTestPublicKey2);
+ EXPECT_FALSE(TrialTokenValidator().validateToken(
+ kSampleToken, kAppropriateOrigin, kAppropriateFeatureName));
+}
+
+} // namespace content
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc
index 99badd7..1d12609 100644
--- a/content/shell/renderer/shell_content_renderer_client.cc
+++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -17,8 +17,23 @@
namespace content {
-ShellContentRendererClient::ShellContentRendererClient() {
-}
+namespace {
+
+// This is the public key which the content shell will use to enable origin
+// trial features.
+// TODO(iclelland): Update this comment with the location of the public and
+// private key files when the command-line tool CL lands
+static const uint8_t kOriginTrialPublicKey[] = {
+ 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
+ 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
+ 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
+};
+} // namespace
+
+ShellContentRendererClient::ShellContentRendererClient()
+ : origin_trial_public_key_(base::StringPiece(
+ reinterpret_cast<const char*>(kOriginTrialPublicKey),
+ arraysize(kOriginTrialPublicKey))) {}
ShellContentRendererClient::~ShellContentRendererClient() {
}
@@ -52,4 +67,8 @@ bool ShellContentRendererClient::IsPluginAllowedToUseDevChannelAPIs() {
#endif
}
+base::StringPiece ShellContentRendererClient::GetOriginTrialPublicKey() {
+ return origin_trial_public_key_;
+}
+
} // namespace content
diff --git a/content/shell/renderer/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h
index 6c4e295..23d71a8 100644
--- a/content/shell/renderer/shell_content_renderer_client.h
+++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -28,9 +28,11 @@ class ShellContentRendererClient : public ContentRendererClient {
// need that outside of layout tests?
bool IsPluginAllowedToUseCompositorAPI(const GURL& url) override;
bool IsPluginAllowedToUseDevChannelAPIs() override;
+ base::StringPiece GetOriginTrialPublicKey() override;
private:
scoped_ptr<web_cache::WebCacheRenderProcessObserver> web_cache_observer_;
+ base::StringPiece origin_trial_public_key_;
};
} // namespace content
diff --git a/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-enabled.html b/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-enabled.html
index a6a1403..378bb86 100644
--- a/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-enabled.html
+++ b/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-enabled.html
@@ -3,7 +3,7 @@
<!-- TODO(iclelland): Generate this sample token during the build. The token
below will expire in 2033, but it would be better to always have a token which
is guaranteed to be valid when the tests are run. -->
-<meta name="origin-trials" content="1|vwg3nKe6n5/EXh83rDzj1/AOL/FkpXP8CMC53/kjWcOH1smcZuzp431/5bEf39ZPOh6P2sjKsl/LPL7nIoycAg==|http://127.0.0.1:8000|Frobulate|2000000000">
+<meta name="origin-trials" content="1|tZPW/JJ2Sxm4z7k/Eb1/upMsppozWpTwEuGwhgQko0zWS6ebvjQ+EXPP/ftoMX8/PCoDgOS3xlrXElMgDDvbCg==|http://127.0.0.1:8000|Frobulate|2000000000">
<title>Test Sample API when trial is enabled</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharness-helpers.js"></script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-expired.html b/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-expired.html
index 6bddd42..973cef5 100644
--- a/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-expired.html
+++ b/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-expired.html
@@ -4,7 +4,7 @@
below has a valid signature for the current signing key, but it would be
better to always have a token which is guaranteed to be valid when the tests
are run. -->
-<meta name="origin-trials" content="1|ktI/SoAgEf1rzplbPPeG44jQv/t4eVFkBq6K22TBP++y3rQurg/RL5iuisXrTlBimad9rlKqOn9MgQKj+O4MDw==|http://127.0.0.1:8000|Frobulate|1000000000" />
+<meta name="origin-trials" content="1|W5OpLTgzFacJn++BqWVqbeyfxdbimq4hqMg65lHYlmod6ZB2Jl5pfNWlHtRJBOl88/paQB5wqWq5e3z870tfCw==|http://127.0.0.1:8000|Frobulate|1000000000" />
<title>Test Sample API when trial has expired</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharness-helpers.js"></script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-multiple-tokens.html b/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-multiple-tokens.html
index c1142e3..fbf9d24 100644
--- a/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-multiple-tokens.html
+++ b/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-multiple-tokens.html
@@ -3,9 +3,9 @@
<!-- TODO(iclelland): Generate these sample tokens during the build. The tokens
below will expire in 2033, but it would be better to always have tokens which
are guaranteed to be valid when the tests are run. -->
-<meta name="origin-trials" content="1|0Z9yc32TDc+Jmn5LbxRS9b4AcU5mBdJR3SG42cfiq84ferbaogVMNqJnyQHAFJ1cbe4gywThVX4w+ZYcktfIBA==|http://127.0.0.1:8000|Grokalyze|2000000000" />
-<meta name="origin-trials" content="1|vwg3nKe6n5/EXh83rDzj1/AOL/FkpXP8CMC53/kjWcOH1smcZuzp431/5bEf39ZPOh6P2sjKsl/LPL7nIoycAg==|http://127.0.0.1:8000|Frobulate|2000000000" />
-<meta name="origin-trials" content="1|CVmciymFpxQj8T1ywqJLpNAIUqVLKMmeMSvYqL27XsJZhwFGS3Dl3igRUnzE5GByOUe0fIrcyVDLA7n8KovqAw==|http://127.0.0.1:8000|EnableMarqueeTag|2000000000" />
+<meta name="origin-trials" content="1|umr41cAPVTw49gYvZb5zQc+lIy6ixCQkC/QyuDBkDNnAbZQjXe7YM/Pb8d0nHCY7xhRq37ZGP7DhLSCp0aOeDA==|http://127.0.0.1:8000|Grokalyze|2000000000" />
+<meta name="origin-trials" content="1|tZPW/JJ2Sxm4z7k/Eb1/upMsppozWpTwEuGwhgQko0zWS6ebvjQ+EXPP/ftoMX8/PCoDgOS3xlrXElMgDDvbCg==|http://127.0.0.1:8000|Frobulate|2000000000" />
+<meta name="origin-trials" content="1|Z+D6g2JZrstb1O6ztVoTi6bWXYGFCdd9v2lu23Doj2RP+q9gHZqhs7RUp1vfUQ0IVt0p5jzVX/OOrwenvktyBA==|http://127.0.0.1:8000|EnableMarqueeTag|2000000000" />
<title>Test Sample API when trial is enabled and multiple tokens are present</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharness-helpers.js"></script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-stolen.html b/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-stolen.html
index 5ed31fe..4a30de8 100644
--- a/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-stolen.html
+++ b/third_party/WebKit/LayoutTests/http/tests/origin_trials/sample-api-stolen.html
@@ -3,7 +3,7 @@
<!-- TODO(iclelland): Generate this sample token during the build. The token
below will expire in 2033, but it would be better to always have a token which
is guaranteed to be valid when the tests are run. -->
-<meta name="origin-trials" content="1|1Rw1j+NkMF27TxRhpNJ5R28nLpbXwDjPKcKdLhTVFNoR5naMmIbYQgnFLPgQSRceq5KSgKb584zRWx2tacTkBw==|http://invalid.example.com|Frobulate|2000000000" />
+<meta name="origin-trials" content="1|ak4CUgJ69tforMyzN7lgxhWaaIny/lGqtLjIqJjMXBA2b8lqul1KhyyLmKZ38+tJnZDLXZmQUn5ZjMFE/SmNDw==|https://invalid.example.com|Frobulate|2000000000" />
<title>Test Sample API when token is present for a different origin</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharness-helpers.js"></script>