summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlizeb <lizeb@chromium.org>2016-02-19 01:29:44 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-19 09:30:56 +0000
commit5120f6dcd75196b5079c8fdae2ef171688b82836 (patch)
treeaae6689ec5bf11697c05ab73f72831bd0bc7e460
parent132a2996a37c917b4bed5150c57f5e17cc56ff68 (diff)
downloadchromium_src-5120f6dcd75196b5079c8fdae2ef171688b82836.zip
chromium_src-5120f6dcd75196b5079c8fdae2ef171688b82836.tar.gz
chromium_src-5120f6dcd75196b5079c8fdae2ef171688b82836.tar.bz2
Android: Add support for android-app scheme in a referrer.
Following android's documentation, native apps can set a referrer with the format android-app://com.foo.bar. This is supported by the Java side, but not the native code. TBR=alokp@chromium.org,asargent@chromium.org # Adding a parameter in chromecast/ and extensions/ TESTED=adb shell am start -n com.google.android.apps.chrome/.Main -a "android.intent.action.VIEW" -d 'http://www.whatismyreferer.com/' --eu "android.intent.extra.REFERRER" "android-app://com.foo.bar" BUG=537863 Review URL: https://codereview.chromium.org/1416863004 Cr-Commit-Position: refs/heads/master@{#376423}
-rw-r--r--chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java81
-rw-r--r--chrome/common/chrome_content_client.cc6
-rw-r--r--chrome/common/chrome_content_client.h1
-rw-r--r--chrome/common/chrome_content_client_ios.mm1
-rw-r--r--chrome/common/url_constants.cc4
-rw-r--r--chrome/common/url_constants.h4
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc10
-rw-r--r--chromecast/common/cast_content_client.cc1
-rw-r--r--chromecast/common/cast_content_client.h1
-rw-r--r--content/common/url_schemes.cc34
-rw-r--r--content/common/url_schemes.h12
-rw-r--r--content/public/common/content_client.h5
-rw-r--r--content/public/common/referrer.cc2
-rw-r--r--extensions/shell/common/shell_content_client.cc1
-rw-r--r--extensions/shell/common/shell_content_client.h1
-rw-r--r--extensions/test/extensions_unittests_main.cc1
-rw-r--r--ios/web/public/url_schemes.h4
-rw-r--r--ios/web/public/url_schemes.mm16
-rw-r--r--net/url_request/url_request_unittest.cc14
-rw-r--r--third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp32
-rw-r--r--third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h5
-rw-r--r--third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp9
-rw-r--r--third_party/WebKit/Source/platform/weborigin/SecurityPolicyTest.cpp30
-rw-r--r--third_party/WebKit/Source/web/WebSecurityPolicy.cpp5
-rw-r--r--third_party/WebKit/public/web/WebSecurityPolicy.h3
-rw-r--r--url/gurl.cc6
-rw-r--r--url/gurl.h3
-rw-r--r--url/url_util.cc153
-rw-r--r--url/url_util.h31
-rw-r--r--url/url_util_unittest.cc15
30 files changed, 383 insertions, 108 deletions
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java
index f5ab4de..ee49238 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java
@@ -6,6 +6,7 @@ package org.chromium.chrome.browser;
import android.content.Intent;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Environment;
import android.provider.Browser;
import android.test.FlakyTest;
@@ -43,9 +44,9 @@ import java.util.concurrent.TimeoutException;
* Test the behavior of tabs when opening a URL from an external app.
*/
public class TabsOpenedFromExternalAppTest extends ChromeTabbedActivityTestBase {
-
private static final String EXTERNAL_APP_1_ID = "app1";
private static final String EXTERNAL_APP_2_ID = "app2";
+ private static final String ANDROID_APP_REFERRER = "android-app://com.my.great.great.app";
static class ElementFocusedCriteria extends Criteria {
private final Tab mTab;
@@ -116,6 +117,40 @@ public class TabsOpenedFromExternalAppTest extends ChromeTabbedActivityTestBase
}
}
+ private static class ReferrerCriteria extends Criteria {
+ private final Tab mTab;
+ private final String mExpectedReferrer;
+ private static final String GET_REFERRER_JS =
+ "(function() { return document.referrer; })();";
+
+ public ReferrerCriteria(Tab tab, String expectedReferrer) {
+ super("Referrer is not as expected.");
+ mTab = tab;
+ // Add quotes to match returned value from JS.
+ mExpectedReferrer = "\"" + expectedReferrer + "\"";
+ }
+
+ @Override
+ public boolean isSatisfied() {
+ String referrer;
+ try {
+ String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult(
+ mTab.getWebContents(), GET_REFERRER_JS);
+ if (jsonText.equalsIgnoreCase("null")) jsonText = "";
+ referrer = jsonText;
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ Assert.fail("InterruptedException was thrown");
+ return false;
+ } catch (TimeoutException e) {
+ e.printStackTrace();
+ Assert.fail("TimeoutException was thrown");
+ return false;
+ }
+ return TextUtils.equals(mExpectedReferrer, referrer);
+ }
+ }
+
private EmbeddedTestServer mTestServer;
public TabsOpenedFromExternalAppTest() {
@@ -146,8 +181,8 @@ public class TabsOpenedFromExternalAppTest extends ChromeTabbedActivityTestBase
* Returns when the URL has been navigated to.
* @throws InterruptedException
*/
- private void launchUrlFromExternalApp(String url, String appId, boolean createNewTab)
- throws InterruptedException {
+ private void launchUrlFromExternalApp(String url, String appId, boolean createNewTab,
+ Bundle extras) throws InterruptedException {
final Intent intent = new Intent(Intent.ACTION_VIEW);
if (appId != null) {
intent.putExtra(Browser.EXTRA_APPLICATION_ID, appId);
@@ -156,6 +191,7 @@ public class TabsOpenedFromExternalAppTest extends ChromeTabbedActivityTestBase
intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true);
}
intent.setData(Uri.parse(url));
+ if (extras != null) intent.putExtras(extras);
final Tab originalTab = getActivity().getActivityTab();
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@@ -175,6 +211,45 @@ public class TabsOpenedFromExternalAppTest extends ChromeTabbedActivityTestBase
ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
}
+ private void launchUrlFromExternalApp(String url, String appId, boolean createNewTab)
+ throws InterruptedException {
+ launchUrlFromExternalApp(url, appId, createNewTab, null);
+ }
+
+ /**
+ * Tests that URLs opened from external apps can set an android-app scheme referrer.
+ * @throws InterruptedException
+ */
+ @LargeTest
+ @Feature({"Navigation"})
+ public void testReferrer() throws InterruptedException {
+ String url = mTestServer.getURL("/chrome/test/data/android/about.html");
+ startMainActivityFromLauncher();
+ Bundle extras = new Bundle();
+ extras.putParcelable(Intent.EXTRA_REFERRER, Uri.parse(ANDROID_APP_REFERRER));
+ launchUrlFromExternalApp(url, EXTERNAL_APP_1_ID, true, extras);
+ CriteriaHelper.pollForCriteria(
+ new ReferrerCriteria(getActivity().getActivityTab(), ANDROID_APP_REFERRER), 2000,
+ 200);
+ }
+
+ /**
+ * Tests that URLs opened from external apps can set an android-app scheme referrer.
+ * @throws InterruptedException
+ */
+ @LargeTest
+ @Feature({"Navigation"})
+ public void testCannotSetArbitraryReferrer() throws InterruptedException {
+ String url = mTestServer.getURL("/chrome/test/data/android/about.html");
+ startMainActivityFromLauncher();
+ String referrer = "foobar://totally.legit.referrer";
+ Bundle extras = new Bundle();
+ extras.putParcelable(Intent.EXTRA_REFERRER, Uri.parse(referrer));
+ launchUrlFromExternalApp(url, EXTERNAL_APP_1_ID, true, extras);
+ CriteriaHelper.pollForCriteria(
+ new ReferrerCriteria(getActivity().getActivityTab(), ""), 2000, 200);
+ }
+
/**
* Tests that URLs opened from the same external app don't create new tabs.
* @throws InterruptedException
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index 58564f2..779c8a5 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -539,10 +539,16 @@ static const url::SchemeWithType kChromeStandardURLSchemes[
void ChromeContentClient::AddAdditionalSchemes(
std::vector<url::SchemeWithType>* standard_schemes,
+ std::vector<url::SchemeWithType>* referrer_schemes,
std::vector<std::string>* savable_schemes) {
for (int i = 0; i < kNumChromeStandardURLSchemes; i++)
standard_schemes->push_back(kChromeStandardURLSchemes[i]);
+#if defined(OS_ANDROID)
+ referrer_schemes->push_back(
+ {chrome::kAndroidAppScheme, url::SCHEME_WITHOUT_PORT});
+#endif
+
savable_schemes->push_back(extensions::kExtensionScheme);
savable_schemes->push_back(extensions::kExtensionResourceScheme);
savable_schemes->push_back(chrome::kChromeSearchScheme);
diff --git a/chrome/common/chrome_content_client.h b/chrome/common/chrome_content_client.h
index 33515ea..21a8bbda 100644
--- a/chrome/common/chrome_content_client.h
+++ b/chrome/common/chrome_content_client.h
@@ -60,6 +60,7 @@ class ChromeContentClient : public content::ContentClient {
void AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) override;
void AddAdditionalSchemes(std::vector<url::SchemeWithType>* standard_schemes,
+ std::vector<url::SchemeWithType>* referrer_schemes,
std::vector<std::string>* saveable_shemes) override;
bool CanSendWhileSwappedOut(const IPC::Message* message) override;
std::string GetProduct() const override;
diff --git a/chrome/common/chrome_content_client_ios.mm b/chrome/common/chrome_content_client_ios.mm
index bfca613..fb603f7 100644
--- a/chrome/common/chrome_content_client_ios.mm
+++ b/chrome/common/chrome_content_client_ios.mm
@@ -32,6 +32,7 @@ void ChromeContentClient::AddPepperPlugins(
void ChromeContentClient::AddAdditionalSchemes(
std::vector<url::SchemeWithType>* standard_schemes,
+ std::vector<url::SchemeWithType>* referrer_schemes,
std::vector<std::string>* saveable_shemes) {
// No additional schemes for iOS.
}
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index ed60a71..4ae8e21 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -18,6 +18,10 @@ namespace chrome {
const char kCrosScheme[] = "cros";
#endif
+#if defined(OS_ANDROID)
+const char kAndroidAppScheme[] = "android-app";
+#endif
+
// Add Chrome UI URLs as necessary, in alphabetical order.
// Be sure to add the corresponding kChromeUI*Host constant below.
// This is a WebUI page that lists other WebUI pages.
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 2e25824..28b7836 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -537,6 +537,10 @@ extern const char kChromeUIDiscardsURL[];
extern const char kCrosScheme[];
#endif
+#if defined(OS_ANDROID)
+extern const char kAndroidAppScheme[];
+#endif
+
// "Learn more" URL for the Cloud Print section under Options.
extern const char kCloudPrintLearnMoreURL[];
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 7d00445..dc9f4e7 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -79,6 +79,7 @@
#include "components/web_cache/renderer/web_cache_render_process_observer.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
#include "content/public/renderer/plugin_instance_throttler.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
@@ -393,8 +394,13 @@ void ChromeContentRendererClient::RenderThreadStarted() {
WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(dom_distiller_scheme);
#if defined(OS_CHROMEOS)
- WebString external_file_scheme(ASCIIToUTF16(content::kExternalFileScheme));
- WebSecurityPolicy::registerURLSchemeAsLocal(external_file_scheme);
+ WebSecurityPolicy::registerURLSchemeAsLocal(
+ WebString::fromUTF8(content::kExternalFileScheme));
+#endif
+
+#if defined(OS_ANDROID)
+ WebSecurityPolicy::registerURLSchemeAsAllowedForReferrer(
+ WebString::fromUTF8(chrome::kAndroidAppScheme));
#endif
#if defined(ENABLE_IPC_FUZZER)
diff --git a/chromecast/common/cast_content_client.cc b/chromecast/common/cast_content_client.cc
index 2332ba6..302be4e 100644
--- a/chromecast/common/cast_content_client.cc
+++ b/chromecast/common/cast_content_client.cc
@@ -81,6 +81,7 @@ CastContentClient::~CastContentClient() {
void CastContentClient::AddAdditionalSchemes(
std::vector<url::SchemeWithType>* standard_schemes,
+ std::vector<url::SchemeWithType>* referrer_schemes,
std::vector<std::string>* savable_schemes) {
standard_schemes->push_back(kChromeResourceSchemeWithType);
}
diff --git a/chromecast/common/cast_content_client.h b/chromecast/common/cast_content_client.h
index f77a610..073debc 100644
--- a/chromecast/common/cast_content_client.h
+++ b/chromecast/common/cast_content_client.h
@@ -18,6 +18,7 @@ class CastContentClient : public content::ContentClient {
// content::ContentClient implementation:
void AddAdditionalSchemes(std::vector<url::SchemeWithType>* standard_schemes,
+ std::vector<url::SchemeWithType>* referrer_schemes,
std::vector<std::string>* saveable_shemes) override;
std::string GetUserAgent() const override;
base::string16 GetLocalizedString(int message_id) const override;
diff --git a/content/common/url_schemes.cc b/content/common/url_schemes.cc
index 6d4c58c..c985e85 100644
--- a/content/common/url_schemes.cc
+++ b/content/common/url_schemes.cc
@@ -18,35 +18,37 @@
namespace {
-void AddStandardSchemeHelper(const url::SchemeWithType& scheme) {
- url::AddStandardScheme(scheme.scheme, scheme.type);
-}
-
} // namespace
namespace content {
-void RegisterContentSchemes(bool lock_standard_schemes) {
+void RegisterContentSchemes(bool lock_schemes) {
std::vector<url::SchemeWithType> additional_standard_schemes;
+ std::vector<url::SchemeWithType> additional_referrer_schemes;
std::vector<std::string> additional_savable_schemes;
+
GetContentClient()->AddAdditionalSchemes(&additional_standard_schemes,
+ &additional_referrer_schemes,
&additional_savable_schemes);
url::AddStandardScheme(kChromeDevToolsScheme, url::SCHEME_WITHOUT_PORT);
url::AddStandardScheme(kChromeUIScheme, url::SCHEME_WITHOUT_PORT);
url::AddStandardScheme(kGuestScheme, url::SCHEME_WITHOUT_PORT);
url::AddStandardScheme(kMetadataScheme, url::SCHEME_WITHOUT_AUTHORITY);
- std::for_each(additional_standard_schemes.begin(),
- additional_standard_schemes.end(),
- AddStandardSchemeHelper);
-
- // Prevent future modification of the standard schemes list. This is to
- // prevent accidental creation of data races in the program. AddStandardScheme
- // isn't threadsafe so must be called when GURL isn't used on any other
- // thread. This is really easy to mess up, so we say that all calls to
- // AddStandardScheme in Chrome must be inside this function.
- if (lock_standard_schemes)
- url::LockStandardSchemes();
+
+ for (const url::SchemeWithType& scheme : additional_standard_schemes)
+ url::AddStandardScheme(scheme.scheme, scheme.type);
+
+ for (const url::SchemeWithType& scheme : additional_referrer_schemes)
+ url::AddReferrerScheme(scheme.scheme, scheme.type);
+
+ // Prevent future modification of the scheme lists. This is to prevent
+ // accidental creation of data races in the program. Add*Scheme aren't
+ // threadsafe so must be called when GURL isn't used on any other thread. This
+ // is really easy to mess up, so we say that all calls to Add*Scheme in Chrome
+ // must be inside this function.
+ if (lock_schemes)
+ url::LockSchemeRegistries();
// We rely on the above lock to protect this part from being invoked twice.
if (!additional_savable_schemes.empty()) {
diff --git a/content/common/url_schemes.h b/content/common/url_schemes.h
index 571c660..1441c9c 100644
--- a/content/common/url_schemes.h
+++ b/content/common/url_schemes.h
@@ -10,16 +10,16 @@
namespace content {
// Note: ContentMainRunner calls this method internally as part of main
-// initialziation, so this function generally should not be called by
+// initialization, so this function generally should not be called by
// embedders. It's exported to facilitate test harnesses that do not
// utilize ContentMainRunner and that do not wish to lock the set
// of standard schemes at init time.
//
-// Called near the beginning of startup to register URL schemes that should
-// be parsed as "standard" with the src/url/ library. Optionally, the set
-// of standard schemes is locked down. The embedder can add additional
-// schemes by overriding the ContentClient::AddAdditionalSchemes method.
-CONTENT_EXPORT void RegisterContentSchemes(bool lock_standard_schemes);
+// Called near the beginning of startup to register URL schemes that should be
+// parsed as "standard" or "referrer" with the src/url/ library. Optionally, the
+// sets of schemes are locked down. The embedder can add additional schemes by
+// overriding the ContentClient::AddAdditionalSchemes method.
+CONTENT_EXPORT void RegisterContentSchemes(bool lock_schemes);
} // namespace content
diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h
index 5bd865d..eabd3da 100644
--- a/content/public/common/content_client.h
+++ b/content/public/common/content_client.h
@@ -88,10 +88,11 @@ class CONTENT_EXPORT ContentClient {
virtual void AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) {}
- // Gives the embedder a chance to register its own standard and saveable
- // url schemes early on in the startup sequence.
+ // Gives the embedder a chance to register its own standard, referrer and
+ // saveable url schemes early on in the startup sequence.
virtual void AddAdditionalSchemes(
std::vector<url::SchemeWithType>* standard_schemes,
+ std::vector<url::SchemeWithType>* referrer_schemes,
std::vector<std::string>* savable_schemes) {}
// Returns whether the given message should be sent in a swapped out renderer.
diff --git a/content/public/common/referrer.cc b/content/public/common/referrer.cc
index 183c950..bd145a2 100644
--- a/content/public/common/referrer.cc
+++ b/content/public/common/referrer.cc
@@ -14,7 +14,7 @@ Referrer Referrer::SanitizeForRequest(const GURL& request,
Referrer sanitized_referrer(referrer.url.GetAsReferrer(), referrer.policy);
if (!request.SchemeIsHTTPOrHTTPS() ||
- !sanitized_referrer.url.SchemeIsHTTPOrHTTPS()) {
+ !sanitized_referrer.url.SchemeIsValidForReferrer()) {
sanitized_referrer.url = GURL();
return sanitized_referrer;
}
diff --git a/extensions/shell/common/shell_content_client.cc b/extensions/shell/common/shell_content_client.cc
index 946fe83..e180da8 100644
--- a/extensions/shell/common/shell_content_client.cc
+++ b/extensions/shell/common/shell_content_client.cc
@@ -83,6 +83,7 @@ static const url::SchemeWithType kShellStandardURLSchemes[
void ShellContentClient::AddAdditionalSchemes(
std::vector<url::SchemeWithType>* standard_schemes,
+ std::vector<url::SchemeWithType>* referrer_schemes,
std::vector<std::string>* savable_schemes) {
for (int i = 0; i < kNumShellStandardURLSchemes; i++)
standard_schemes->push_back(kShellStandardURLSchemes[i]);
diff --git a/extensions/shell/common/shell_content_client.h b/extensions/shell/common/shell_content_client.h
index f105511..471272a 100644
--- a/extensions/shell/common/shell_content_client.h
+++ b/extensions/shell/common/shell_content_client.h
@@ -20,6 +20,7 @@ class ShellContentClient : public content::ContentClient {
void AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) override;
void AddAdditionalSchemes(std::vector<url::SchemeWithType>* standard_schemes,
+ std::vector<url::SchemeWithType>* referrer_schemes,
std::vector<std::string>* saveable_shemes) override;
std::string GetUserAgent() const override;
base::string16 GetLocalizedString(int message_id) const override;
diff --git a/extensions/test/extensions_unittests_main.cc b/extensions/test/extensions_unittests_main.cc
index bb9cc00..f0ea868 100644
--- a/extensions/test/extensions_unittests_main.cc
+++ b/extensions/test/extensions_unittests_main.cc
@@ -39,6 +39,7 @@ class ExtensionsContentClient : public content::ContentClient {
// content::ContentClient overrides:
void AddAdditionalSchemes(
std::vector<url::SchemeWithType>* standard_schemes,
+ std::vector<url::SchemeWithType>* referrer_schemes,
std::vector<std::string>* savable_schemes) override {
for (int i = 0; i < kNumExtensionStandardURLSchemes; i++)
standard_schemes->push_back(kExtensionStandardURLSchemes[i]);
diff --git a/ios/web/public/url_schemes.h b/ios/web/public/url_schemes.h
index ccbc99c..6532916 100644
--- a/ios/web/public/url_schemes.h
+++ b/ios/web/public/url_schemes.h
@@ -15,10 +15,10 @@ namespace web {
//
// Called near the beginning of startup to register URL schemes that
// should be parsed as "standard" with the src/url/ library. The set
-// of standard scheme is locked if |lock_standard_schemes| is true.
+// of standard scheme is locked if |lock_schemes| is true.
// The embedder can add additional schemes by overriding the
// WebClient::AddAditionalSchemes method.
-void RegisterWebSchemes(bool lock_standard_schemes);
+void RegisterWebSchemes(bool lock_schemes);
} // namespace web
diff --git a/ios/web/public/url_schemes.mm b/ios/web/public/url_schemes.mm
index 638ba7f..e501ee2 100644
--- a/ios/web/public/url_schemes.mm
+++ b/ios/web/public/url_schemes.mm
@@ -18,19 +18,19 @@ void AddStandardSchemeHelper(const url::SchemeWithType& scheme) {
}
} // namespace
-void RegisterWebSchemes(bool lock_standard_schemes) {
+void RegisterWebSchemes(bool lock_schemes) {
std::vector<url::SchemeWithType> additional_standard_schemes;
GetWebClient()->AddAdditionalSchemes(&additional_standard_schemes);
std::for_each(additional_standard_schemes.begin(),
additional_standard_schemes.end(), AddStandardSchemeHelper);
- // Prevent future modification of the standard schemes list. This is to
- // prevent accidental creation of data races in the program. AddStandardScheme
- // isn't threadsafe so must be called when GURL isn't used on any other
- // thread. This is really easy to mess up, so we say that all calls to
- // AddStandardScheme in Chrome must be inside this function.
- if (lock_standard_schemes)
- url::LockStandardSchemes();
+ // Prevent future modification of the schemes lists. This is to prevent
+ // accidental creation of data races in the program. Add*Scheme aren't
+ // threadsafe so must be called when GURL isn't used on any other thread. This
+ // is really easy to mess up, so we say that all calls to Add*Scheme in Chrome
+ // must be inside this function.
+ if (lock_schemes)
+ url::LockSchemeRegistries();
}
} // namespace web
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 748b753..55f5235 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -6567,6 +6567,20 @@ TEST_F(URLRequestTestHTTP, RedirectJobWithReferenceFragment) {
EXPECT_EQ(redirect_url, r->url());
}
+TEST_F(URLRequestTestHTTP, UnsupportedReferrerScheme) {
+ ASSERT_TRUE(http_test_server()->Start());
+
+ const std::string referrer("foobar://totally.legit.referrer");
+ TestDelegate d;
+ scoped_ptr<URLRequest> req(default_context_.CreateRequest(
+ http_test_server()->GetURL("/echoheader?Referer"), DEFAULT_PRIORITY, &d));
+ req->SetReferrer(referrer);
+ req->Start();
+ base::RunLoop().Run();
+
+ EXPECT_EQ(std::string("None"), d.data_received());
+}
+
TEST_F(URLRequestTestHTTP, NoUserPassInReferrer) {
ASSERT_TRUE(http_test_server()->Start());
diff --git a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
index 8489a85..491c651 100644
--- a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
@@ -194,6 +194,18 @@ static URLSchemesSet& secureContextBypassingSchemes()
return secureContextBypassingSchemes;
}
+static URLSchemesSet& allowedInReferrerSchemes()
+{
+ DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, allowedInReferrerSchemes, ());
+
+ if (allowedInReferrerSchemes.isEmpty()) {
+ allowedInReferrerSchemes.add("http");
+ allowedInReferrerSchemes.add("https");
+ }
+
+ return allowedInReferrerSchemes;
+}
+
bool SchemeRegistry::shouldTreatURLSchemeAsLocal(const String& scheme)
{
if (scheme.isEmpty())
@@ -392,6 +404,26 @@ bool SchemeRegistry::shouldTreatURLSchemeAsFirstPartyWhenTopLevel(const String&
return firstPartyWhenTopLevelSchemes().contains(scheme);
}
+void SchemeRegistry::registerURLSchemeAsAllowedForReferrer(const String& scheme)
+{
+ MutexLocker locker(mutex());
+ allowedInReferrerSchemes().add(scheme);
+}
+
+void SchemeRegistry::removeURLSchemeAsAllowedForReferrer(const String& scheme)
+{
+ MutexLocker locker(mutex());
+ allowedInReferrerSchemes().remove(scheme);
+}
+
+bool SchemeRegistry::shouldTreatURLSchemeAsAllowedForReferrer(const String& scheme)
+{
+ if (scheme.isEmpty())
+ return false;
+ MutexLocker locker(mutex());
+ return allowedInReferrerSchemes().contains(scheme);
+}
+
void SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme, PolicyAreas policyAreas)
{
MutexLocker locker(mutex());
diff --git a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h
index 153cf4a..a234c9b 100644
--- a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h
+++ b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h
@@ -101,6 +101,11 @@ public:
static void registerURLSchemeAsFirstPartyWhenTopLevel(const String& scheme);
static bool shouldTreatURLSchemeAsFirstPartyWhenTopLevel(const String& scheme);
+ // Schemes that can be used in a referrer.
+ static void registerURLSchemeAsAllowedForReferrer(const String& scheme);
+ static void removeURLSchemeAsAllowedForReferrer(const String& scheme);
+ static bool shouldTreatURLSchemeAsAllowedForReferrer(const String& scheme);
+
// Allow resources from some schemes to load on a page, regardless of its
// Content Security Policy.
// This enum should be kept in sync with public/web/WebSecurityPolicy.h.
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
index af82e51..3eb154a 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
@@ -31,6 +31,7 @@
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/weborigin/KURL.h"
#include "platform/weborigin/OriginAccessEntry.h"
+#include "platform/weborigin/SchemeRegistry.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "wtf/HashMap.h"
#include "wtf/HashSet.h"
@@ -67,9 +68,10 @@ void SecurityPolicy::init()
bool SecurityPolicy::shouldHideReferrer(const KURL& url, const String& referrer)
{
bool referrerIsSecureURL = protocolIs(referrer, "https");
- bool referrerIsWebURL = referrerIsSecureURL || protocolIs(referrer, "http");
+ String scheme = KURL(KURL(), referrer).protocol();
+ bool schemeIsAllowed = SchemeRegistry::shouldTreatURLSchemeAsAllowedForReferrer(scheme);
- if (!referrerIsWebURL)
+ if (!schemeIsAllowed)
return true;
if (!referrerIsSecureURL)
@@ -85,7 +87,8 @@ Referrer SecurityPolicy::generateReferrer(ReferrerPolicy referrerPolicy, const K
if (referrer.isEmpty())
return Referrer(String(), referrerPolicy);
- if (!(protocolIs(referrer, "https") || protocolIs(referrer, "http")))
+ String scheme = KURL(KURL(), referrer).protocol();
+ if (!SchemeRegistry::shouldTreatURLSchemeAsAllowedForReferrer(scheme))
return Referrer(String(), referrerPolicy);
if (SecurityOrigin::shouldUseInnerURL(url))
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityPolicyTest.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityPolicyTest.cpp
index 59a3603..e6ed820 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityPolicyTest.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityPolicyTest.cpp
@@ -31,14 +31,40 @@
#include "platform/weborigin/SecurityPolicy.h"
#include "platform/weborigin/KURL.h"
+#include "platform/weborigin/SchemeRegistry.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
-TEST(SecurityPolicyTest, ReferrerIsAlwaysAWebURL)
+TEST(SecurityPolicyTest, EmptyReferrerForUnauthorizedScheme)
{
- EXPECT_TRUE(String() == SecurityPolicy::generateReferrer(ReferrerPolicyAlways, KURL(ParsedURLString, "http://example.com/"), String::fromUTF8("chrome://somepage/")).referrer);
+ const KURL exampleHttpUrl = KURL(ParsedURLString, "http://example.com/");
+ EXPECT_TRUE(String() == SecurityPolicy::generateReferrer(ReferrerPolicyAlways, exampleHttpUrl, String::fromUTF8("chrome://somepage/")).referrer);
+}
+
+TEST(SecurityPolicyTest, GenerateReferrerRespectsReferrerSchemesRegistry)
+{
+ const KURL exampleHttpUrl = KURL(ParsedURLString, "http://example.com/");
+ const String foobarURL = String::fromUTF8("foobar://somepage/");
+ const String foobarScheme = String::fromUTF8("foobar");
+
+ EXPECT_EQ(String(), SecurityPolicy::generateReferrer(ReferrerPolicyAlways, exampleHttpUrl, foobarURL).referrer);
+ SchemeRegistry::registerURLSchemeAsAllowedForReferrer(foobarScheme);
+ EXPECT_EQ(foobarURL, SecurityPolicy::generateReferrer(ReferrerPolicyAlways, exampleHttpUrl, foobarURL).referrer);
+ SchemeRegistry::removeURLSchemeAsAllowedForReferrer(foobarScheme);
+}
+
+TEST(SecurityPolicyTest, ShouldHideReferrerRespectsReferrerSchemesRegistry)
+{
+ const KURL exampleHttpUrl = KURL(ParsedURLString, "http://example.com/");
+ const String foobarURL = String::fromUTF8("foobar://somepage/");
+ const String foobarScheme = String::fromUTF8("foobar");
+
+ EXPECT_TRUE(SecurityPolicy::shouldHideReferrer(exampleHttpUrl, foobarScheme));
+ SchemeRegistry::registerURLSchemeAsAllowedForReferrer(foobarScheme);
+ EXPECT_FALSE(SecurityPolicy::shouldHideReferrer(exampleHttpUrl, foobarURL));
+ SchemeRegistry::removeURLSchemeAsAllowedForReferrer(foobarScheme);
}
TEST(SecurityPolicyTest, GenerateReferrer)
diff --git a/third_party/WebKit/Source/web/WebSecurityPolicy.cpp b/third_party/WebKit/Source/web/WebSecurityPolicy.cpp
index ea67c1d..2c1ac0f 100644
--- a/third_party/WebKit/Source/web/WebSecurityPolicy.cpp
+++ b/third_party/WebKit/Source/web/WebSecurityPolicy.cpp
@@ -152,4 +152,9 @@ void WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs(const WebSt
SchemeRegistry::registerURLSchemeAsNotAllowingJavascriptURLs(scheme);
}
+void WebSecurityPolicy::registerURLSchemeAsAllowedForReferrer(const WebString& scheme)
+{
+ SchemeRegistry::registerURLSchemeAsAllowedForReferrer(scheme);
+}
+
} // namespace blink
diff --git a/third_party/WebKit/public/web/WebSecurityPolicy.h b/third_party/WebKit/public/web/WebSecurityPolicy.h
index fbe011d..eb2858f 100644
--- a/third_party/WebKit/public/web/WebSecurityPolicy.h
+++ b/third_party/WebKit/public/web/WebSecurityPolicy.h
@@ -125,6 +125,9 @@ public:
// by bookmarklets or javascript: URLs typed in the omnibox.
BLINK_EXPORT static void registerURLSchemeAsNotAllowingJavascriptURLs(const WebString&);
+ // Registers an URL scheme as allowed in referrers.
+ BLINK_EXPORT static void registerURLSchemeAsAllowedForReferrer(const WebString&);
+
private:
WebSecurityPolicy();
};
diff --git a/url/gurl.cc b/url/gurl.cc
index db8b277..2b67bee 100644
--- a/url/gurl.cc
+++ b/url/gurl.cc
@@ -332,7 +332,7 @@ GURL GURL::GetOrigin() const {
}
GURL GURL::GetAsReferrer() const {
- if (!is_valid_ || !SchemeIsHTTPOrHTTPS())
+ if (!SchemeIsValidForReferrer())
return GURL();
if (!has_ref() && !has_username() && !has_password())
@@ -386,6 +386,10 @@ bool GURL::SchemeIsHTTPOrHTTPS() const {
return SchemeIs(url::kHttpScheme) || SchemeIs(url::kHttpsScheme);
}
+bool GURL::SchemeIsValidForReferrer() const {
+ return is_valid_ && IsReferrerScheme(spec_.data(), parsed_.scheme);
+}
+
bool GURL::SchemeIsWSOrWSS() const {
return SchemeIs(url::kWsScheme) || SchemeIs(url::kWssScheme);
}
diff --git a/url/gurl.h b/url/gurl.h
index 6af2bac..c55959b 100644
--- a/url/gurl.h
+++ b/url/gurl.h
@@ -215,6 +215,9 @@ class URL_EXPORT GURL {
// Returns true if the scheme is "http" or "https".
bool SchemeIsHTTPOrHTTPS() const;
+ // Returns true if the scheme is valid for use as a referrer.
+ bool SchemeIsValidForReferrer() const;
+
// Returns true is the scheme is "ws" or "wss".
bool SchemeIsWSOrWSS() const;
diff --git a/url/url_util.cc b/url/url_util.cc
index cbb252f..c1e9979 100644
--- a/url/url_util.cc
+++ b/url/url_util.cc
@@ -34,13 +34,21 @@ const SchemeWithType kStandardURLSchemes[kNumStandardURLSchemes] = {
{kFileSystemScheme, SCHEME_WITHOUT_AUTHORITY},
};
-// List of the currently installed standard schemes. This list is lazily
-// initialized by InitStandardSchemes and is leaked on shutdown to prevent
-// any destructors from being called that will slow us down or cause problems.
-std::vector<SchemeWithType>* standard_schemes = NULL;
+const int kNumReferrerURLSchemes = 2;
+const SchemeWithType kReferrerURLSchemes[kNumReferrerURLSchemes] = {
+ {kHttpScheme, SCHEME_WITH_PORT},
+ {kHttpsScheme, SCHEME_WITH_PORT},
+};
+
+// Lists of the currently installed standard and referrer schemes. These lists
+// are lazily initialized by InitStandardSchemes and InitReferrerSchemes and are
+// leaked on shutdown to prevent any destructors from being called that will
+// slow us down or cause problems.
+std::vector<SchemeWithType>* standard_schemes = nullptr;
+std::vector<SchemeWithType>* referrer_schemes = nullptr;
-// See the LockStandardSchemes declaration in the header.
-bool standard_schemes_locked = false;
+// See the LockSchemeRegistries declaration in the header.
+bool scheme_registries_locked = false;
// This template converts a given character type to the corresponding
// StringPiece type.
@@ -53,14 +61,27 @@ template<> struct CharToStringPiece<base::char16> {
typedef base::StringPiece16 Piece;
};
-// Ensures that the standard_schemes list is initialized, does nothing if it
-// already has values.
-void InitStandardSchemes() {
- if (standard_schemes)
+void InitSchemes(std::vector<SchemeWithType>** schemes,
+ const SchemeWithType* initial_schemes,
+ size_t size) {
+ if (*schemes)
return;
- standard_schemes = new std::vector<SchemeWithType>;
- for (int i = 0; i < kNumStandardURLSchemes; i++)
- standard_schemes->push_back(kStandardURLSchemes[i]);
+ *schemes = new std::vector<SchemeWithType>(size);
+ for (size_t i = 0; i < size; i++) {
+ (*schemes)->push_back(initial_schemes[i]);
+ }
+}
+
+// Ensures that the standard_schemes list is initialized, does nothing if
+// it already has values.
+void InitStandardSchemes() {
+ InitSchemes(&standard_schemes, kStandardURLSchemes, kNumStandardURLSchemes);
+}
+
+// Ensures that the referrer_schemes list is initialized, does nothing if
+// it already has values.
+void InitReferrerSchemes() {
+ InitSchemes(&referrer_schemes, kReferrerURLSchemes, kNumReferrerURLSchemes);
}
// Given a string and a range inside the string, compares it to the given
@@ -78,22 +99,20 @@ inline bool DoCompareSchemeComponent(const CHAR* spec,
}
// Returns true and sets |type| to the SchemeType of the given scheme
-// identified by |scheme| within |spec| if the scheme is one of the registered
-// "standard" schemes.
+// identified by |scheme| within |spec| if in |schemes|.
template<typename CHAR>
-bool DoIsStandard(const CHAR* spec,
- const Component& scheme,
- SchemeType* type) {
+bool DoIsInSchemes(const CHAR* spec,
+ const Component& scheme,
+ SchemeType* type,
+ const std::vector<SchemeWithType>& schemes) {
if (!scheme.is_nonempty())
return false; // Empty or invalid schemes are non-standard.
- InitStandardSchemes();
- for (size_t i = 0; i < standard_schemes->size(); i++) {
- if (base::LowerCaseEqualsASCII(
- typename CharToStringPiece<CHAR>::Piece(
- &spec[scheme.begin], scheme.len),
- standard_schemes->at(i).scheme)) {
- *type = standard_schemes->at(i).type;
+ for (const SchemeWithType& scheme_with_type : schemes) {
+ if (base::LowerCaseEqualsASCII(typename CharToStringPiece<CHAR>::Piece(
+ &spec[scheme.begin], scheme.len),
+ scheme_with_type.scheme)) {
+ *type = scheme_with_type.type;
return true;
}
}
@@ -101,6 +120,13 @@ bool DoIsStandard(const CHAR* spec,
}
template<typename CHAR>
+bool DoIsStandard(const CHAR* spec, const Component& scheme, SchemeType* type) {
+ InitStandardSchemes();
+ return DoIsInSchemes(spec, scheme, type, *standard_schemes);
+}
+
+
+template<typename CHAR>
bool DoFindAndCompareScheme(const CHAR* str,
int str_len,
const char* compare,
@@ -364,31 +390,19 @@ bool DoReplaceComponents(const char* spec,
return ReplacePathURL(spec, parsed, replacements, output, out_parsed);
}
-} // namespace
-
-void Initialize() {
- InitStandardSchemes();
-}
-
-void Shutdown() {
- if (standard_schemes) {
- delete standard_schemes;
- standard_schemes = NULL;
- }
-}
-
-void AddStandardScheme(const char* new_scheme,
- SchemeType type) {
- // If this assert triggers, it means you've called AddStandardScheme after
- // LockStandardSchemes have been called (see the header file for
- // LockStandardSchemes for more).
+void DoAddScheme(const char* new_scheme,
+ SchemeType type,
+ std::vector<SchemeWithType>* schemes) {
+ DCHECK(schemes);
+ // If this assert triggers, it means you've called Add*Scheme after
+ // LockSchemeRegistries has been called (see the header file for
+ // LockSchemeRegistries for more).
//
- // This normally means you're trying to set up a new standard scheme too late
- // in your application's init process. Locate where your app does this
- // initialization and calls LockStandardSchemes, and add your new standard
- // scheme there.
- DCHECK(!standard_schemes_locked) <<
- "Trying to add a standard scheme after the list has been locked.";
+ // This normally means you're trying to set up a new scheme too late in your
+ // application's init process. Locate where your app does this initialization
+ // and calls LockSchemeRegistries, and add your new scheme there.
+ DCHECK(!scheme_registries_locked)
+ << "Trying to add a scheme after the lists have been locked.";
size_t scheme_len = strlen(new_scheme);
if (scheme_len == 0)
@@ -400,15 +414,42 @@ void AddStandardScheme(const char* new_scheme,
ANNOTATE_LEAKING_OBJECT_PTR(dup_scheme);
memcpy(dup_scheme, new_scheme, scheme_len + 1);
- InitStandardSchemes();
SchemeWithType scheme_with_type;
scheme_with_type.scheme = dup_scheme;
scheme_with_type.type = type;
- standard_schemes->push_back(scheme_with_type);
+ schemes->push_back(scheme_with_type);
+}
+
+} // namespace
+
+void Initialize() {
+ InitStandardSchemes();
+ InitReferrerSchemes();
+}
+
+void Shutdown() {
+ if (standard_schemes) {
+ delete standard_schemes;
+ standard_schemes = NULL;
+ }
+ if (referrer_schemes) {
+ delete referrer_schemes;
+ referrer_schemes = NULL;
+ }
}
-void LockStandardSchemes() {
- standard_schemes_locked = true;
+void AddStandardScheme(const char* new_scheme, SchemeType type) {
+ InitStandardSchemes();
+ DoAddScheme(new_scheme, type, standard_schemes);
+}
+
+void AddReferrerScheme(const char* new_scheme, SchemeType type) {
+ InitReferrerSchemes();
+ DoAddScheme(new_scheme, type, referrer_schemes);
+}
+
+void LockSchemeRegistries() {
+ scheme_registries_locked = true;
}
bool IsStandard(const char* spec, const Component& scheme) {
@@ -427,6 +468,12 @@ bool IsStandard(const base::char16* spec, const Component& scheme) {
return DoIsStandard(spec, scheme, &unused_scheme_type);
}
+bool IsReferrerScheme(const char* spec, const Component& scheme) {
+ InitReferrerSchemes();
+ SchemeType unused_scheme_type;
+ return DoIsInSchemes(spec, scheme, &unused_scheme_type, *referrer_schemes);
+}
+
bool FindAndCompareScheme(const char* str,
int str_len,
const char* compare,
diff --git a/url/url_util.h b/url/url_util.h
index 04a6ef4..a209a61 100644
--- a/url/url_util.h
+++ b/url/url_util.h
@@ -20,7 +20,7 @@ namespace url {
// Initialization is NOT required, it will be implicitly initialized when first
// used. However, this implicit initialization is NOT threadsafe. If you are
// using this library in a threaded environment and don't have a consistent
-// "first call" (an example might be calling AddStandardScheme with your special
+// "first call" (an example might be calling Add*Scheme with your special
// application-specific schemes) then you will want to call initialize before
// spawning any threads.
//
@@ -61,24 +61,33 @@ struct URL_EXPORT SchemeWithType {
// URI syntax" (https://tools.ietf.org/html/rfc3986#section-3).
//
// This function is not threadsafe and can not be called concurrently with any
-// other url_util function. It will assert if the list of standard schemes has
-// been locked (see LockStandardSchemes).
+// other url_util function. It will assert if the lists of schemes have
+// been locked (see LockSchemeRegistries).
URL_EXPORT void AddStandardScheme(const char* new_scheme,
SchemeType scheme_type);
-// Sets a flag to prevent future calls to AddStandardScheme from succeeding.
+// Adds an application-defined scheme to the internal list of schemes allowed
+// for referrers.
+//
+// This function is not threadsafe and can not be called concurrently with any
+// other url_util function. It will assert if the lists of schemes have
+// been locked (see LockSchemeRegistries).
+URL_EXPORT void AddReferrerScheme(const char* new_scheme,
+ SchemeType scheme_type);
+
+// Sets a flag to prevent future calls to Add*Scheme from succeeding.
//
// This is designed to help prevent errors for multithreaded applications.
-// Normal usage would be to call AddStandardScheme for your custom schemes at
-// the beginning of program initialization, and then LockStandardSchemes. This
-// prevents future callers from mistakenly calling AddStandardScheme when the
+// Normal usage would be to call Add*Scheme for your custom schemes at
+// the beginning of program initialization, and then LockSchemeRegistries. This
+// prevents future callers from mistakenly calling Add*Scheme when the
// program is running with multiple threads, where such usage would be
// dangerous.
//
-// We could have had AddStandardScheme use a lock instead, but that would add
+// We could have had Add*Scheme use a lock instead, but that would add
// some platform-specific dependencies we don't otherwise have now, and is
// overkill considering the normal usage is so simple.
-URL_EXPORT void LockStandardSchemes();
+URL_EXPORT void LockSchemeRegistries();
// Locates the scheme in the given string and places it into |found_scheme|,
// which may be NULL to indicate the caller does not care about the range.
@@ -112,6 +121,10 @@ inline bool FindAndCompareScheme(const base::string16& str,
URL_EXPORT bool IsStandard(const char* spec, const Component& scheme);
URL_EXPORT bool IsStandard(const base::char16* spec, const Component& scheme);
+// Returns true if the given scheme identified by |scheme| within |spec| is in
+// the list of allowed schemes for referrers (see AddReferrerScheme).
+URL_EXPORT bool IsReferrerScheme(const char* spec, const Component& scheme);
+
// Returns true and sets |type| to the SchemeType of the given scheme
// identified by |scheme| within |spec| if the scheme is in the list of known
// standard-format schemes (see AddStandardScheme).
diff --git a/url/url_util_unittest.cc b/url/url_util_unittest.cc
index 4143062..f0032c2 100644
--- a/url/url_util_unittest.cc
+++ b/url/url_util_unittest.cc
@@ -71,6 +71,21 @@ TEST(URLUtilTest, IsStandard) {
EXPECT_FALSE(IsStandard(kFooScheme, Component(0, strlen(kFooScheme))));
}
+TEST(URLUtilTest, IsReferrerScheme) {
+ const char kHTTPScheme[] = "http";
+ EXPECT_TRUE(IsReferrerScheme(kHTTPScheme, Component(0, strlen(kHTTPScheme))));
+
+ const char kFooScheme[] = "foo";
+ EXPECT_FALSE(IsReferrerScheme(kFooScheme, Component(0, strlen(kFooScheme))));
+}
+
+TEST(URLUtilTest, AddReferrerScheme) {
+ const char kFooScheme[] = "foo";
+ EXPECT_FALSE(IsReferrerScheme(kFooScheme, Component(0, strlen(kFooScheme))));
+ AddReferrerScheme(kFooScheme, url::SCHEME_WITHOUT_PORT);
+ EXPECT_TRUE(IsReferrerScheme(kFooScheme, Component(0, strlen(kFooScheme))));
+}
+
TEST(URLUtilTest, GetStandardSchemeType) {
url::SchemeType scheme_type;