summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/policy/policy_templates.json15
-rw-r--r--chrome/browser/browser_process_impl.cc21
-rw-r--r--chrome/browser/browser_process_impl.h6
-rw-r--r--chrome/browser/policy/config_dir_policy_provider_unittest.cc5
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store.cc3
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store_unittest.cc4
-rw-r--r--chrome/browser/policy/configuration_policy_provider_mac_unittest.cc5
-rw-r--r--chrome/browser/policy/configuration_policy_provider_win_unittest.cc5
-rw-r--r--chrome/browser/prefs/pref_member.cc24
-rw-r--r--chrome/browser/prefs/pref_member.h1
-rw-r--r--chrome/browser/prefs/pref_member_unittest.cc38
-rw-r--r--chrome/browser/prefs/pref_service.cc4
-rw-r--r--chrome/browser/prefs/pref_service.h3
-rw-r--r--chrome/common/pref_names.cc3
-rw-r--r--chrome/common/pref_names.h1
-rw-r--r--content/browser/child_process_security_policy.cc20
-rw-r--r--content/browser/child_process_security_policy.h18
-rw-r--r--content/browser/child_process_security_policy_unittest.cc33
-rw-r--r--content/browser/tab_contents/navigation_controller.cc18
19 files changed, 212 insertions, 15 deletions
diff --git a/chrome/app/policy/policy_templates.json b/chrome/app/policy/policy_templates.json
index 4311177d..d533e4e 100644
--- a/chrome/app/policy/policy_templates.json
+++ b/chrome/app/policy/policy_templates.json
@@ -94,7 +94,7 @@
# persistent IDs for all fields (but not for groups!) are needed. These are
# specified by the 'id' keys of each policy. NEVER CHANGE EXISTING IDs,
# because doing so would break the deployed wire format!
-# For your editing convenience: highest ID currently used: 84
+# For your editing convenience: highest ID currently used: 85
#
# Placeholders:
# The following placeholder strings are automatically substituted:
@@ -234,6 +234,19 @@
'desc': '''Disables use of the SPDY protocol in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>.''',
},
{
+ 'name': 'DisabledSchemes',
+ 'type': 'list',
+ 'supported_on': ['chrome.*:12-', 'chrome_os:0.11-'],
+ 'features': {'dynamic_refresh': 1},
+ 'example_value': ['file', 'mailto'],
+ 'id': 85,
+ 'caption': '''Disable URL protocol schemes''',
+ 'desc': '''Disables the listed protocol schemes in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>.
+
+ URLs using a scheme from this list will not load and can not be navigated to.''',
+ 'label': '''List of disabled protocol schemes''',
+ },
+ {
'name': 'JavascriptEnabled',
'type': 'main',
'supported_on': ['chrome.*:8-', 'chrome_os:0.11-'],
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index f45f30c..0f44325 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -63,6 +63,7 @@
#include "chrome/installer/util/google_update_constants.h"
#include "content/browser/browser_child_process_host.h"
#include "content/browser/browser_thread.h"
+#include "content/browser/child_process_security_policy.h"
#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/resource_dispatcher_host.h"
@@ -631,6 +632,8 @@ void BrowserProcessImpl::Observe(NotificationType type,
if (*pref == prefs::kDefaultBrowserSettingEnabled) {
if (local_state_->GetBoolean(prefs::kDefaultBrowserSettingEnabled))
ShellIntegration::SetAsDefaultBrowser();
+ } else if (*pref == prefs::kDisabledSchemes) {
+ ApplyDisabledSchemesPolicy();
}
} else {
NOTREACHED();
@@ -869,6 +872,13 @@ void BrowserProcessImpl::CreateLocalState() {
plugin_finder_disabled_pref_.Init(prefs::kDisablePluginFinder,
local_state_.get(), NULL);
plugin_finder_disabled_pref_.MoveToThread(BrowserThread::IO);
+
+ // Initialize the preference for the disabled schemes policy, and
+ // load the initial policy on startup.
+ local_state_->RegisterListPref(prefs::kDisabledSchemes);
+ disabled_schemes_pref_.Init(prefs::kDisabledSchemes, local_state_.get(),
+ this);
+ ApplyDisabledSchemesPolicy();
}
void BrowserProcessImpl::CreateIconManager() {
@@ -951,6 +961,17 @@ bool BrowserProcessImpl::IsSafeBrowsingDetectionServiceEnabled() {
#endif
}
+void BrowserProcessImpl::ApplyDisabledSchemesPolicy() {
+ std::set<std::string> schemes;
+ for (ListValue::const_iterator iter = (*disabled_schemes_pref_)->begin();
+ iter != (*disabled_schemes_pref_)->end(); ++iter) {
+ std::string scheme;
+ if ((*iter)->GetAsString(&scheme))
+ schemes.insert(scheme);
+ }
+ ChildProcessSecurityPolicy::GetInstance()->RegisterDisabledSchemes(schemes);
+}
+
// The BrowserProcess object must outlive the file thread so we use traits
// which don't do any management.
DISABLE_RUNNABLE_METHOD_REFCOUNT(BrowserProcessImpl);
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index 77dc71f..f0292c9 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -116,7 +116,6 @@ class BrowserProcessImpl : public BrowserProcess,
bool ShouldClearLocalState(FilePath* profile_path);
void CreateResourceDispatcherHost();
- void CreatePrefService();
void CreateMetricsService();
void CreateIOThread();
@@ -148,6 +147,8 @@ class BrowserProcessImpl : public BrowserProcess,
bool IsSafeBrowsingDetectionServiceEnabled();
+ void ApplyDisabledSchemesPolicy();
+
#if defined(IPC_MESSAGE_LOG_ENABLED)
void SetIPCLoggingEnabledForChildProcesses(bool enabled);
#endif
@@ -266,6 +267,9 @@ class BrowserProcessImpl : public BrowserProcess,
// Monitors the state of the 'DisablePluginFinder' policy.
BooleanPrefMember plugin_finder_disabled_pref_;
+ // Monitors the list of disabled schemes policy.
+ ListPrefMember disabled_schemes_pref_;
+
#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
base::RepeatingTimer<BrowserProcessImpl> autoupdate_timer_;
diff --git a/chrome/browser/policy/config_dir_policy_provider_unittest.cc b/chrome/browser/policy/config_dir_policy_provider_unittest.cc
index aa6354f..f6bbfc9 100644
--- a/chrome/browser/policy/config_dir_policy_provider_unittest.cc
+++ b/chrome/browser/policy/config_dir_policy_provider_unittest.cc
@@ -362,6 +362,9 @@ INSTANTIATE_TEST_CASE_P(
key::kBookmarkBarEnabled),
ValueTestParams::ForBooleanPolicy(
kPolicyEditBookmarksEnabled,
- key::kEditBookmarksEnabled)));
+ key::kEditBookmarksEnabled),
+ ValueTestParams::ForListPolicy(
+ kPolicyDisabledSchemes,
+ key::kDisabledSchemes)));
} // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc
index d73ac28..cc41521 100644
--- a/chrome/browser/policy/configuration_policy_pref_store.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store.cc
@@ -146,6 +146,8 @@ const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry
prefs::kNetworkPredictionEnabled },
{ Value::TYPE_BOOLEAN, kPolicyDisableSpdy,
prefs::kDisableSpdy },
+ { Value::TYPE_LIST, kPolicyDisabledSchemes,
+ prefs::kDisabledSchemes },
{ Value::TYPE_BOOLEAN, kPolicySafeBrowsingEnabled,
prefs::kSafeBrowsingEnabled },
{ Value::TYPE_BOOLEAN, kPolicyPasswordManagerEnabled,
@@ -857,6 +859,7 @@ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList() {
{ kPolicyDnsPrefetchingEnabled, Value::TYPE_BOOLEAN,
key::kDnsPrefetchingEnabled },
{ kPolicyDisableSpdy, Value::TYPE_BOOLEAN, key::kDisableSpdy },
+ { kPolicyDisabledSchemes, Value::TYPE_LIST, key::kDisabledSchemes },
{ kPolicySafeBrowsingEnabled, Value::TYPE_BOOLEAN,
key::kSafeBrowsingEnabled },
{ kPolicyMetricsReportingEnabled, Value::TYPE_BOOLEAN,
diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
index ad6b451..1aea222 100644
--- a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
@@ -82,7 +82,9 @@ INSTANTIATE_TEST_CASE_P(
TypeAndName(kPolicyDisabledPluginsExceptions,
prefs::kPluginsDisabledPluginsExceptions),
TypeAndName(kPolicyEnabledPlugins,
- prefs::kPluginsEnabledPlugins)));
+ prefs::kPluginsEnabledPlugins),
+ TypeAndName(kPolicyDisabledSchemes,
+ prefs::kDisabledSchemes)));
// Test cases for string-valued policy settings.
class ConfigurationPolicyPrefStoreStringTest
diff --git a/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc b/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc
index 0a76502..2284952 100644
--- a/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc
@@ -336,6 +336,9 @@ INSTANTIATE_TEST_CASE_P(
key::kEditBookmarksEnabled),
PolicyTestParams::ForBooleanPolicy(
kPolicyAllowFileSelectionDialogs,
- key::kAllowFileSelectionDialogs)));
+ key::kAllowFileSelectionDialogs),
+ PolicyTestParams::ForListPolicy(
+ kPolicyDisabledSchemes,
+ key::kDisabledSchemes)));
} // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
index facff3d..865a5ca 100644
--- a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
@@ -494,6 +494,9 @@ INSTANTIATE_TEST_CASE_P(
key::kEditBookmarksEnabled),
PolicyTestParams::ForBooleanPolicy(
kPolicyAllowFileSelectionDialogs,
- key::kAllowFileSelectionDialogs)));
+ key::kAllowFileSelectionDialogs),
+ PolicyTestParams::ForListPolicy(
+ kPolicyDisabledSchemes,
+ key::kDisabledSchemes)));
} // namespace policy
diff --git a/chrome/browser/prefs/pref_member.cc b/chrome/browser/prefs/pref_member.cc
index 2efeafc..90b369b 100644
--- a/chrome/browser/prefs/pref_member.cc
+++ b/chrome/browser/prefs/pref_member.cc
@@ -163,3 +163,27 @@ bool PrefMember<FilePath>::Internal::UpdateValueInternal(const Value& value)
return base::GetValueAsFilePath(value, &value_);
}
+template <>
+void PrefMember<ListValue*>::UpdatePref(ListValue*const& value) {
+ // prefs takes ownership of the value passed, so make a copy.
+ prefs()->SetList(pref_name().c_str(), value->DeepCopy());
+}
+
+template <>
+bool PrefMember<ListValue*>::Internal::UpdateValueInternal(const Value& value)
+ const {
+ // Verify the type before doing the DeepCopy to avoid leaking the copy.
+ if (value.GetType() != Value::TYPE_LIST)
+ return false;
+
+ // ListPrefMember keeps a copy of the ListValue and of its contents.
+ // GetAsList() assigns its |this| (the DeepCopy) to |value_|.
+ delete value_;
+ return value.DeepCopy()->GetAsList(&value_);
+}
+
+template <>
+PrefMember<ListValue*>::Internal::~Internal() {
+ delete value_;
+}
+
diff --git a/chrome/browser/prefs/pref_member.h b/chrome/browser/prefs/pref_member.h
index 5e58a39..5fdd91d 100644
--- a/chrome/browser/prefs/pref_member.h
+++ b/chrome/browser/prefs/pref_member.h
@@ -244,5 +244,6 @@ typedef PrefMember<int> IntegerPrefMember;
typedef PrefMember<double> DoublePrefMember;
typedef PrefMember<std::string> StringPrefMember;
typedef PrefMember<FilePath> FilePathPrefMember;
+typedef PrefMember<ListValue*> ListPrefMember;
#endif // CHROME_BROWSER_PREFS_PREF_MEMBER_H_
diff --git a/chrome/browser/prefs/pref_member_unittest.cc b/chrome/browser/prefs/pref_member_unittest.cc
index 9fca66b..b8079dd 100644
--- a/chrome/browser/prefs/pref_member_unittest.cc
+++ b/chrome/browser/prefs/pref_member_unittest.cc
@@ -19,12 +19,14 @@ const char kBoolPref[] = "bool";
const char kIntPref[] = "int";
const char kDoublePref[] = "double";
const char kStringPref[] = "string";
+const char kListPref[] = "list";
void RegisterTestPrefs(PrefService* prefs) {
prefs->RegisterBooleanPref(kBoolPref, false);
prefs->RegisterIntegerPref(kIntPref, 0);
prefs->RegisterDoublePref(kDoublePref, 0.0);
prefs->RegisterStringPref(kStringPref, "default");
+ prefs->RegisterListPref(kListPref);
}
class GetPrefValueCallback
@@ -179,6 +181,42 @@ TEST(PrefMemberTest, BasicGetAndSet) {
EXPECT_EQ("bar", prefs.GetString(kStringPref));
EXPECT_EQ("bar", string.GetValue());
EXPECT_EQ("bar", *string);
+
+ // Test list
+ ListPrefMember list;
+ list.Init(kListPref, &prefs, NULL);
+
+ // Check the defaults
+ const ListValue* list_value = prefs.GetList(kListPref);
+ ASSERT_TRUE(list_value != NULL);
+ EXPECT_EQ(0u, list_value->GetSize());
+ EXPECT_TRUE(list_value->empty());
+ ASSERT_TRUE(list.GetValue() != NULL);
+ EXPECT_EQ(0u, list.GetValue()->GetSize());
+ EXPECT_TRUE(list.GetValue()->empty());
+ ASSERT_TRUE(*list != NULL);
+ EXPECT_EQ(0u, (*list)->GetSize());
+ EXPECT_TRUE((*list)->empty());
+
+ // Try changing through the member variable.
+ scoped_ptr<ListValue> list_value_numbers(new ListValue());
+ list_value_numbers->Append(new StringValue("one"));
+ list_value_numbers->Append(new StringValue("two"));
+ list_value_numbers->Append(new StringValue("three"));
+ list.SetValue(list_value_numbers.get());
+ EXPECT_TRUE(list_value_numbers->Equals(list.GetValue()));
+ EXPECT_TRUE(list_value_numbers->Equals(prefs.GetList(kListPref)));
+ EXPECT_TRUE(list_value_numbers->Equals(*list));
+
+ // Try changing back through the pref.
+ ListValue* list_value_ints = new ListValue();
+ list_value_ints->Append(new FundamentalValue(1));
+ list_value_ints->Append(new FundamentalValue(2));
+ list_value_ints->Append(new FundamentalValue(3));
+ prefs.SetList(kListPref, list_value_ints); // takes ownership
+ EXPECT_TRUE(list_value_ints->Equals(list.GetValue()));
+ EXPECT_TRUE(list_value_ints->Equals(prefs.GetList(kListPref)));
+ EXPECT_TRUE(list_value_ints->Equals(*list));
}
TEST(PrefMemberTest, TwoPrefs) {
diff --git a/chrome/browser/prefs/pref_service.cc b/chrome/browser/prefs/pref_service.cc
index abefe07..3beff39 100644
--- a/chrome/browser/prefs/pref_service.cc
+++ b/chrome/browser/prefs/pref_service.cc
@@ -521,6 +521,10 @@ void PrefService::SetFilePath(const char* path, const FilePath& value) {
SetUserPrefValue(path, base::CreateFilePathValue(value));
}
+void PrefService::SetList(const char* path, ListValue* value) {
+ SetUserPrefValue(path, value);
+}
+
void PrefService::SetInt64(const char* path, int64 value) {
SetUserPrefValue(path, Value::CreateStringValue(base::Int64ToString(value)));
}
diff --git a/chrome/browser/prefs/pref_service.h b/chrome/browser/prefs/pref_service.h
index 690b8c2..200693d 100644
--- a/chrome/browser/prefs/pref_service.h
+++ b/chrome/browser/prefs/pref_service.h
@@ -203,6 +203,9 @@ class PrefService : public base::NonThreadSafe {
void SetDouble(const char* path, double value);
void SetString(const char* path, const std::string& value);
void SetFilePath(const char* path, const FilePath& value);
+ // SetList() takes ownership of |value|. Pass a copy of the ListValue to
+ // keep ownership of the original list, if necessary.
+ void SetList(const char* path, ListValue* value);
// Int64 helper methods that actually store the given value as a string.
// Note that if obtaining the named value via GetDictionary or GetList, the
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index cd65e1d..067fcab 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -246,6 +246,9 @@ const char kDnsPrefetchingHostReferralList[] =
// Disables the SPDY protocol.
const char kDisableSpdy[] = "spdy.disabled";
+// Disables the listed protocol schemes.
+const char kDisabledSchemes[] = "protocol.disabled_schemes";
+
// Boolean pref indicating whether the instant confirm dialog has been shown.
const char kInstantConfirmDialogShown[] = "instant.confirm_dialog_shown";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index fd714ba..e00df1e 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -85,6 +85,7 @@ extern const char kDnsPrefetchingStartupList[];
extern const char kDnsHostReferralList[]; // OBSOLETE
extern const char kDnsPrefetchingHostReferralList[];
extern const char kDisableSpdy[];
+extern const char kDisabledSchemes[];
extern const char kInstantConfirmDialogShown[];
extern const char kInstantEnabled[];
extern const char kInstantEnabledOnce[];
diff --git a/content/browser/child_process_security_policy.cc b/content/browser/child_process_security_policy.cc
index 1f4e9ce..cda7a06 100644
--- a/content/browser/child_process_security_policy.cc
+++ b/content/browser/child_process_security_policy.cc
@@ -136,7 +136,7 @@ ChildProcessSecurityPolicy::ChildProcessSecurityPolicy() {
RegisterWebSafeScheme(chrome::kBlobScheme);
RegisterWebSafeScheme(chrome::kFileSystemScheme);
- // We know about the following psuedo schemes and treat them specially.
+ // We know about the following pseudo schemes and treat them specially.
RegisterPseudoScheme(chrome::kAboutScheme);
RegisterPseudoScheme(chrome::kJavaScriptScheme);
RegisterPseudoScheme(chrome::kViewSourceScheme);
@@ -178,7 +178,7 @@ void ChildProcessSecurityPolicy::RegisterWebSafeScheme(
const std::string& scheme) {
base::AutoLock lock(lock_);
DCHECK(web_safe_schemes_.count(scheme) == 0) << "Add schemes at most once.";
- DCHECK(pseudo_schemes_.count(scheme) == 0) << "Web-safe implies not psuedo.";
+ DCHECK(pseudo_schemes_.count(scheme) == 0) << "Web-safe implies not pseudo.";
web_safe_schemes_.insert(scheme);
}
@@ -194,7 +194,7 @@ void ChildProcessSecurityPolicy::RegisterPseudoScheme(
base::AutoLock lock(lock_);
DCHECK(pseudo_schemes_.count(scheme) == 0) << "Add schemes at most once.";
DCHECK(web_safe_schemes_.count(scheme) == 0) <<
- "Psuedo implies not web-safe.";
+ "Pseudo implies not web-safe.";
pseudo_schemes_.insert(scheme);
}
@@ -205,6 +205,17 @@ bool ChildProcessSecurityPolicy::IsPseudoScheme(const std::string& scheme) {
return (pseudo_schemes_.find(scheme) != pseudo_schemes_.end());
}
+void ChildProcessSecurityPolicy::RegisterDisabledSchemes(
+ const std::set<std::string>& schemes) {
+ base::AutoLock lock(lock_);
+ disabled_schemes_ = schemes;
+}
+
+bool ChildProcessSecurityPolicy::IsDisabledScheme(const std::string& scheme) {
+ base::AutoLock lock(lock_);
+ return disabled_schemes_.find(scheme) != disabled_schemes_.end();
+}
+
void ChildProcessSecurityPolicy::GrantRequestURL(
int child_id, const GURL& url) {
@@ -334,6 +345,9 @@ bool ChildProcessSecurityPolicy::CanRequestURL(
if (!url.is_valid())
return false; // Can't request invalid URLs.
+ if (IsDisabledScheme(url.scheme()))
+ return false; // The scheme is disabled by policy.
+
if (IsWebSafeScheme(url.scheme()))
return true; // The scheme has been white-listed for every child process.
diff --git a/content/browser/child_process_security_policy.h b/content/browser/child_process_security_policy.h
index ec540f1..da8e924 100644
--- a/content/browser/child_process_security_policy.h
+++ b/content/browser/child_process_security_policy.h
@@ -20,8 +20,8 @@ class FilePath;
class GURL;
// The ChildProcessSecurityPolicy class is used to grant and revoke security
-// capabilities for child porcesses. For example, it restricts whether a child
-// process is permmitted to loaded file:// URLs based on whether the process
+// capabilities for child processes. For example, it restricts whether a child
+// process is permitted to load file:// URLs based on whether the process
// has ever been commanded to load file:// URLs by the browser.
//
// ChildProcessSecurityPolicy is a singleton that may be used on any thread.
@@ -53,6 +53,15 @@ class ChildProcessSecurityPolicy {
// Returns true iff |scheme| has been registered as pseudo scheme.
bool IsPseudoScheme(const std::string& scheme);
+ // Sets the list of disabled schemes.
+ // URLs using these schemes won't be loaded at all. The previous list of
+ // schemes is overwritten. An empty |schemes| disables this feature.
+ // Schemes listed as disabled take precedence over Web-safe schemes.
+ void RegisterDisabledSchemes(const std::set<std::string>& schemes);
+
+ // Returns true iff |scheme| is listed as a disabled scheme.
+ bool IsDisabledScheme(const std::string& scheme);
+
// Upon creation, child processes should register themselves by calling this
// this method exactly once.
void Add(int child_id);
@@ -160,6 +169,11 @@ class ChildProcessSecurityPolicy {
// protected by |lock_|.
SchemeSet pseudo_schemes_;
+ // These schemes are disabled by policy, and child processes are always
+ // denied permission to request them. This overrides |web_safe_schemes_|.
+ // This set is protected by |lock_|.
+ SchemeSet disabled_schemes_;
+
// This map holds a SecurityState for each child process. The key for the
// map is the ID of the ChildProcessHost. The SecurityState objects are
// owned by this object and are protected by |lock_|. References to them must
diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc
index e20178e..53799b7 100644
--- a/content/browser/child_process_security_policy_unittest.cc
+++ b/content/browser/child_process_security_policy_unittest.cc
@@ -52,9 +52,25 @@ TEST_F(ChildProcessSecurityPolicyTest, IsPseudoSchemeTest) {
EXPECT_TRUE(p->IsPseudoScheme(chrome::kJavaScriptScheme));
EXPECT_TRUE(p->IsPseudoScheme(chrome::kViewSourceScheme));
- EXPECT_FALSE(p->IsPseudoScheme("registered-psuedo-scheme"));
- p->RegisterPseudoScheme("registered-psuedo-scheme");
- EXPECT_TRUE(p->IsPseudoScheme("registered-psuedo-scheme"));
+ EXPECT_FALSE(p->IsPseudoScheme("registered-pseudo-scheme"));
+ p->RegisterPseudoScheme("registered-pseudo-scheme");
+ EXPECT_TRUE(p->IsPseudoScheme("registered-pseudo-scheme"));
+}
+
+TEST_F(ChildProcessSecurityPolicyTest, IsDisabledSchemeTest) {
+ ChildProcessSecurityPolicy* p = ChildProcessSecurityPolicy::GetInstance();
+
+ EXPECT_FALSE(p->IsDisabledScheme("evil-scheme"));
+ std::set<std::string> disabled_set;
+ disabled_set.insert("evil-scheme");
+ p->RegisterDisabledSchemes(disabled_set);
+ EXPECT_TRUE(p->IsDisabledScheme("evil-scheme"));
+ EXPECT_FALSE(p->IsDisabledScheme("good-scheme"));
+
+ disabled_set.clear();
+ p->RegisterDisabledSchemes(disabled_set);
+ EXPECT_FALSE(p->IsDisabledScheme("evil-scheme"));
+ EXPECT_FALSE(p->IsDisabledScheme("good-scheme"));
}
TEST_F(ChildProcessSecurityPolicyTest, StandardSchemesTest) {
@@ -161,6 +177,17 @@ TEST_F(ChildProcessSecurityPolicyTest, CanServiceCommandsTest) {
p->GrantRequestURL(kRendererID, GURL("file:///etc/passwd"));
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("evil-scheme:/path")));
+ std::set<std::string> disabled_set;
+ disabled_set.insert("evil-scheme");
+ p->RegisterDisabledSchemes(disabled_set);
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("http://www.google.com")));
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("evil-scheme:/path")));
+ disabled_set.clear();
+ p->RegisterDisabledSchemes(disabled_set);
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("http://www.google.com")));
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("evil-scheme:/path")));
+
// We should forget our state if we repeat a renderer id.
p->Remove(kRendererID);
p->Add(kRendererID);
diff --git a/content/browser/tab_contents/navigation_controller.cc b/content/browser/tab_contents/navigation_controller.cc
index 5bdbd23..310e1cf 100644
--- a/content/browser/tab_contents/navigation_controller.cc
+++ b/content/browser/tab_contents/navigation_controller.cc
@@ -17,6 +17,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
+#include "content/browser/child_process_security_policy.h"
#include "content/browser/in_process_webkit/session_storage_namespace.h"
#include "content/browser/site_instance.h"
#include "content/browser/tab_contents/interstitial_page.h"
@@ -256,10 +257,25 @@ NavigationEntry* NavigationController::GetEntryWithPageID(
}
void NavigationController::LoadEntry(NavigationEntry* entry) {
+ // Don't navigate to URLs disabled by policy. This prevents showing the URL
+ // on the Omnibar when it is also going to be blocked by
+ // ChildProcessSecurityPolicy::CanRequestURL.
+ ChildProcessSecurityPolicy *policy =
+ ChildProcessSecurityPolicy::GetInstance();
+ if (policy->IsDisabledScheme(entry->url().scheme()) ||
+ policy->IsDisabledScheme(entry->virtual_url().scheme())) {
+ VLOG(1) << "URL not loaded because the scheme is blocked by policy: "
+ << entry->url();
+ delete entry;
+ return;
+ }
+
// Handle non-navigational URLs that popup dialogs and such, these should not
// actually navigate.
- if (HandleNonNavigationAboutURL(entry->url()))
+ if (HandleNonNavigationAboutURL(entry->url())) {
+ delete entry;
return;
+ }
// When navigating to a new page, we don't know for sure if we will actually
// end up leaving the current page. The new page load could for example