summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--third_party/WebKit/Source/build/scripts/templates/OriginTrials.cpp.tmpl38
-rw-r--r--third_party/WebKit/Source/build/scripts/templates/OriginTrials.h.tmpl19
-rw-r--r--third_party/WebKit/Source/core/core.gypi3
-rw-r--r--third_party/WebKit/Source/core/dom/Document.cpp6
-rw-r--r--third_party/WebKit/Source/core/dom/Document.h4
-rw-r--r--third_party/WebKit/Source/core/dom/ExecutionContext.cpp6
-rw-r--r--third_party/WebKit/Source/core/dom/ExecutionContext.h4
-rw-r--r--third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContext.cpp41
-rw-r--r--third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContext.h41
-rw-r--r--third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContextTest.cpp117
-rw-r--r--third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp78
-rw-r--r--third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h33
-rw-r--r--third_party/WebKit/Source/core/origin_trials/OriginTrialContextTest.cpp114
-rw-r--r--third_party/WebKit/Source/core/testing/NullExecutionContext.cpp10
-rw-r--r--third_party/WebKit/Source/core/testing/NullExecutionContext.h2
15 files changed, 403 insertions, 113 deletions
diff --git a/third_party/WebKit/Source/build/scripts/templates/OriginTrials.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/OriginTrials.cpp.tmpl
index 37c26020..c95d7fb 100644
--- a/third_party/WebKit/Source/build/scripts/templates/OriginTrials.cpp.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/OriginTrials.cpp.tmpl
@@ -3,35 +3,63 @@
#include "core/origin_trials/OriginTrials.h"
+#include "core/dom/ExecutionContext.h"
#include "core/origin_trials/OriginTrialContext.h"
#include "platform/RuntimeEnabledFeatures.h"
namespace blink {
+
+OriginTrials::OriginTrials(PassOwnPtrWillBeRawPtr<OriginTrialContext> originTrialContext)
+ : m_originTrialContext(originTrialContext) {}
+
+// static
+const char* OriginTrials::supplementName()
+{
+ return "OriginTrials";
+}
+
+// static
+OriginTrials* OriginTrials::from(ExecutionContext* host)
+{
+ OriginTrials* originTrials = reinterpret_cast<OriginTrials*>(WillBeHeapSupplement<ExecutionContext>::from(host, supplementName()));
+ if (!originTrials) {
+ originTrials = new OriginTrials(host->createOriginTrialContext());
+ WillBeHeapSupplement<ExecutionContext>::provideTo(*host, supplementName(), adoptPtrWillBeNoop(originTrials));
+ }
+ return originTrials;
+}
+
{% for feature in features %}
{% if feature.origin_trial_feature_name %}
// static
bool OriginTrials::{{feature.first_lowered_name}}Enabled(ExecutionContext* executionContext, String& errorMessage) {
- return {{feature.first_lowered_name}}EnabledImpl(executionContext, &errorMessage);
+ return OriginTrials::from(executionContext)->{{feature.first_lowered_name}}EnabledImpl(&errorMessage);
}
// static
bool OriginTrials::{{feature.first_lowered_name}}Enabled(ExecutionContext* executionContext) {
- return {{feature.first_lowered_name}}EnabledImpl(executionContext, nullptr);
+ return OriginTrials::from(executionContext)->{{feature.first_lowered_name}}EnabledImpl(nullptr);
}
+
{% endif %}
{% endfor %}
{% for feature in features %}
{% if feature.origin_trial_feature_name %}
-// static
-bool OriginTrials::{{feature.first_lowered_name}}EnabledImpl(ExecutionContext* executionContext, String* errorMessage) {
+bool OriginTrials::{{feature.first_lowered_name}}EnabledImpl(String* errorMessage) {
if (RuntimeEnabledFeatures::{{feature.first_lowered_name}}Enabled())
return true;
- return OriginTrialContext::isFeatureEnabled(executionContext, "{{feature.origin_trial_feature_name}}", errorMessage);
+ if (!m_originTrialContext) return false;
+ return m_originTrialContext->isFeatureEnabled("{{feature.origin_trial_feature_name}}", errorMessage);
}
{% endif %}
{% endfor %}
+DEFINE_TRACE(OriginTrials)
+{
+ visitor->trace(m_originTrialContext);
+ WillBeHeapSupplement<ExecutionContext>::trace(visitor);
+}
} // namespace blink
diff --git a/third_party/WebKit/Source/build/scripts/templates/OriginTrials.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/OriginTrials.h.tmpl
index f49790e..d7f4d54 100644
--- a/third_party/WebKit/Source/build/scripts/templates/OriginTrials.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/OriginTrials.h.tmpl
@@ -5,32 +5,43 @@
#define OriginTrials_h
#include "core/CoreExport.h"
+#include "platform/Supplementable.h"
#include "wtf/text/WTFString.h"
namespace blink {
class ExecutionContext;
+class OriginTrialContext;
// A class that stores dynamic tests for experimental features which can be
// enabled through the experimental framework via API keys.
-class CORE_EXPORT OriginTrials {
+class CORE_EXPORT OriginTrials final : public NoBaseWillBeGarbageCollected<OriginTrials>, public WillBeHeapSupplement<ExecutionContext> {
+WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(OriginTrials)
public:
+ OriginTrials(PassOwnPtrWillBeRawPtr<OriginTrialContext>);
+
+ static const char* supplementName();
+ static OriginTrials* from(ExecutionContext*);
+
{% for feature in features %}
{% if feature.origin_trial_feature_name %}
+
static bool {{feature.first_lowered_name}}Enabled(ExecutionContext* executionContext, String& errorMessage);
static bool {{feature.first_lowered_name}}Enabled(ExecutionContext* executionContext);
{% endif %}
{% endfor %}
-private:
- OriginTrials() { }
+ DECLARE_TRACE();
+private:
{% for feature in features %}
{% if feature.origin_trial_feature_name %}
- static bool {{feature.first_lowered_name}}EnabledImpl(ExecutionContext* executionContext, String* errorMessage);
+ bool {{feature.first_lowered_name}}EnabledImpl(String* errorMessage);
{% endif %}
{% endfor %}
+
+ OwnPtrWillBeMember<OriginTrialContext> m_originTrialContext;
};
} // namespace blink
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi
index 64ac28d..244fcab 100644
--- a/third_party/WebKit/Source/core/core.gypi
+++ b/third_party/WebKit/Source/core/core.gypi
@@ -1917,6 +1917,8 @@
'loader/appcache/ApplicationCache.h',
'loader/appcache/ApplicationCacheHost.cpp',
'loader/appcache/ApplicationCacheHost.h',
+ 'origin_trials/DocumentOriginTrialContext.cpp',
+ 'origin_trials/DocumentOriginTrialContext.h',
'origin_trials/OriginTrialContext.cpp',
'origin_trials/OriginTrialContext.h',
'page/AutoscrollController.cpp',
@@ -4031,6 +4033,7 @@
'loader/LinkHeaderTest.cpp',
'loader/LinkLoaderTest.cpp',
'loader/MixedContentCheckerTest.cpp',
+ 'origin_trials/DocumentOriginTrialContextTest.cpp',
'origin_trials/OriginTrialContextTest.cpp',
'page/ChromeClientTest.cpp',
'page/ContextMenuControllerTest.cpp',
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 93a13ab..a24e8423 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -184,6 +184,7 @@
#include "core/loader/ImageLoader.h"
#include "core/loader/NavigationScheduler.h"
#include "core/loader/appcache/ApplicationCacheHost.h"
+#include "core/origin_trials/DocumentOriginTrialContext.h"
#include "core/page/ChromeClient.h"
#include "core/page/EventWithHitTestResults.h"
#include "core/page/FocusController.h"
@@ -5916,6 +5917,11 @@ void Document::enforceStrictMixedContentChecking()
frame()->loader().client()->didEnforceStrictMixedContentChecking();
}
+PassOwnPtrWillBeRawPtr<OriginTrialContext> Document::createOriginTrialContext()
+{
+ return adoptPtrWillBeNoop(new DocumentOriginTrialContext(this));
+}
+
DEFINE_TRACE(Document)
{
#if ENABLE(OILPAN)
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 3088fc8..c13baa7 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -140,6 +140,7 @@ class NodeIntersectionObserverData;
class NodeIterator;
class NthIndexCache;
class OriginAccessEntry;
+class OriginTrialContext;
class Page;
class PlatformMouseEvent;
class ProcessingInstruction;
@@ -1079,6 +1080,7 @@ protected:
ParserSynchronizationPolicy getParserSynchronizationPolicy() const { return m_parserSyncPolicy; }
private:
+ friend class DocumentOriginTrialContextTest;
friend class IgnoreDestructiveWriteCountIncrementer;
friend class NthIndexCache;
@@ -1162,6 +1164,8 @@ private:
const OriginAccessEntry& accessEntryFromURL();
+ PassOwnPtrWillBeRawPtr<OriginTrialContext> createOriginTrialContext() override;
+
DocumentLifecycle m_lifecycle;
bool m_hasNodesWithPlaceholderStyle;
diff --git a/third_party/WebKit/Source/core/dom/ExecutionContext.cpp b/third_party/WebKit/Source/core/dom/ExecutionContext.cpp
index bb89d5a..bda769b 100644
--- a/third_party/WebKit/Source/core/dom/ExecutionContext.cpp
+++ b/third_party/WebKit/Source/core/dom/ExecutionContext.cpp
@@ -36,6 +36,7 @@
#include "core/frame/UseCounter.h"
#include "core/html/PublicURLManager.h"
#include "core/inspector/InspectorInstrumentation.h"
+#include "core/origin_trials/OriginTrialContext.h"
#include "core/workers/WorkerGlobalScope.h"
#include "core/workers/WorkerThread.h"
#include "wtf/MainThread.h"
@@ -265,6 +266,11 @@ void ExecutionContext::setReferrerPolicy(ReferrerPolicy referrerPolicy)
m_referrerPolicy = referrerPolicy;
}
+PassOwnPtrWillBeRawPtr<OriginTrialContext> ExecutionContext::createOriginTrialContext()
+{
+ return nullptr;
+}
+
void ExecutionContext::removeURLFromMemoryCache(const KURL& url)
{
memoryCache()->removeURLFromCache(url);
diff --git a/third_party/WebKit/Source/core/dom/ExecutionContext.h b/third_party/WebKit/Source/core/dom/ExecutionContext.h
index 8bb226b..e5e67bc 100644
--- a/third_party/WebKit/Source/core/dom/ExecutionContext.h
+++ b/third_party/WebKit/Source/core/dom/ExecutionContext.h
@@ -53,6 +53,7 @@ class EventQueue;
class EventTarget;
class ExecutionContextTask;
class LocalDOMWindow;
+class OriginTrialContext;
class PublicURLManager;
class SecurityOrigin;
class ScriptCallStack;
@@ -155,6 +156,9 @@ public:
virtual void setReferrerPolicy(ReferrerPolicy);
ReferrerPolicy getReferrerPolicy() const { return m_referrerPolicy; }
+ // Override to enable experimental features through origin trials
+ virtual PassOwnPtrWillBeRawPtr<OriginTrialContext> createOriginTrialContext();
+
protected:
ExecutionContext();
virtual ~ExecutionContext();
diff --git a/third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContext.cpp b/third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContext.cpp
new file mode 100644
index 0000000..f43bceb
--- /dev/null
+++ b/third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContext.cpp
@@ -0,0 +1,41 @@
+// Copyright 2015 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 "core/origin_trials/DocumentOriginTrialContext.h"
+
+#include "core/dom/ElementTraversal.h"
+#include "core/html/HTMLHeadElement.h"
+#include "core/html/HTMLMetaElement.h"
+
+namespace blink {
+
+class Document;
+
+DocumentOriginTrialContext::DocumentOriginTrialContext(Document* document)
+ : m_parent(document)
+{
+}
+
+Vector<String> DocumentOriginTrialContext::getTokens()
+{
+ // When in a document, the tokens are provided in a meta tag
+ Vector<String> tokens;
+ HTMLHeadElement* head = m_parent->head();
+ if (head) {
+ for (HTMLMetaElement& metaElement : Traversal<HTMLMetaElement>::childrenOf(*head)) {
+ if (equalIgnoringCase(metaElement.httpEquiv(), kTrialHeaderName)) {
+ tokens.append(metaElement.content());
+ }
+ }
+ }
+ return tokens;
+}
+
+DEFINE_TRACE(DocumentOriginTrialContext)
+{
+ visitor->trace(m_parent);
+ OriginTrialContext::trace(visitor);
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContext.h b/third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContext.h
new file mode 100644
index 0000000..01231c9
--- /dev/null
+++ b/third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContext.h
@@ -0,0 +1,41 @@
+// Copyright 2015 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 DocumentOriginTrialContext_h
+#define DocumentOriginTrialContext_h
+
+#include "core/CoreExport.h"
+#include "core/dom/Document.h"
+#include "core/origin_trials/OriginTrialContext.h"
+#include "platform/heap/Handle.h"
+#include "wtf/Forward.h"
+#include <utility>
+
+namespace blink {
+
+class WebApiKeyValidator;
+
+// DocumentOriginTrialContext is a specialization of OriginTrialContext for
+// the Document execution context. It enables and disables feature trials based
+// on the tokens found in <meta> tags in the document header.
+class CORE_EXPORT DocumentOriginTrialContext : public OriginTrialContext {
+public:
+ explicit DocumentOriginTrialContext(Document*);
+ ~DocumentOriginTrialContext() override = default;
+
+ ExecutionContext* executionContext() override { return m_parent; }
+ Vector<String> getTokens() override;
+
+ DECLARE_VIRTUAL_TRACE();
+
+protected:
+ friend class DocumentOriginTrialContextTest;
+
+private:
+ RawPtrWillBeMember<Document> m_parent;
+};
+
+} // namespace blink
+
+#endif // DocumentOriginTrialContext_h
diff --git a/third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContextTest.cpp b/third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContextTest.cpp
new file mode 100644
index 0000000..1c6b231
--- /dev/null
+++ b/third_party/WebKit/Source/core/origin_trials/DocumentOriginTrialContextTest.cpp
@@ -0,0 +1,117 @@
+// Copyright 2015 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 "core/origin_trials/DocumentOriginTrialContext.h"
+
+#include "core/HTMLNames.h"
+#include "core/dom/DOMException.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/frame/FrameView.h"
+#include "core/html/HTMLDocument.h"
+#include "core/html/HTMLHeadElement.h"
+#include "core/html/HTMLMetaElement.h"
+#include "core/testing/DummyPageHolder.h"
+#include "platform/weborigin/KURL.h"
+#include "platform/weborigin/SecurityOrigin.h"
+#include "public/platform/WebTrialTokenValidator.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+using ::testing::UnorderedElementsAre;
+
+namespace {
+
+// API Key which will appear valid
+const char* kGoodTrialToken = "1|AnySignatureWillDo|https://www.example.com|Frobulate|2000000000";
+const char* kAnotherTrialToken = "1|AnySignatureWillDo|https://www.example.com|FrobulateV2|2000000000";
+
+} // namespace
+
+class DocumentOriginTrialContextTest : public ::testing::Test {
+protected:
+ DocumentOriginTrialContextTest()
+ : m_pageHolder(DummyPageHolder::create())
+ , m_frameworkWasEnabled(RuntimeEnabledFeatures::experimentalFrameworkEnabled())
+ {
+ RuntimeEnabledFeatures::setExperimentalFrameworkEnabled(true);
+ }
+
+ ~DocumentOriginTrialContextTest()
+ {
+ RuntimeEnabledFeatures::setExperimentalFrameworkEnabled(m_frameworkWasEnabled);
+ m_pageHolder.clear();
+ }
+
+ void SetUp() override
+ {
+ setInnerHTML(
+ "<html>"
+ "<head>"
+ "</head>"
+ "<body>"
+ "</body>"
+ "</html>");
+ }
+
+ Document& document() { return m_pageHolder->document(); }
+
+ void setPageOrigin(const String& origin)
+ {
+ KURL pageURL(ParsedURLString, origin);
+ RefPtr<SecurityOrigin> pageOrigin = SecurityOrigin::create(pageURL);
+ document().updateSecurityOrigin(pageOrigin);
+ }
+
+ void setInnerHTML(const char* htmlContent)
+ {
+ document().documentElement()->setInnerHTML(String::fromUTF8(htmlContent), ASSERT_NO_EXCEPTION);
+ document().view()->updateAllLifecyclePhases();
+ }
+
+ void addTrialToken(const AtomicString& token)
+ {
+ HTMLElement* head = document().head();
+ ASSERT_TRUE(head);
+
+ RefPtrWillBeRawPtr<HTMLMetaElement> meta = HTMLMetaElement::create(document());
+ meta->setAttribute(HTMLNames::http_equivAttr, OriginTrialContext::kTrialHeaderName);
+ meta->setAttribute(HTMLNames::contentAttr, token);
+ head->appendChild(meta.release());
+ }
+
+ Vector<String> getTokens()
+ {
+ return document().createOriginTrialContext()->getTokens();
+ }
+
+private:
+ OwnPtr<DummyPageHolder> m_pageHolder;
+ const bool m_frameworkWasEnabled;
+};
+
+TEST_F(DocumentOriginTrialContextTest, DetectsZeroTokens)
+{
+ String errorMessage;
+ Vector<String> tokens = getTokens();
+ EXPECT_EQ(0UL, tokens.size());
+}
+
+TEST_F(DocumentOriginTrialContextTest, ExtractsSingleToken)
+{
+ addTrialToken(kGoodTrialToken);
+ Vector<String> tokens = getTokens();
+ EXPECT_EQ(1UL, tokens.size());
+ EXPECT_EQ(kGoodTrialToken, tokens[0]);
+}
+
+TEST_F(DocumentOriginTrialContextTest, ExtractsAllTokens)
+{
+ addTrialToken(kGoodTrialToken);
+ addTrialToken(kAnotherTrialToken);
+ EXPECT_THAT(getTokens(), UnorderedElementsAre(kGoodTrialToken, kAnotherTrialToken));
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp
index 636d43a..788e2d8 100644
--- a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp
+++ b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp
@@ -17,8 +17,6 @@ namespace blink {
namespace {
-const char kTrialHeaderName[] = "origin-trial";
-
String getCurrentOrigin(ExecutionContext* executionContext)
{
return executionContext->securityOrigin()->toString();
@@ -30,40 +28,13 @@ String getDisabledMessage(const String& featureName)
return "The '" + featureName + "' feature is currently enabled in limited trials. Please see [Phosphor console URL] for information on enabling a trial for your site.";
}
-bool hasValidToken(ExecutionContext* executionContext, const String& featureName, String* errorMessage, WebTrialTokenValidator* validator)
-{
- bool foundAnyToken = false;
- String origin = getCurrentOrigin(executionContext);
-
- // When in a document, the token is provided in a meta tag
- if (executionContext->isDocument()) {
- HTMLHeadElement* head = toDocument(executionContext)->head();
- for (HTMLMetaElement* metaElement = head ? Traversal<HTMLMetaElement>::firstChild(*head) : 0; metaElement; metaElement = Traversal<HTMLMetaElement>::nextSibling(*metaElement)) {
- if (equalIgnoringCase(metaElement->httpEquiv(), kTrialHeaderName)) {
- foundAnyToken = true;
- String tokenString = metaElement->content();
- // Check with the validator service to verify the signature.
- if (validator->validateToken(tokenString, origin, featureName)) {
- return true;
- }
- }
- }
- }
+} // namespace
- if (errorMessage) {
- if (foundAnyToken) {
- *errorMessage = "The provided token(s) are not valid for the '" + featureName + "' feature.";
- } else {
- *errorMessage = getDisabledMessage(featureName);
- }
- }
- return false;
-}
+const char OriginTrialContext::kTrialHeaderName[] = "origin-trial";
-} // namespace
+OriginTrialContext::OriginTrialContext() {}
-// static
-bool OriginTrialContext::isFeatureEnabled(ExecutionContext* executionContext, const String& featureName, String* errorMessage, WebTrialTokenValidator* validator)
+bool OriginTrialContext::isFeatureEnabled(const String& featureName, String* errorMessage, WebTrialTokenValidator* validator)
{
if (!RuntimeEnabledFeatures::experimentalFrameworkEnabled()) {
// TODO(iclelland): Set an error message here, the first time the
@@ -71,16 +42,16 @@ bool OriginTrialContext::isFeatureEnabled(ExecutionContext* executionContext, co
return false;
}
- if (!executionContext) {
- ASSERT_NOT_REACHED();
- return false;
- }
-
// Feature trials are only enabled for secure origins
bool isSecure = errorMessage
- ? executionContext->isSecureContext(*errorMessage)
- : executionContext->isSecureContext();
+ ? executionContext()->isSecureContext(*errorMessage)
+ : executionContext()->isSecureContext();
if (!isSecure) {
+ // The execution context should always set a message here, if a valid
+ // pointer was passed in. If it does not, then we should find out why
+ // not, and decide whether the OriginTrialContext should be using its
+ // own error messages for this case.
+ DCHECK(!errorMessage || !errorMessage->isEmpty());
return false;
}
@@ -93,7 +64,32 @@ bool OriginTrialContext::isFeatureEnabled(ExecutionContext* executionContext, co
}
}
- return hasValidToken(executionContext, featureName, errorMessage, validator);
+ return hasValidToken(getTokens(), featureName, errorMessage, validator);
+}
+
+bool OriginTrialContext::hasValidToken(Vector<String> tokens, const String& featureName, String* errorMessage, WebTrialTokenValidator* validator)
+{
+ String origin = getCurrentOrigin(executionContext());
+
+ for (const String& token : tokens) {
+ // Check with the validator service to verify the signature.
+ if (validator->validateToken(token, origin, featureName)) {
+ return true;
+ }
+ }
+
+ if (errorMessage) {
+ if (tokens.size()) {
+ *errorMessage = "The provided token(s) are not valid for the '" + featureName + "' feature.";
+ } else {
+ *errorMessage = getDisabledMessage(featureName);
+ }
+ }
+ return false;
+}
+
+DEFINE_TRACE(OriginTrialContext)
+{
}
} // namespace blink
diff --git a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h
index 579307d..afe5771 100644
--- a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h
+++ b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h
@@ -6,12 +6,13 @@
#define OriginTrialContext_h
#include "core/CoreExport.h"
-#include "core/dom/DOMException.h"
-#include "core/dom/ExecutionContext.h"
-#include "wtf/text/WTFString.h"
+#include "platform/heap/Handle.h"
+#include "wtf/Forward.h"
+#include "wtf/Vector.h"
namespace blink {
+class ExecutionContext;
class WebTrialTokenValidator;
// The Experimental Framework (EF) provides limited access to experimental
@@ -27,24 +28,34 @@ class WebTrialTokenValidator;
// feature names. Instead, the EF validates the name provided by the feature
// implementation against any provided tokens.
//
-// This class is not intended to be instantiated. Any required state is kept
-// with a WebApiKeyValidator object held in the Platform object.
-// The static methods in this class may be called either from the main thread
-// or from a worker thread.
+// This class is abstract, and should be subclassed for each execution context
+// which supports origin trials.
//
// TODO(chasej): Link to documentation, or provide more detail on keys, .etc
-class CORE_EXPORT OriginTrialContext {
+class CORE_EXPORT OriginTrialContext : public NoBaseWillBeGarbageCollectedFinalized<OriginTrialContext> {
+public:
+ static const char kTrialHeaderName[];
+ virtual ~OriginTrialContext() = default;
+
+ virtual ExecutionContext* executionContext() = 0;
+ virtual Vector<String> getTokens() = 0;
+
+ DECLARE_VIRTUAL_TRACE();
+
+protected:
+ OriginTrialContext();
+
private:
friend class OriginTrialContextTest;
friend class OriginTrials;
- OriginTrialContext();
-
// Returns true if the feature should be considered enabled for the current
// execution context. This method usually makes use of the token validator
// object in the platform, but this may be overridden if a custom validator
// is required (for testing, for instance).
- static bool isFeatureEnabled(ExecutionContext*, const String& featureName, String* errorMessage, WebTrialTokenValidator* = nullptr);
+ bool isFeatureEnabled(const String& featureName, String* errorMessage, WebTrialTokenValidator* = nullptr);
+
+ bool hasValidToken(Vector<String> tokens, const String& featureName, String* errorMessage, WebTrialTokenValidator*);
};
} // namespace blink
diff --git a/third_party/WebKit/Source/core/origin_trials/OriginTrialContextTest.cpp b/third_party/WebKit/Source/core/origin_trials/OriginTrialContextTest.cpp
index 6464351..49f7952 100644
--- a/third_party/WebKit/Source/core/origin_trials/OriginTrialContextTest.cpp
+++ b/third_party/WebKit/Source/core/origin_trials/OriginTrialContextTest.cpp
@@ -12,10 +12,12 @@
#include "core/html/HTMLHeadElement.h"
#include "core/html/HTMLMetaElement.h"
#include "core/testing/DummyPageHolder.h"
+#include "core/testing/NullExecutionContext.h"
#include "platform/weborigin/KURL.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "public/platform/WebTrialTokenValidator.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "wtf/Vector.h"
namespace blink {
namespace {
@@ -66,75 +68,76 @@ private:
DISALLOW_COPY_AND_ASSIGN(MockTokenValidator);
};
-} // namespace
-
-class OriginTrialContextTest : public ::testing::Test {
-protected:
- OriginTrialContextTest()
- : m_page(DummyPageHolder::create())
- , m_frameworkWasEnabled(RuntimeEnabledFeatures::experimentalFrameworkEnabled())
- , m_tokenValidator(adoptPtr(new MockTokenValidator()))
+// Concrete subclass of OriginTrialContext which simply maintains a vector of
+// token strings to use for tests.
+class TestOriginTrialContext : public OriginTrialContext {
+public:
+ explicit TestOriginTrialContext()
+ : m_parent(adoptRefWillBeNoop(new NullExecutionContext()))
{
- if (!RuntimeEnabledFeatures::experimentalFrameworkEnabled()) {
- RuntimeEnabledFeatures::setExperimentalFrameworkEnabled(true);
- }
}
- ~OriginTrialContextTest()
- {
- if (!m_frameworkWasEnabled) {
- RuntimeEnabledFeatures::setExperimentalFrameworkEnabled(false);
- }
+ ~TestOriginTrialContext() override = default;
- m_page.clear();
- }
+ ExecutionContext* executionContext() override { return m_parent.get(); }
- void SetUp() override
+ void addToken(const String& token)
{
- m_document = toHTMLDocument(&m_page->document());
- setInnerHTML(
- "<html>"
- "<head>"
- "</head>"
- "<body>"
- "</body>"
- "</html>");
+ m_tokens.append(token);
}
- ExecutionContext* executionContext() { return &(m_page->document()); }
- MockTokenValidator* tokenValidator() { return m_tokenValidator.get(); }
- HTMLDocument& document() const { return *m_document; }
-
- void setPageOrigin(const String& origin)
+ void updateSecurityOrigin(const String& origin)
{
KURL pageURL(ParsedURLString, origin);
RefPtr<SecurityOrigin> pageOrigin = SecurityOrigin::create(pageURL);
- m_page->document().updateSecurityOrigin(pageOrigin);
+ m_parent->setSecurityOrigin(pageOrigin);
+ m_parent->setIsSecureContext(SecurityOrigin::isSecure(pageURL));
}
- void setInnerHTML(const char* htmlContent)
+ Vector<String> getTokens() override
{
- document().documentElement()->setInnerHTML(String::fromUTF8(htmlContent), ASSERT_NO_EXCEPTION);
- document().view()->updateAllLifecyclePhases();
+ Vector<String> tokens;
+ for (String token : m_tokens) {
+ tokens.append(token);
+ }
+ return tokens;
}
- void addTrialToken(const String& token)
+ DEFINE_INLINE_VIRTUAL_TRACE()
{
- HTMLElement* head = document().head();
- ASSERT_TRUE(head);
-
- RefPtrWillBeRawPtr<HTMLMetaElement> meta = HTMLMetaElement::create(document());
- meta->setAttribute(HTMLNames::http_equivAttr, "origin-trial");
- AtomicString value(token);
- meta->setAttribute(HTMLNames::contentAttr, value);
- head->appendChild(meta.release());
+ visitor->trace(m_parent);
+ OriginTrialContext::trace(visitor);
}
+private:
+ RefPtrWillBeMember<NullExecutionContext> m_parent;
+ Vector<String> m_tokens;
+};
+
+} // namespace
+
+class OriginTrialContextTest : public ::testing::Test {
+protected:
+ OriginTrialContextTest()
+ : m_frameworkWasEnabled(RuntimeEnabledFeatures::experimentalFrameworkEnabled())
+ , m_tokenValidator(adoptPtr(new MockTokenValidator()))
+ , m_originTrialContext(adoptPtrWillBeNoop(new TestOriginTrialContext))
+ {
+ RuntimeEnabledFeatures::setExperimentalFrameworkEnabled(true);
+ }
+
+ ~OriginTrialContextTest()
+ {
+ RuntimeEnabledFeatures::setExperimentalFrameworkEnabled(m_frameworkWasEnabled);
+ }
+
+ MockTokenValidator* tokenValidator() { return m_tokenValidator.get(); }
+
bool isFeatureEnabled(const String& origin, const String& featureName, const String& token, String* errorMessage)
{
- setPageOrigin(origin);
- addTrialToken(token);
- return OriginTrialContext::isFeatureEnabled(executionContext(), featureName, errorMessage, tokenValidator());
+ m_originTrialContext->updateSecurityOrigin(origin);
+ m_originTrialContext->addToken(token);
+ return m_originTrialContext->isFeatureEnabled(featureName, errorMessage, tokenValidator());
}
bool isFeatureEnabledWithoutErrorMessage(const String& origin, const String& featureName, const char* token)
@@ -143,10 +146,9 @@ protected:
}
private:
- OwnPtr<DummyPageHolder> m_page;
- RefPtrWillBePersistent<HTMLDocument> m_document;
const bool m_frameworkWasEnabled;
OwnPtr<MockTokenValidator> m_tokenValidator;
+ OwnPtrWillBePersistent<TestOriginTrialContext> m_originTrialContext;
};
TEST_F(OriginTrialContextTest, EnabledNonExistingFeature)
@@ -219,7 +221,17 @@ TEST_F(OriginTrialContextTest, EnabledNonSecureRegisteredOrigin)
kGoodToken,
&errorMessage);
EXPECT_FALSE(isOriginEnabled);
- EXPECT_TRUE(errorMessage.contains("secure origin")) << "Message should indicate only secure origins are allowed, was: " << errorMessage;
+ EXPECT_EQ(0, tokenValidator()->callCount());
+ EXPECT_FALSE(errorMessage.isEmpty());
+}
+
+TEST_F(OriginTrialContextTest, EnabledNonSecureRegisteredOriginWithoutErrorMessage)
+{
+ bool isOriginEnabled = isFeatureEnabledWithoutErrorMessage(
+ kFrobulateEnabledOriginUnsecure,
+ kFrobulateFeatureName,
+ kGoodToken);
+ EXPECT_FALSE(isOriginEnabled);
EXPECT_EQ(0, tokenValidator()->callCount());
}
diff --git a/third_party/WebKit/Source/core/testing/NullExecutionContext.cpp b/third_party/WebKit/Source/core/testing/NullExecutionContext.cpp
index f2a649d..a52527e 100644
--- a/third_party/WebKit/Source/core/testing/NullExecutionContext.cpp
+++ b/third_party/WebKit/Source/core/testing/NullExecutionContext.cpp
@@ -25,6 +25,7 @@ public:
NullExecutionContext::NullExecutionContext()
: m_tasksNeedSuspension(false)
+ , m_isSecureContext(true)
, m_queue(adoptPtrWillBeNoop(new NullEventQueue()))
{
}
@@ -33,9 +34,16 @@ void NullExecutionContext::postTask(const WebTraceLocation&, PassOwnPtr<Executio
{
}
+void NullExecutionContext::setIsSecureContext(bool isSecureContext)
+{
+ m_isSecureContext = isSecureContext;
+}
+
bool NullExecutionContext::isSecureContext(String& errorMessage, const SecureContextCheck privilegeContextCheck) const
{
- return true;
+ if (!m_isSecureContext)
+ errorMessage = "A secure context is required";
+ return m_isSecureContext;
}
} // namespace blink
diff --git a/third_party/WebKit/Source/core/testing/NullExecutionContext.h b/third_party/WebKit/Source/core/testing/NullExecutionContext.h
index 9883edf..9f88e8c 100644
--- a/third_party/WebKit/Source/core/testing/NullExecutionContext.h
+++ b/third_party/WebKit/Source/core/testing/NullExecutionContext.h
@@ -40,6 +40,7 @@ public:
void addConsoleMessage(PassRefPtrWillBeRawPtr<ConsoleMessage>) override { }
void logExceptionToConsole(const String& errorMessage, int scriptId, const String& sourceURL, int lineNumber, int columnNumber, PassRefPtr<ScriptCallStack>) override { }
+ void setIsSecureContext(bool);
bool isSecureContext(String& errorMessage, const SecureContextCheck = StandardSecureContextCheck) const override;
DEFINE_INLINE_TRACE()
@@ -63,6 +64,7 @@ protected:
private:
bool m_tasksNeedSuspension;
+ bool m_isSecureContext;
OwnPtrWillBeMember<EventQueue> m_queue;
KURL m_dummyURL;