summaryrefslogtreecommitdiff
path: root/chromium/components/content_settings
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/content_settings')
-rw-r--r--chromium/components/content_settings/android/BUILD.gn25
-rw-r--r--chromium/components/content_settings/android/DEPS6
-rw-r--r--chromium/components/content_settings/android/cookie_controls_bridge.cc106
-rw-r--r--chromium/components/content_settings/android/cookie_controls_bridge.h59
-rw-r--r--chromium/components/content_settings/android/java/src/org/chromium/components/content_settings/CookieControlsBridge.java86
-rw-r--r--chromium/components/content_settings/android/java_templates/PrefNames.java.tmpl14
-rw-r--r--chromium/components/content_settings/browser/BUILD.gn13
-rw-r--r--chromium/components/content_settings/browser/content_settings_usages_state.cc78
-rw-r--r--chromium/components/content_settings/browser/content_settings_usages_state.h23
-rw-r--r--chromium/components/content_settings/browser/tab_specific_content_settings.cc561
-rw-r--r--chromium/components/content_settings/browser/tab_specific_content_settings.h255
-rw-r--r--chromium/components/content_settings/browser/tab_specific_content_settings_unittest.cc259
-rw-r--r--chromium/components/content_settings/browser/test_tab_specific_content_settings_delegate.cc63
-rw-r--r--chromium/components/content_settings/browser/test_tab_specific_content_settings_delegate.h47
-rw-r--r--chromium/components/content_settings/browser/ui/BUILD.gn21
-rw-r--r--chromium/components/content_settings/browser/ui/cookie_controls_controller.cc161
-rw-r--r--chromium/components/content_settings/browser/ui/cookie_controls_controller.h106
-rw-r--r--chromium/components/content_settings/browser/ui/cookie_controls_view.h25
-rw-r--r--chromium/components/content_settings/core/browser/BUILD.gn1
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_policy_provider.cc60
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_policy_provider.h7
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_pref.cc1
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_provider.cc14
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_provider.h10
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_registry.cc2
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_rule.cc10
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_rule.h10
-rw-r--r--chromium/components/content_settings/core/browser/cookie_settings.cc15
-rw-r--r--chromium/components/content_settings/core/browser/cookie_settings_unittest.cc42
-rw-r--r--chromium/components/content_settings/core/browser/host_content_settings_map.cc24
-rw-r--r--chromium/components/content_settings/core/browser/host_content_settings_map.h5
-rw-r--r--chromium/components/content_settings/core/browser/uma_util.h1
-rw-r--r--chromium/components/content_settings/core/common/content_settings.mojom2
-rw-r--r--chromium/components/content_settings/core/common/content_settings_mojom_traits.cc2
-rw-r--r--chromium/components/content_settings/core/common/content_settings_mojom_traits.h4
-rw-r--r--chromium/components/content_settings/core/common/content_settings_pattern.cc4
-rw-r--r--chromium/components/content_settings/core/common/content_settings_pattern.h8
-rw-r--r--chromium/components/content_settings/core/common/content_settings_pattern_unittest.cc19
-rw-r--r--chromium/components/content_settings/core/common/features.cc7
-rw-r--r--chromium/components/content_settings/core/common/features.h6
-rw-r--r--chromium/components/content_settings/core/common/pref_names.h1
-rw-r--r--chromium/components/content_settings/renderer/content_settings_agent_impl.cc25
-rw-r--r--chromium/components/content_settings/renderer/content_settings_agent_impl.h3
-rw-r--r--chromium/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc3
44 files changed, 1649 insertions, 545 deletions
diff --git a/chromium/components/content_settings/android/BUILD.gn b/chromium/components/content_settings/android/BUILD.gn
index 05939eea464..1c5229bc235 100644
--- a/chromium/components/content_settings/android/BUILD.gn
+++ b/chromium/components/content_settings/android/BUILD.gn
@@ -5,28 +5,43 @@
import("//build/config/android/rules.gni")
generate_jni("content_settings_jni_headers") {
- sources = [ "java/src/org/chromium/components/content_settings/ContentSettingsFeatureList.java" ]
+ sources = [
+ "java/src/org/chromium/components/content_settings/ContentSettingsFeatureList.java",
+ "java/src/org/chromium/components/content_settings/CookieControlsBridge.java",
+ ]
}
android_library("java") {
sources = [
"java/src/org/chromium/components/content_settings/ContentSettingsFeatureList.java",
+ "java/src/org/chromium/components/content_settings/CookieControlsBridge.java",
"java/src/org/chromium/components/content_settings/CookieControlsObserver.java",
]
deps = [
":content_settings_enums_java",
"//base:base_java",
"//base:jni_java",
+ "//components/embedder_support/android:browser_context_java",
+ "//content/public/android:content_java",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
source_set("android") {
- sources = [ "content_settings_feature_list.cc" ]
+ sources = [
+ "content_settings_feature_list.cc",
+ "cookie_controls_bridge.cc",
+ "cookie_controls_bridge.h",
+ ]
deps = [
":content_settings_jni_headers",
"//base",
+ "//components/content_settings/browser/ui",
+ "//components/content_settings/core/browser",
"//components/content_settings/core/common",
+ "//components/embedder_support/android:browser_context",
+ "//components/permissions",
+ "//content/public/browser",
]
}
@@ -45,3 +60,9 @@ java_cpp_enum("content_settings_enums_javagen") {
]
visibility = [ ":*" ] # Depend on through :content_settings_enums_java
}
+
+java_cpp_strings("java_pref_names_srcjar") {
+ sources = [ "//components/content_settings/core/common/pref_names.cc" ]
+
+ template = "java_templates/PrefNames.java.tmpl"
+}
diff --git a/chromium/components/content_settings/android/DEPS b/chromium/components/content_settings/android/DEPS
new file mode 100644
index 00000000000..d722cb7774c
--- /dev/null
+++ b/chromium/components/content_settings/android/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "+components/embedder_support/android",
+ "+components/permissions",
+ "+content/public/android",
+ "+content/public/browser",
+]
diff --git a/chromium/components/content_settings/android/cookie_controls_bridge.cc b/chromium/components/content_settings/android/cookie_controls_bridge.cc
new file mode 100644
index 00000000000..6c243e8e07e
--- /dev/null
+++ b/chromium/components/content_settings/android/cookie_controls_bridge.cc
@@ -0,0 +1,106 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/content_settings/android/cookie_controls_bridge.h"
+
+#include <memory>
+
+#include "components/content_settings/android/content_settings_jni_headers/CookieControlsBridge_jni.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
+#include "components/embedder_support/android/browser_context/browser_context_handle.h"
+#include "components/permissions/permissions_client.h"
+#include "content/public/browser/browser_context.h"
+
+namespace content_settings {
+
+using base::android::JavaParamRef;
+
+CookieControlsBridge::CookieControlsBridge(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jobject>& jweb_contents_android,
+ const base::android::JavaParamRef<jobject>&
+ joriginal_browser_context_handle)
+ : jobject_(obj) {
+ content::WebContents* web_contents =
+ content::WebContents::FromJavaWebContents(jweb_contents_android);
+ content::BrowserContext* original_context =
+ browser_context::BrowserContextFromJavaHandle(
+ joriginal_browser_context_handle);
+ auto* permissions_client = permissions::PermissionsClient::Get();
+ controller_ = std::make_unique<CookieControlsController>(
+ permissions_client->GetCookieSettings(web_contents->GetBrowserContext()),
+ original_context ? permissions_client->GetCookieSettings(original_context)
+ : nullptr);
+ observer_.Add(controller_.get());
+ controller_->Update(web_contents);
+}
+
+void CookieControlsBridge::OnStatusChanged(
+ CookieControlsStatus new_status,
+ CookieControlsEnforcement new_enforcement,
+ int blocked_cookies) {
+ if (status_ != new_status || enforcement_ != new_enforcement) {
+ status_ = new_status;
+ enforcement_ = new_enforcement;
+ JNIEnv* env = base::android::AttachCurrentThread();
+ // Only call status callback if status has changed
+ Java_CookieControlsBridge_onCookieBlockingStatusChanged(
+ env, jobject_, static_cast<int>(status_),
+ static_cast<int>(enforcement_));
+ }
+
+ OnBlockedCookiesCountChanged(blocked_cookies);
+}
+
+void CookieControlsBridge::OnBlockedCookiesCountChanged(int blocked_cookies) {
+ // The blocked cookie count changes quite frequently, so avoid unnecessary
+ // UI updates if possible.
+ if (blocked_cookies_ == blocked_cookies)
+ return;
+
+ blocked_cookies_ = blocked_cookies;
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_CookieControlsBridge_onBlockedCookiesCountChanged(
+ env, jobject_, blocked_cookies_.value_or(0));
+}
+
+void CookieControlsBridge::SetThirdPartyCookieBlockingEnabledForSite(
+ JNIEnv* env,
+ bool block_cookies) {
+ controller_->OnCookieBlockingEnabledForSite(block_cookies);
+}
+
+void CookieControlsBridge::OnUiClosing(JNIEnv* env) {
+ controller_->OnUiClosing();
+}
+
+CookieControlsBridge::~CookieControlsBridge() = default;
+
+void CookieControlsBridge::Destroy(JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ delete this;
+}
+
+jboolean JNI_CookieControlsBridge_IsCookieControlsEnabled(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& jbrowser_context_handle) {
+ content::BrowserContext* context =
+ browser_context::BrowserContextFromJavaHandle(jbrowser_context_handle);
+ return permissions::PermissionsClient::Get()
+ ->GetCookieSettings(context)
+ ->IsCookieControlsEnabled();
+}
+
+static jlong JNI_CookieControlsBridge_Init(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jobject>& jweb_contents_android,
+ const base::android::JavaParamRef<jobject>&
+ joriginal_browser_context_handle) {
+ return reinterpret_cast<intptr_t>(new CookieControlsBridge(
+ env, obj, jweb_contents_android, joriginal_browser_context_handle));
+}
+
+} // namespace content_settings
diff --git a/chromium/components/content_settings/android/cookie_controls_bridge.h b/chromium/components/content_settings/android/cookie_controls_bridge.h
new file mode 100644
index 00000000000..f22a0905bd6
--- /dev/null
+++ b/chromium/components/content_settings/android/cookie_controls_bridge.h
@@ -0,0 +1,59 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CONTENT_SETTINGS_ANDROID_COOKIE_CONTROLS_BRIDGE_H_
+#define COMPONENTS_CONTENT_SETTINGS_ANDROID_COOKIE_CONTROLS_BRIDGE_H_
+
+#include "base/android/jni_weak_ref.h"
+#include "base/optional.h"
+#include "components/content_settings/browser/ui/cookie_controls_controller.h"
+#include "components/content_settings/browser/ui/cookie_controls_view.h"
+#include "components/content_settings/core/common/cookie_controls_status.h"
+
+namespace content_settings {
+
+// Communicates between CookieControlsController (C++ backend) and PageInfoView
+// (Java UI).
+class CookieControlsBridge : public CookieControlsView {
+ public:
+ // Creates a CookeControlsBridge for interaction with a
+ // CookieControlsController.
+ CookieControlsBridge(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jobject>& jweb_contents_android,
+ const base::android::JavaParamRef<jobject>&
+ joriginal_browser_context_handle);
+
+ ~CookieControlsBridge() override;
+
+ // Called by the Java counterpart when it is getting garbage collected.
+ void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+
+ void SetThirdPartyCookieBlockingEnabledForSite(JNIEnv* env,
+ bool block_cookies);
+
+ void OnUiClosing(JNIEnv* env);
+
+ // CookieControlsView:
+ void OnStatusChanged(CookieControlsStatus status,
+ CookieControlsEnforcement enforcement,
+ int blocked_cookies) override;
+ void OnBlockedCookiesCountChanged(int blocked_cookies) override;
+
+ private:
+ base::android::ScopedJavaGlobalRef<jobject> jobject_;
+ CookieControlsStatus status_ = CookieControlsStatus::kUninitialized;
+ CookieControlsEnforcement enforcement_ =
+ CookieControlsEnforcement::kNoEnforcement;
+ base::Optional<int> blocked_cookies_;
+ std::unique_ptr<CookieControlsController> controller_;
+ ScopedObserver<CookieControlsController, CookieControlsView> observer_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(CookieControlsBridge);
+};
+
+} // namespace content_settings
+
+#endif // COMPONENTS_CONTENT_SETTINGS_ANDROID_COOKIE_CONTROLS_BRIDGE_H_
diff --git a/chromium/components/content_settings/android/java/src/org/chromium/components/content_settings/CookieControlsBridge.java b/chromium/components/content_settings/android/java/src/org/chromium/components/content_settings/CookieControlsBridge.java
new file mode 100644
index 00000000000..2e23b96ba65
--- /dev/null
+++ b/chromium/components/content_settings/android/java/src/org/chromium/components/content_settings/CookieControlsBridge.java
@@ -0,0 +1,86 @@
+// Copyright 2019 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.
+
+package org.chromium.components.content_settings;
+
+import androidx.annotation.Nullable;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
+import org.chromium.components.embedder_support.browser_context.BrowserContextHandle;
+import org.chromium.content_public.browser.WebContents;
+
+/**
+ * Communicates between CookieControlsController (C++ backend) and PageInfoView (Java UI).
+ */
+@JNINamespace("content_settings")
+public class CookieControlsBridge {
+ private long mNativeCookieControlsBridge;
+ private CookieControlsObserver mObserver;
+
+ /**
+ * Initializes a CookieControlsBridge instance.
+ * @param observer An observer to call with updates from the cookie controller.
+ * @param webContents The WebContents instance to observe.
+ * @param originalBrowserContext The "original" browser context. In Chrome, this corresponds to
+ * the regular profile when webContents is incognito.
+ */
+ public CookieControlsBridge(CookieControlsObserver observer, WebContents webContents,
+ @Nullable BrowserContextHandle originalBrowserContext) {
+ mObserver = observer;
+ mNativeCookieControlsBridge = CookieControlsBridgeJni.get().init(
+ CookieControlsBridge.this, webContents, originalBrowserContext);
+ }
+
+ public void setThirdPartyCookieBlockingEnabledForSite(boolean blockCookies) {
+ if (mNativeCookieControlsBridge != 0) {
+ CookieControlsBridgeJni.get().setThirdPartyCookieBlockingEnabledForSite(
+ mNativeCookieControlsBridge, blockCookies);
+ }
+ }
+
+ public void onUiClosing() {
+ if (mNativeCookieControlsBridge != 0) {
+ CookieControlsBridgeJni.get().onUiClosing(mNativeCookieControlsBridge);
+ }
+ }
+
+ /**
+ * Destroys the native counterpart of this class.
+ */
+ public void destroy() {
+ if (mNativeCookieControlsBridge != 0) {
+ CookieControlsBridgeJni.get().destroy(
+ mNativeCookieControlsBridge, CookieControlsBridge.this);
+ mNativeCookieControlsBridge = 0;
+ }
+ }
+
+ public static boolean isCookieControlsEnabled(BrowserContextHandle handle) {
+ return CookieControlsBridgeJni.get().isCookieControlsEnabled(handle);
+ }
+
+ @CalledByNative
+ private void onCookieBlockingStatusChanged(
+ @CookieControlsStatus int status, @CookieControlsEnforcement int enforcement) {
+ mObserver.onCookieBlockingStatusChanged(status, enforcement);
+ }
+
+ @CalledByNative
+ private void onBlockedCookiesCountChanged(int blockedCookies) {
+ mObserver.onBlockedCookiesCountChanged(blockedCookies);
+ }
+
+ @NativeMethods
+ interface Natives {
+ long init(CookieControlsBridge caller, WebContents webContents,
+ BrowserContextHandle originalContextHandle);
+ void destroy(long nativeCookieControlsBridge, CookieControlsBridge caller);
+ void setThirdPartyCookieBlockingEnabledForSite(
+ long nativeCookieControlsBridge, boolean blockCookies);
+ void onUiClosing(long nativeCookieControlsBridge);
+ boolean isCookieControlsEnabled(BrowserContextHandle browserContextHandle);
+ }
+}
diff --git a/chromium/components/content_settings/android/java_templates/PrefNames.java.tmpl b/chromium/components/content_settings/android/java_templates/PrefNames.java.tmpl
new file mode 100644
index 00000000000..0fc897821bb
--- /dev/null
+++ b/chromium/components/content_settings/android/java_templates/PrefNames.java.tmpl
@@ -0,0 +1,14 @@
+// Copyright 2020 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.
+
+package org.chromium.components.content_settings;
+
+/** Contains content settings related preference names (keys). */
+public final class PrefNames {{
+
+{NATIVE_STRINGS}
+
+ // Prevents instantiation.
+ private PrefNames() {{}}
+}}
diff --git a/chromium/components/content_settings/browser/BUILD.gn b/chromium/components/content_settings/browser/BUILD.gn
index 8377ccc4031..a4168a97483 100644
--- a/chromium/components/content_settings/browser/BUILD.gn
+++ b/chromium/components/content_settings/browser/BUILD.gn
@@ -26,11 +26,24 @@ source_set("browser") {
]
}
+source_set("test_support") {
+ testonly = true
+ sources = [
+ "test_tab_specific_content_settings_delegate.cc",
+ "test_tab_specific_content_settings_delegate.h",
+ ]
+ deps = [
+ ":browser",
+ "//content/public/browser",
+ ]
+}
+
source_set("unit_tests") {
testonly = true
sources = [ "tab_specific_content_settings_unittest.cc" ]
deps = [
":browser",
+ ":test_support",
"//base",
"//components/content_settings/core/browser",
"//components/security_state/core",
diff --git a/chromium/components/content_settings/browser/content_settings_usages_state.cc b/chromium/components/content_settings/browser/content_settings_usages_state.cc
index b65036db080..63e75f1af13 100644
--- a/chromium/components/content_settings/browser/content_settings_usages_state.cc
+++ b/chromium/components/content_settings/browser/content_settings_usages_state.cc
@@ -11,9 +11,10 @@
#include "components/url_formatter/url_formatter.h"
ContentSettingsUsagesState::ContentSettingsUsagesState(
- HostContentSettingsMap* host_content_settings_map,
- ContentSettingsType type)
- : host_content_settings_map_(host_content_settings_map), type_(type) {}
+ content_settings::TabSpecificContentSettings::Delegate* delegate_,
+ ContentSettingsType type,
+ const GURL& embedder_url)
+ : delegate_(delegate_), type_(type), embedder_url_(embedder_url) {}
ContentSettingsUsagesState::~ContentSettingsUsagesState() {}
@@ -23,64 +24,67 @@ void ContentSettingsUsagesState::OnPermissionSet(const GURL& requesting_origin,
allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
}
-void ContentSettingsUsagesState::DidNavigate(const GURL& url,
- const GURL& previous_url) {
- embedder_url_ = url;
- if (state_map_.empty())
- return;
- if (previous_url.GetOrigin() != url.GetOrigin()) {
- state_map_.clear();
- return;
- }
- // We're in the same origin, check if there's any icon to be displayed.
- unsigned int tab_state_flags = 0;
- GetDetailedInfo(nullptr, &tab_state_flags);
- if (!(tab_state_flags & TABSTATE_HAS_ANY_ICON))
- state_map_.clear();
-}
-
-void ContentSettingsUsagesState::ClearStateMap() {
- state_map_.clear();
-}
-
void ContentSettingsUsagesState::GetDetailedInfo(
FormattedHostsPerState* formatted_hosts_per_state,
unsigned int* tab_state_flags) const {
DCHECK(tab_state_flags);
DCHECK(embedder_url_.is_valid());
+ // This logic is used only for |ContentSettingsType::GEOLOCATION| and
+ // |ContentSettingsType::MIDI_SYSEX|.
+ DCHECK(type_ == ContentSettingsType::GEOLOCATION ||
+ type_ == ContentSettingsType::MIDI_SYSEX);
ContentSetting default_setting =
- host_content_settings_map_->GetDefaultContentSetting(type_, nullptr);
+ delegate_->GetSettingsMap()->GetDefaultContentSetting(type_, nullptr);
std::set<std::string> formatted_hosts;
std::set<std::string> repeated_formatted_hosts;
- // Build a set of repeated formatted hosts
- for (auto i(state_map_.begin()); i != state_map_.end(); ++i) {
- std::string formatted_host = GURLToFormattedHost(i->first);
+ // Build a set of repeated formatted hosts.
+ for (const auto& i : state_map_) {
+ std::string formatted_host = GURLToFormattedHost(i.first);
if (!formatted_hosts.insert(formatted_host).second) {
repeated_formatted_hosts.insert(formatted_host);
}
}
- for (auto i(state_map_.begin()); i != state_map_.end(); ++i) {
- if (i->second == CONTENT_SETTING_ALLOW)
+ for (const auto& i : state_map_) {
+ const GURL& origin = i.first;
+ // The setting that was applied when the corresponding capability was last
+ // requested.
+ const ContentSetting& effective_setting = i.second;
+
+ if (effective_setting == CONTENT_SETTING_ALLOW)
*tab_state_flags |= TABSTATE_HAS_ANY_ALLOWED;
if (formatted_hosts_per_state) {
- std::string formatted_host = GURLToFormattedHost(i->first);
+ std::string formatted_host = GURLToFormattedHost(origin);
std::string final_formatted_host =
repeated_formatted_hosts.find(formatted_host) ==
repeated_formatted_hosts.end()
? formatted_host
- : i->first.spec();
- (*formatted_hosts_per_state)[i->second].insert(final_formatted_host);
+ : origin.spec();
+ (*formatted_hosts_per_state)[effective_setting].insert(
+ final_formatted_host);
}
- const ContentSetting saved_setting =
- host_content_settings_map_->GetContentSetting(i->first, embedder_url_,
- type_, std::string());
+ ContentSetting saved_setting =
+ delegate_->GetSettingsMap()->GetContentSetting(origin, embedder_url_,
+ type_, std::string());
+ ContentSetting embargo_setting =
+ delegate_->GetEmbargoSetting(origin, type_);
+
+ // |embargo_setting| can be only CONTENT_SETTING_ASK or
+ // CONTENT_SETTING_BLOCK. If |saved_setting| is CONTENT_SETTING_ASK then
+ // the |embargo_setting| takes effect.
+ if (saved_setting == CONTENT_SETTING_ASK)
+ saved_setting = embargo_setting;
+
+ // |effective_setting| can be only CONTENT_SETTING_ALLOW or
+ // CONTENT_SETTING_BLOCK.
+ if (saved_setting != effective_setting)
+ *tab_state_flags |= TABSTATE_HAS_CHANGED;
+
if (saved_setting != default_setting)
*tab_state_flags |= TABSTATE_HAS_EXCEPTION;
- if (saved_setting != i->second)
- *tab_state_flags |= TABSTATE_HAS_CHANGED;
+
if (saved_setting != CONTENT_SETTING_ASK)
*tab_state_flags |= TABSTATE_HAS_ANY_ICON;
}
diff --git a/chromium/components/content_settings/browser/content_settings_usages_state.h b/chromium/components/content_settings/browser/content_settings_usages_state.h
index a34ed720de4..2e68ca9875c 100644
--- a/chromium/components/content_settings/browser/content_settings_usages_state.h
+++ b/chromium/components/content_settings/browser/content_settings_usages_state.h
@@ -9,19 +9,23 @@
#include <set>
#include "base/macros.h"
+#include "components/content_settings/browser/tab_specific_content_settings.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "url/gurl.h"
-class HostContentSettingsMap;
-
-// This class manages a content setting state per tab for a given
+// This class manages a content setting state per page for a given
// |ContentSettingsType|, and provides information and presentation data about
// the content setting usage.
+// TODO(crbug.com/1086363): Move this class into the `content_settings`
+// namespace.
class ContentSettingsUsagesState {
public:
- ContentSettingsUsagesState(HostContentSettingsMap* host_content_settings_map,
- ContentSettingsType type);
+ ContentSettingsUsagesState(
+ content_settings::TabSpecificContentSettings::Delegate* delegate_,
+ ContentSettingsType type,
+ const GURL& embedder_url);
+
~ContentSettingsUsagesState();
typedef std::map<GURL, ContentSetting> StateMap;
@@ -30,12 +34,6 @@ class ContentSettingsUsagesState {
// Sets the state for |requesting_origin|.
void OnPermissionSet(const GURL& requesting_origin, bool allowed);
- // Delegated by WebContents to indicate a navigation has happened and we
- // may need to clear our settings.
- void DidNavigate(const GURL& url, const GURL& previous_url);
-
- void ClearStateMap();
-
enum TabState {
TABSTATE_NONE = 0,
// There's at least one entry with non-default setting.
@@ -57,8 +55,7 @@ class ContentSettingsUsagesState {
private:
std::string GURLToFormattedHost(const GURL& url) const;
-
- HostContentSettingsMap* const host_content_settings_map_;
+ content_settings::TabSpecificContentSettings::Delegate* delegate_;
ContentSettingsType type_;
StateMap state_map_;
GURL embedder_url_;
diff --git a/chromium/components/content_settings/browser/tab_specific_content_settings.cc b/chromium/components/content_settings/browser/tab_specific_content_settings.cc
index b783a2c6fde..95ab944de51 100644
--- a/chromium/components/content_settings/browser/tab_specific_content_settings.cc
+++ b/chromium/components/content_settings/browser/tab_specific_content_settings.cc
@@ -9,6 +9,8 @@
#include "base/command_line.h"
#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
+#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -22,17 +24,14 @@
#include "components/browsing_data/content/local_storage_helper.h"
#include "components/browsing_data/content/service_worker_helper.h"
#include "components/browsing_data/content/shared_worker_helper.h"
+#include "components/content_settings/browser/content_settings_usages_state.h"
#include "components/content_settings/common/content_settings_agent.mojom.h"
#include "components/content_settings/core/browser/content_settings_details.h"
#include "components/content_settings/core/browser/content_settings_info.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
#include "components/content_settings/core/browser/content_settings_utils.h"
#include "components/prefs/pref_service.h"
-#include "components/security_state/core/security_state_pref_names.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_details.h"
-#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -44,9 +43,6 @@
#include "url/origin.h"
using content::BrowserThread;
-using content::NavigationController;
-using content::NavigationEntry;
-using content::WebContents;
namespace content_settings {
namespace {
@@ -62,60 +58,325 @@ bool ShouldSendUpdatedContentSettingsRulesToRenderer(
return RendererContentSettingRules::IsRendererContentSetting((content_type));
}
+void MaybeSendRendererContentSettingsRules(
+ content::RenderFrameHost* rfh,
+ const HostContentSettingsMap* map,
+ TabSpecificContentSettings::Delegate* delegate) {
+ DCHECK_EQ(rfh, rfh->GetMainFrame());
+ // Only send a message to the renderer if it is initialised and not dead.
+ // Otherwise, the IPC messages will be queued in the browser process,
+ // potentially causing large memory leaks. See https://crbug.com/875937.
+ content::RenderProcessHost* process = rfh->GetProcess();
+ if (!process->IsInitializedAndNotDead())
+ return;
+
+ RendererContentSettingRules rules;
+ GetRendererContentSettingRules(map, &rules);
+ delegate->SetContentSettingRules(process, rules);
+}
+
+bool WillNavigationCreateNewTabSpecificContentSettingsOnCommit(
+ content::NavigationHandle* navigation_handle) {
+ return navigation_handle->IsInMainFrame() &&
+ !navigation_handle->IsSameDocument() &&
+ !navigation_handle->IsServedFromBackForwardCache();
+}
+
} // namespace
TabSpecificContentSettings::SiteDataObserver::SiteDataObserver(
- TabSpecificContentSettings* tab_specific_content_settings)
- : tab_specific_content_settings_(tab_specific_content_settings) {
- tab_specific_content_settings_->AddSiteDataObserver(this);
+ content::WebContents* web_contents)
+ : web_contents_(web_contents) {
+ // Make sure the handler was attached to the WebContents as some UT might skip
+ // this.
+ auto* handler =
+ TabSpecificContentSettings::WebContentsHandler::FromWebContents(
+ web_contents_);
+ if (handler)
+ handler->AddSiteDataObserver(this);
}
TabSpecificContentSettings::SiteDataObserver::~SiteDataObserver() {
- if (tab_specific_content_settings_)
- tab_specific_content_settings_->RemoveSiteDataObserver(this);
+ if (!web_contents_)
+ return;
+ auto* handler =
+ TabSpecificContentSettings::WebContentsHandler::FromWebContents(
+ web_contents_);
+ if (handler)
+ handler->RemoveSiteDataObserver(this);
}
-void TabSpecificContentSettings::SiteDataObserver::ContentSettingsDestroyed() {
- tab_specific_content_settings_ = nullptr;
+void TabSpecificContentSettings::SiteDataObserver::WebContentsDestroyed() {
+ web_contents_ = nullptr;
}
-TabSpecificContentSettings::TabSpecificContentSettings(
- WebContents* tab,
+// static
+void TabSpecificContentSettings::WebContentsHandler::CreateForWebContents(
+ content::WebContents* web_contents,
+ std::unique_ptr<Delegate> delegate) {
+ DCHECK(web_contents);
+ if (TabSpecificContentSettings::WebContentsHandler::FromWebContents(
+ web_contents)) {
+ return;
+ }
+
+ web_contents->SetUserData(
+ TabSpecificContentSettings::WebContentsHandler::UserDataKey(),
+ base::WrapUnique(new TabSpecificContentSettings::WebContentsHandler(
+ web_contents, std::move(delegate))));
+}
+
+TabSpecificContentSettings::WebContentsHandler::WebContentsHandler(
+ content::WebContents* web_contents,
std::unique_ptr<Delegate> delegate)
- : content::WebContentsObserver(tab),
+ : WebContentsObserver(web_contents),
delegate_(std::move(delegate)),
+ map_(delegate_->GetSettingsMap()) {
+ DCHECK(!TabSpecificContentSettings::GetForCurrentDocument(
+ web_contents->GetMainFrame()));
+ content::SetRenderDocumentHostUserData(
+ web_contents->GetMainFrame(), TabSpecificContentSettings::UserDataKey(),
+ base::WrapUnique(new TabSpecificContentSettings(*this, delegate_.get())));
+}
+
+TabSpecificContentSettings::WebContentsHandler::~WebContentsHandler() {
+ for (SiteDataObserver& observer : observer_list_)
+ observer.WebContentsDestroyed();
+}
+
+void TabSpecificContentSettings::WebContentsHandler::
+ TransferNavigationContentSettingsToCommittedDocument(
+ const InflightNavigationContentSettings& navigation_settings,
+ content::RenderFrameHost* rfh) {
+ for (const auto& cookie_access : navigation_settings.cookie_accesses) {
+ OnCookiesAccessed(rfh, cookie_access);
+ }
+ for (const auto& service_worker_access :
+ navigation_settings.service_worker_accesses) {
+ OnServiceWorkerAccessed(rfh, service_worker_access.first,
+ service_worker_access.second);
+ }
+}
+
+void TabSpecificContentSettings::WebContentsHandler::OnCookiesAccessed(
+ content::NavigationHandle* navigation,
+ const content::CookieAccessDetails& details) {
+ auto it = inflight_navigation_settings_.find(navigation);
+ if (it != inflight_navigation_settings_.end()) {
+ it->second.cookie_accesses.push_back(details);
+ return;
+ }
+ // TODO(carlscab): We should be able to
+ // DHECK(!WillNavigationCreateNewTabSpecificContentSettingsOnCommit) here, but
+ // there is still code that starts a navigation before attaching the tab
+ // helpers in DevConsole related code. So we miss the DidStartNavigation event
+ // for those navigations. (https://crbug.com/1095576)
+ OnCookiesAccessed(web_contents()->GetMainFrame(), details);
+}
+
+void TabSpecificContentSettings::WebContentsHandler::OnCookiesAccessed(
+ content::RenderFrameHost* rfh,
+ const content::CookieAccessDetails& details) {
+ auto* tscs =
+ TabSpecificContentSettings::GetForCurrentDocument(rfh->GetMainFrame());
+ if (tscs)
+ tscs->OnCookiesAccessed(details);
+}
+
+void TabSpecificContentSettings::WebContentsHandler::OnServiceWorkerAccessed(
+ content::NavigationHandle* navigation,
+ const GURL& scope,
+ content::AllowServiceWorkerResult allowed) {
+ DCHECK(scope.is_valid());
+
+ auto it = inflight_navigation_settings_.find(navigation);
+ if (it != inflight_navigation_settings_.end()) {
+ it->second.service_worker_accesses.emplace_back(
+ std::make_pair(scope, allowed));
+ return;
+ }
+ // TODO(carlscab): We should be able to
+ // DHECK(!WillNavigationCreateNewTabSpecificContentSettingsOnCommit) here, but
+ // there is still code that starts a navigation before attaching the tab
+ // helpers in DevConsole related code. So we miss the DidStartNavigation event
+ // for those navigations.
+ OnServiceWorkerAccessed(web_contents()->GetMainFrame(), scope, allowed);
+}
+
+void TabSpecificContentSettings::WebContentsHandler::OnServiceWorkerAccessed(
+ content::RenderFrameHost* frame,
+ const GURL& scope,
+ content::AllowServiceWorkerResult allowed) {
+ auto* tscs =
+ TabSpecificContentSettings::GetForCurrentDocument(frame->GetMainFrame());
+ if (tscs)
+ tscs->OnServiceWorkerAccessed(scope, allowed);
+}
+
+void TabSpecificContentSettings::WebContentsHandler::
+ RenderFrameForInterstitialPageCreated(
+ content::RenderFrameHost* render_frame_host) {
+ // We want to tell the renderer-side code to ignore content settings for this
+ // page.
+ mojo::AssociatedRemote<content_settings::mojom::ContentSettingsAgent>
+ content_settings_agent;
+ render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
+ &content_settings_agent);
+ content_settings_agent->SetAsInterstitial();
+}
+
+void TabSpecificContentSettings::WebContentsHandler::DidStartNavigation(
+ content::NavigationHandle* navigation_handle) {
+ if (!WillNavigationCreateNewTabSpecificContentSettingsOnCommit(
+ navigation_handle)) {
+ return;
+ }
+
+ inflight_navigation_settings_.insert(
+ std::make_pair(navigation_handle, InflightNavigationContentSettings()));
+}
+
+void TabSpecificContentSettings::WebContentsHandler::ReadyToCommitNavigation(
+ content::NavigationHandle* navigation_handle) {
+ if (!WillNavigationCreateNewTabSpecificContentSettingsOnCommit(
+ navigation_handle)) {
+ return;
+ }
+
+ // There may be content settings that were updated for the navigated URL.
+ // These would not have been sent before if we're navigating cross-origin.
+ // Ensure up to date rules are sent before navigation commits.
+ MaybeSendRendererContentSettingsRules(
+ navigation_handle->GetWebContents()->GetMainFrame(), map_,
+ delegate_.get());
+}
+
+void TabSpecificContentSettings::WebContentsHandler::DidFinishNavigation(
+ content::NavigationHandle* navigation_handle) {
+ if (!WillNavigationCreateNewTabSpecificContentSettingsOnCommit(
+ navigation_handle)) {
+ return;
+ }
+
+ if (!navigation_handle->HasCommitted()) {
+ inflight_navigation_settings_.erase(navigation_handle);
+ return;
+ }
+
+ auto tscs =
+ base::WrapUnique(new TabSpecificContentSettings(*this, delegate_.get()));
+
+ // TODO(carlscab): This sort of internal. Maybe add a
+ // RenderDocumentHostUserData::Create(RenderFrameHost* rfh, Params...)
+ content::SetRenderDocumentHostUserData(
+ navigation_handle->GetRenderFrameHost(),
+ TabSpecificContentSettings::UserDataKey(), std::move(tscs));
+
+ auto it = inflight_navigation_settings_.find(navigation_handle);
+ if (it != inflight_navigation_settings_.end()) {
+ TransferNavigationContentSettingsToCommittedDocument(
+ it->second, navigation_handle->GetRenderFrameHost());
+ inflight_navigation_settings_.erase(it);
+ }
+
+ delegate_->UpdateLocationBar();
+}
+
+void TabSpecificContentSettings::WebContentsHandler::AppCacheAccessed(
+ const GURL& manifest_url,
+ bool blocked_by_policy) {
+ auto* tscs = TabSpecificContentSettings::GetForCurrentDocument(
+ web_contents()->GetMainFrame());
+ if (tscs)
+ tscs->AppCacheAccessed(manifest_url, blocked_by_policy);
+}
+
+void TabSpecificContentSettings::WebContentsHandler::AddSiteDataObserver(
+ SiteDataObserver* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void TabSpecificContentSettings::WebContentsHandler::RemoveSiteDataObserver(
+ SiteDataObserver* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+void TabSpecificContentSettings::WebContentsHandler::NotifySiteDataObservers() {
+ for (SiteDataObserver& observer : observer_list_)
+ observer.OnSiteDataAccessed();
+}
+
+TabSpecificContentSettings::WebContentsHandler::
+ InflightNavigationContentSettings::InflightNavigationContentSettings() =
+ default;
+TabSpecificContentSettings::WebContentsHandler::
+ InflightNavigationContentSettings::InflightNavigationContentSettings(
+ const InflightNavigationContentSettings&) = default;
+TabSpecificContentSettings::WebContentsHandler::
+ InflightNavigationContentSettings::InflightNavigationContentSettings(
+ InflightNavigationContentSettings&&) = default;
+
+TabSpecificContentSettings::WebContentsHandler::
+ InflightNavigationContentSettings::~InflightNavigationContentSettings() =
+ default;
+
+TabSpecificContentSettings::WebContentsHandler::
+ InflightNavigationContentSettings&
+ TabSpecificContentSettings::WebContentsHandler::
+ InflightNavigationContentSettings::operator=(
+ InflightNavigationContentSettings&&) = default;
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(TabSpecificContentSettings::WebContentsHandler)
+
+TabSpecificContentSettings::TabSpecificContentSettings(
+ TabSpecificContentSettings::WebContentsHandler& handler,
+ Delegate* delegate)
+ : handler_(handler),
+ main_frame_(handler_.web_contents()->GetMainFrame()),
+ delegate_(delegate),
+ visible_url_(handler_.web_contents()->GetVisibleURL()),
map_(delegate_->GetSettingsMap()),
- allowed_local_shared_objects_(tab->GetBrowserContext(),
- delegate_->GetAdditionalFileSystemTypes(),
- delegate_->GetIsDeletionDisabledCallback()),
- blocked_local_shared_objects_(tab->GetBrowserContext(),
- delegate_->GetAdditionalFileSystemTypes(),
- delegate_->GetIsDeletionDisabledCallback()),
- geolocation_usages_state_(map_, ContentSettingsType::GEOLOCATION),
- midi_usages_state_(map_, ContentSettingsType::MIDI_SYSEX),
+ allowed_local_shared_objects_(
+ handler_.web_contents()->GetBrowserContext(),
+ delegate_->GetAdditionalFileSystemTypes(),
+ delegate_->GetIsDeletionDisabledCallback()),
+ blocked_local_shared_objects_(
+ handler_.web_contents()->GetBrowserContext(),
+ delegate_->GetAdditionalFileSystemTypes(),
+ delegate_->GetIsDeletionDisabledCallback()),
+ geolocation_usages_state_(std::make_unique<ContentSettingsUsagesState>(
+ delegate_,
+ ContentSettingsType::GEOLOCATION,
+ handler_.web_contents()->GetVisibleURL())),
+ midi_usages_state_(std::make_unique<ContentSettingsUsagesState>(
+ delegate_,
+ ContentSettingsType::MIDI_SYSEX,
+ handler_.web_contents()->GetVisibleURL())),
load_plugins_link_enabled_(true),
microphone_camera_state_(MICROPHONE_CAMERA_NOT_ACCESSED) {
- ClearContentSettingsExceptForNavigationRelatedSettings();
- ClearNavigationRelatedContentSettings();
-
observer_.Add(map_);
}
-TabSpecificContentSettings::~TabSpecificContentSettings() {
- for (SiteDataObserver& observer : observer_list_)
- observer.ContentSettingsDestroyed();
-}
+TabSpecificContentSettings::~TabSpecificContentSettings() = default;
// static
void TabSpecificContentSettings::CreateForWebContents(
content::WebContents* web_contents,
std::unique_ptr<Delegate> delegate) {
- DCHECK(web_contents);
- if (!FromWebContents(web_contents)) {
- web_contents->SetUserData(UserDataKey(),
- base::WrapUnique(new TabSpecificContentSettings(
- web_contents, std::move(delegate))));
+ TabSpecificContentSettings::WebContentsHandler::CreateForWebContents(
+ web_contents, std::move(delegate));
+}
+
+// static
+void TabSpecificContentSettings::DeleteForWebContentsForTest(
+ content::WebContents* web_contents) {
+ if (web_contents->GetMainFrame()) {
+ TabSpecificContentSettings::DeleteForCurrentDocument(
+ web_contents->GetMainFrame());
}
+
+ web_contents->RemoveUserData(
+ TabSpecificContentSettings::WebContentsHandler::UserDataKey());
}
// static
@@ -126,11 +387,18 @@ TabSpecificContentSettings* TabSpecificContentSettings::GetForFrame(
content::RenderFrameHost* frame =
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
- WebContents* web_contents = WebContents::FromRenderFrameHost(frame);
- if (!web_contents)
+ if (!frame)
return nullptr;
+ return TabSpecificContentSettings::GetForCurrentDocument(
+ frame->GetMainFrame());
+}
- return TabSpecificContentSettings::FromWebContents(web_contents);
+// static
+TabSpecificContentSettings* TabSpecificContentSettings::FromWebContents(
+ content::WebContents* web_contents) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return TabSpecificContentSettings::GetForCurrentDocument(
+ web_contents->GetMainFrame());
}
// static
@@ -197,6 +465,14 @@ void TabSpecificContentSettings::SharedWorkerAccessed(
blocked_by_policy);
}
+// static
+content::WebContentsObserver*
+TabSpecificContentSettings::GetWebContentsObserverForTest(
+ content::WebContents* web_contents) {
+ return TabSpecificContentSettings::WebContentsHandler::FromWebContents(
+ web_contents);
+}
+
bool TabSpecificContentSettings::IsContentBlocked(
ContentSettingsType content_type) const {
DCHECK_NE(ContentSettingsType::GEOLOCATION, content_type)
@@ -330,22 +606,10 @@ void TabSpecificContentSettings::OnDomStorageAccessed(const GURL& url,
else
OnContentAllowed(ContentSettingsType::COOKIES);
- NotifySiteDataObservers();
-}
-
-void TabSpecificContentSettings::OnCookiesAccessed(
- content::NavigationHandle* navigation,
- const content::CookieAccessDetails& details) {
- OnCookiesAccessedImpl(details);
+ handler_.NotifySiteDataObservers();
}
void TabSpecificContentSettings::OnCookiesAccessed(
- content::RenderFrameHost* rfh,
- const content::CookieAccessDetails& details) {
- OnCookiesAccessedImpl(details);
-}
-
-void TabSpecificContentSettings::OnCookiesAccessedImpl(
const content::CookieAccessDetails& details) {
if (details.cookie_list.empty())
return;
@@ -357,7 +621,7 @@ void TabSpecificContentSettings::OnCookiesAccessedImpl(
OnContentAllowed(ContentSettingsType::COOKIES);
}
- NotifySiteDataObservers();
+ handler_.NotifySiteDataObservers();
}
void TabSpecificContentSettings::OnIndexedDBAccessed(const GURL& url,
@@ -370,7 +634,7 @@ void TabSpecificContentSettings::OnIndexedDBAccessed(const GURL& url,
OnContentAllowed(ContentSettingsType::COOKIES);
}
- NotifySiteDataObservers();
+ handler_.NotifySiteDataObservers();
}
void TabSpecificContentSettings::OnCacheStorageAccessed(
@@ -386,36 +650,10 @@ void TabSpecificContentSettings::OnCacheStorageAccessed(
OnContentAllowed(ContentSettingsType::COOKIES);
}
- NotifySiteDataObservers();
+ handler_.NotifySiteDataObservers();
}
void TabSpecificContentSettings::OnServiceWorkerAccessed(
- content::NavigationHandle* navigation,
- const GURL& scope,
- content::AllowServiceWorkerResult allowed) {
- DCHECK(scope.is_valid());
- if (allowed) {
- allowed_local_shared_objects_.service_workers()->Add(
- url::Origin::Create(scope));
- } else {
- blocked_local_shared_objects_.service_workers()->Add(
- url::Origin::Create(scope));
- }
-
- if (allowed.javascript_blocked_by_policy()) {
- OnContentBlocked(ContentSettingsType::JAVASCRIPT);
- } else {
- OnContentAllowed(ContentSettingsType::JAVASCRIPT);
- }
- if (allowed.cookies_blocked_by_policy()) {
- OnContentBlocked(ContentSettingsType::COOKIES);
- } else {
- OnContentAllowed(ContentSettingsType::COOKIES);
- }
-}
-
-void TabSpecificContentSettings::OnServiceWorkerAccessed(
- content::RenderFrameHost* frame,
const GURL& scope,
content::AllowServiceWorkerResult allowed) {
DCHECK(scope.is_valid());
@@ -466,7 +704,7 @@ void TabSpecificContentSettings::OnWebDatabaseAccessed(const GURL& url,
OnContentAllowed(ContentSettingsType::COOKIES);
}
- NotifySiteDataObservers();
+ handler_.NotifySiteDataObservers();
}
void TabSpecificContentSettings::OnFileSystemAccessed(const GURL& url,
@@ -482,13 +720,13 @@ void TabSpecificContentSettings::OnFileSystemAccessed(const GURL& url,
OnContentAllowed(ContentSettingsType::COOKIES);
}
- NotifySiteDataObservers();
+ handler_.NotifySiteDataObservers();
}
void TabSpecificContentSettings::OnGeolocationPermissionSet(
const GURL& requesting_origin,
bool allowed) {
- geolocation_usages_state_.OnPermissionSet(requesting_origin, allowed);
+ geolocation_usages_state_->OnPermissionSet(requesting_origin, allowed);
delegate_->UpdateLocationBar();
}
@@ -564,44 +802,16 @@ void TabSpecificContentSettings::OnMediaStreamPermissionSet(
void TabSpecificContentSettings::OnMidiSysExAccessed(
const GURL& requesting_origin) {
- midi_usages_state_.OnPermissionSet(requesting_origin, true);
+ midi_usages_state_->OnPermissionSet(requesting_origin, true);
OnContentAllowed(ContentSettingsType::MIDI_SYSEX);
}
void TabSpecificContentSettings::OnMidiSysExAccessBlocked(
const GURL& requesting_origin) {
- midi_usages_state_.OnPermissionSet(requesting_origin, false);
+ midi_usages_state_->OnPermissionSet(requesting_origin, false);
OnContentBlocked(ContentSettingsType::MIDI_SYSEX);
}
-void TabSpecificContentSettings::
- ClearContentSettingsExceptForNavigationRelatedSettings() {
- for (auto& status : content_settings_status_) {
- if (status.first == ContentSettingsType::COOKIES ||
- status.first == ContentSettingsType::JAVASCRIPT)
- continue;
- status.second.blocked = false;
- status.second.allowed = false;
- }
- microphone_camera_state_ = MICROPHONE_CAMERA_NOT_ACCESSED;
- camera_was_just_granted_on_site_level_ = false;
- mic_was_just_granted_on_site_level_ = false;
- load_plugins_link_enabled_ = true;
- delegate_->UpdateLocationBar();
-}
-
-void TabSpecificContentSettings::ClearNavigationRelatedContentSettings() {
- blocked_local_shared_objects_.Reset();
- allowed_local_shared_objects_.Reset();
- for (ContentSettingsType type :
- {ContentSettingsType::COOKIES, ContentSettingsType::JAVASCRIPT}) {
- ContentSettingsStatus& status = content_settings_status_[type];
- status.blocked = false;
- status.allowed = false;
- }
- delegate_->UpdateLocationBar();
-}
-
void TabSpecificContentSettings::FlashDownloadBlocked() {
OnContentBlocked(ContentSettingsType::PLUGINS);
}
@@ -635,7 +845,7 @@ void TabSpecificContentSettings::OnContentSettingChanged(
if (!details.update_all() &&
// The visible URL is the URL in the URL field of a tab.
// Currently this should be matched by the |primary_pattern|.
- !details.primary_pattern().Matches(web_contents()->GetVisibleURL())) {
+ !details.primary_pattern().Matches(visible_url_)) {
return;
}
@@ -674,8 +884,7 @@ void TabSpecificContentSettings::OnContentSettingChanged(
case ContentSettingsType::CLIPBOARD_READ_WRITE:
case ContentSettingsType::SENSORS: {
ContentSetting setting = map_->GetContentSetting(
- web_contents()->GetVisibleURL(), web_contents()->GetVisibleURL(),
- content_type, std::string());
+ visible_url_, visible_url_, content_type, std::string());
// If an indicator is shown and the content settings has changed, swap the
// indicator for the one with the opposite meaning (allowed <=> blocked).
if (setting == CONTENT_SETTING_BLOCK && status.allowed) {
@@ -696,82 +905,7 @@ void TabSpecificContentSettings::OnContentSettingChanged(
if (!ShouldSendUpdatedContentSettingsRulesToRenderer(content_type))
return;
- MaybeSendRendererContentSettingsRules(web_contents());
-}
-
-void TabSpecificContentSettings::MaybeSendRendererContentSettingsRules(
- content::WebContents* web_contents) {
- // Only send a message to the renderer if it is initialised and not dead.
- // Otherwise, the IPC messages will be queued in the browser process,
- // potentially causing large memory leaks. See https://crbug.com/875937.
- content::RenderProcessHost* process =
- web_contents->GetMainFrame()->GetProcess();
- if (!process->IsInitializedAndNotDead())
- return;
-
- RendererContentSettingRules rules;
- GetRendererContentSettingRules(map_, &rules);
- delegate_->SetContentSettingRules(process, rules);
-}
-
-void TabSpecificContentSettings::RenderFrameForInterstitialPageCreated(
- content::RenderFrameHost* render_frame_host) {
- // We want to tell the renderer-side code to ignore content settings for this
- // page.
- mojo::AssociatedRemote<content_settings::mojom::ContentSettingsAgent>
- content_settings_agent;
- render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
- &content_settings_agent);
- content_settings_agent->SetAsInterstitial();
-}
-
-void TabSpecificContentSettings::DidStartNavigation(
- content::NavigationHandle* navigation_handle) {
- if (!navigation_handle->IsInMainFrame() ||
- navigation_handle->IsSameDocument()) {
- return;
- }
-
- ClearNavigationRelatedContentSettings();
-}
-
-void TabSpecificContentSettings::ReadyToCommitNavigation(
- content::NavigationHandle* navigation_handle) {
- if (!navigation_handle->IsInMainFrame() ||
- navigation_handle->IsSameDocument()) {
- return;
- }
-
- PrefService* prefs = delegate_->GetPrefs();
- if (prefs &&
- !prefs->GetBoolean(
- security_state::prefs::kStricterMixedContentTreatmentEnabled)) {
- auto* render_frame_host = navigation_handle->GetRenderFrameHost();
- mojo::AssociatedRemote<content_settings::mojom::ContentSettingsAgent>
- content_settings_agent;
- render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
- &content_settings_agent);
- content_settings_agent->SetDisabledMixedContentUpgrades();
- }
-
- // There may be content settings that were updated for the navigated URL.
- // These would not have been sent before if we're navigating cross-origin.
- // Ensure up to date rules are sent before navigation commits.
- MaybeSendRendererContentSettingsRules(navigation_handle->GetWebContents());
-}
-
-void TabSpecificContentSettings::DidFinishNavigation(
- content::NavigationHandle* navigation_handle) {
- if (!navigation_handle->IsInMainFrame() ||
- !navigation_handle->HasCommitted() ||
- navigation_handle->IsSameDocument()) {
- return;
- }
-
- ClearContentSettingsExceptForNavigationRelatedSettings();
- GeolocationDidNavigate(navigation_handle);
- MidiDidNavigate(navigation_handle);
- ClearContentSettingsChangedViaPageInfo();
+ MaybeSendRendererContentSettingsRules(main_frame_, map_, delegate_);
}
void TabSpecificContentSettings::AppCacheAccessed(const GURL& manifest_url,
@@ -787,39 +921,10 @@ void TabSpecificContentSettings::AppCacheAccessed(const GURL& manifest_url,
}
}
-void TabSpecificContentSettings::AddSiteDataObserver(
- SiteDataObserver* observer) {
- observer_list_.AddObserver(observer);
-}
-
-void TabSpecificContentSettings::RemoveSiteDataObserver(
- SiteDataObserver* observer) {
- observer_list_.RemoveObserver(observer);
-}
-
-void TabSpecificContentSettings::NotifySiteDataObservers() {
- for (SiteDataObserver& observer : observer_list_)
- observer.OnSiteDataAccessed();
-}
-
void TabSpecificContentSettings::ClearContentSettingsChangedViaPageInfo() {
content_settings_changed_via_page_info_.clear();
}
-void TabSpecificContentSettings::GeolocationDidNavigate(
- content::NavigationHandle* navigation_handle) {
- geolocation_usages_state_.ClearStateMap();
- geolocation_usages_state_.DidNavigate(navigation_handle->GetURL(),
- navigation_handle->GetPreviousURL());
-}
-
-void TabSpecificContentSettings::MidiDidNavigate(
- content::NavigationHandle* navigation_handle) {
- midi_usages_state_.ClearStateMap();
- midi_usages_state_.DidNavigate(navigation_handle->GetURL(),
- navigation_handle->GetPreviousURL());
-}
-
void TabSpecificContentSettings::BlockAllContentForTesting() {
content_settings::ContentSettingsRegistry* registry =
content_settings::ContentSettingsRegistry::GetInstance();
@@ -834,16 +939,16 @@ void TabSpecificContentSettings::BlockAllContentForTesting() {
// Geolocation and media must be blocked separately, as the generic
// TabSpecificContentSettings::OnContentBlocked does not apply to them.
- OnGeolocationPermissionSet(web_contents()->GetLastCommittedURL(), false);
+ OnGeolocationPermissionSet(main_frame_->GetLastCommittedURL(), false);
MicrophoneCameraStateFlags media_blocked =
static_cast<MicrophoneCameraStateFlags>(
TabSpecificContentSettings::MICROPHONE_ACCESSED |
TabSpecificContentSettings::MICROPHONE_BLOCKED |
TabSpecificContentSettings::CAMERA_ACCESSED |
TabSpecificContentSettings::CAMERA_BLOCKED);
- OnMediaStreamPermissionSet(web_contents()->GetLastCommittedURL(),
- media_blocked, std::string(), std::string(),
- std::string(), std::string());
+ OnMediaStreamPermissionSet(main_frame_->GetLastCommittedURL(), media_blocked,
+ std::string(), std::string(), std::string(),
+ std::string());
}
void TabSpecificContentSettings::ContentSettingChangedViaPageInfo(
@@ -857,6 +962,6 @@ bool TabSpecificContentSettings::HasContentSettingChangedViaPageInfo(
content_settings_changed_via_page_info_.end();
}
-WEB_CONTENTS_USER_DATA_KEY_IMPL(TabSpecificContentSettings)
+RENDER_DOCUMENT_HOST_USER_DATA_KEY_IMPL(TabSpecificContentSettings)
} // namespace content_settings
diff --git a/chromium/components/content_settings/browser/tab_specific_content_settings.h b/chromium/components/content_settings/browser/tab_specific_content_settings.h
index 39583b71436..38529f2676f 100644
--- a/chromium/components/content_settings/browser/tab_specific_content_settings.h
+++ b/chromium/components/content_settings/browser/tab_specific_content_settings.h
@@ -14,17 +14,19 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observer.h"
#include "build/build_config.h"
#include "components/browsing_data/content/cookie_helper.h"
#include "components/browsing_data/content/local_shared_objects_container.h"
-#include "components/content_settings/browser/content_settings_usages_state.h"
#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "content/public/browser/allow_service_worker_result.h"
+#include "content/public/browser/render_document_host_user_data.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
@@ -36,6 +38,8 @@ namespace url {
class Origin;
} // namespace url
+class ContentSettingsUsagesState;
+
namespace content_settings {
// TODO(msramek): Media is storing their state in TabSpecificContentSettings:
@@ -44,13 +48,28 @@ namespace content_settings {
// content::WebContentsUserData
// This class manages state about permissions, content settings, cookies and
-// site data for a specific WebContents. It tracks which content was accessed
-// and which content was blocked. Based on this it provides information about
-// which types of content were accessed and blocked.
+// site data for a specific page (main document and all of its child frames). It
+// tracks which content was accessed and which content was blocked. Based on
+// this it provides information about which types of content were accessed and
+// blocked.
+//
+// Tracking is done per main document so instances of this class will be deleted
+// when the main document is deleted. This can happen after the tab navigates
+// away to a new document or when the tab itself is deleted, so you should not
+// keep references to objects of this class.
+//
+// When a page enters the back-forward cache its associated
+// TabSpecificContentSettings are not cleared and will be restored along with
+// the document when navigating back. These stored instances still listen to
+// content settings updates and keep their internal state up to date.
+//
+// Events tied to a main frame navigation will be associated with the newly
+// loaded page once the navigation commits or discarded if it does not.
+//
+// TODO(carlscab): Rename this class to PageSpecificContentSettings
class TabSpecificContentSettings
- : public content::WebContentsObserver,
- public content_settings::Observer,
- public content::WebContentsUserData<TabSpecificContentSettings> {
+ : public content_settings::Observer,
+ public content::RenderDocumentHostUserData<TabSpecificContentSettings> {
public:
// Fields describing the current mic/camera state. If a page has attempted to
// access a device, the XXX_ACCESSED bit will be set. If access was blocked,
@@ -85,6 +104,10 @@ class TabSpecificContentSettings
// Gets the settings map for the current web contents.
virtual HostContentSettingsMap* GetSettingsMap() = 0;
+ virtual ContentSetting GetEmbargoSetting(
+ const GURL& request_origin,
+ ContentSettingsType permission) = 0;
+
// Gets any additional file system types which should be used when
// constructing a browsing_data::FileSystemHelper.
virtual std::vector<storage::FileSystemType>
@@ -114,23 +137,20 @@ class TabSpecificContentSettings
// |TabSpecificContentSettings|.
class SiteDataObserver {
public:
- explicit SiteDataObserver(
- TabSpecificContentSettings* tab_specific_content_settings);
+ explicit SiteDataObserver(content::WebContents* web_contents);
virtual ~SiteDataObserver();
// Called whenever site data is accessed.
virtual void OnSiteDataAccessed() = 0;
- TabSpecificContentSettings* tab_specific_content_settings() {
- return tab_specific_content_settings_;
- }
+ content::WebContents* web_contents() { return web_contents_; }
- // Called when the TabSpecificContentSettings is destroyed; nulls out
+ // Called when the WebContents is destroyed; nulls out
// the local reference.
- void ContentSettingsDestroyed();
+ void WebContentsDestroyed();
private:
- TabSpecificContentSettings* tab_specific_content_settings_;
+ content::WebContents* web_contents_;
DISALLOW_COPY_AND_ASSIGN(SiteDataObserver);
};
@@ -139,10 +159,14 @@ class TabSpecificContentSettings
static void CreateForWebContents(content::WebContents* web_contents,
std::unique_ptr<Delegate> delegate);
+ static void DeleteForWebContentsForTest(content::WebContents* web_contents);
// Returns the object given a RenderFrameHost ids.
static TabSpecificContentSettings* GetForFrame(int render_process_id,
int render_frame_id);
+ // TODO(carlscab): Get rid of this and use GetForFrame instead
+ static TabSpecificContentSettings* FromWebContents(
+ content::WebContents* contents);
// Called when a specific Web database in the current page was accessed. If
// access was blocked due to the user's content settings,
@@ -188,17 +212,15 @@ class TabSpecificContentSettings
const url::Origin& constructor_origin,
bool blocked_by_policy);
- // Resets the |content_settings_status_|, except for
- // information which are needed for navigation: ContentSettingsType::COOKIES
- // for cookies and service workers, and ContentSettingsType::JAVASCRIPT for
- // service workers.
- // Only public for tests.
- void ClearContentSettingsExceptForNavigationRelatedSettings();
+ static content::WebContentsObserver* GetWebContentsObserverForTest(
+ content::WebContents* web_contents);
- // Resets navigation related information (ContentSettingsType::COOKIES and
- // ContentSettingsType::JAVASCRIPT).
- // Only public for tests.
- void ClearNavigationRelatedContentSettings();
+ // Returns a WeakPtr to this instance. Given that TabSpecificContentSettings
+ // instances are tied to a page it is generally unsafe to store these
+ // references, instead a WeakPtr should be used instead.
+ base::WeakPtr<TabSpecificContentSettings> AsWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
// Notifies that a Flash download has been blocked.
void FlashDownloadBlocked();
@@ -259,13 +281,13 @@ class TabSpecificContentSettings
// Returns the ContentSettingsUsagesState that controls the
// geolocation API usage on this page.
const ContentSettingsUsagesState& geolocation_usages_state() const {
- return geolocation_usages_state_;
+ return *geolocation_usages_state_;
}
// Returns the ContentSettingsUsageState that controls the MIDI usage on
// this page.
const ContentSettingsUsagesState& midi_usages_state() const {
- return midi_usages_state_;
+ return *midi_usages_state_;
}
// Returns the |LocalSharedObjectsContainer| instances corresponding to all
@@ -329,12 +351,9 @@ class TabSpecificContentSettings
void OnMidiSysExAccessed(const GURL& reqesting_origin);
void OnMidiSysExAccessBlocked(const GURL& requesting_origin);
- // Adds the given |SiteDataObserver|. The |observer| is notified when a
- // locale shared object, like for example a cookie, is accessed.
- void AddSiteDataObserver(SiteDataObserver* observer);
-
- // Removes the given |SiteDataObserver|.
- void RemoveSiteDataObserver(SiteDataObserver* observer);
+ void OnCookiesAccessed(const content::CookieAccessDetails& details);
+ void OnServiceWorkerAccessed(const GURL& scope,
+ content::AllowServiceWorkerResult allowed);
// Block all content. Used for testing content setting bubbles.
void BlockAllContentForTesting();
@@ -346,45 +365,121 @@ class TabSpecificContentSettings
// since the last navigation.
bool HasContentSettingChangedViaPageInfo(ContentSettingsType type) const;
- Delegate* delegate() { return delegate_.get(); }
+ Delegate* delegate() { return delegate_; }
private:
- friend class content::WebContentsUserData<TabSpecificContentSettings>;
+ friend class content::RenderDocumentHostUserData<TabSpecificContentSettings>;
+
+ // This class attaches to WebContents to listen to events and route them to
+ // appropriate TabSpecificContentSettings, store navigation related events
+ // until the navigation finishes and then transferring the
+ // navigation-associated state to the newly-created page.
+ class WebContentsHandler
+ : public content::WebContentsObserver,
+ public content::WebContentsUserData<WebContentsHandler> {
+ public:
+ static void CreateForWebContents(content::WebContents* web_contents,
+ std::unique_ptr<Delegate> delegate);
- explicit TabSpecificContentSettings(content::WebContents* tab,
- std::unique_ptr<Delegate> delegate);
+ explicit WebContentsHandler(content::WebContents* web_contents,
+ std::unique_ptr<Delegate> delegate);
+ ~WebContentsHandler() override;
+ // Adds the given |SiteDataObserver|. The |observer| is notified when a
+ // locale shared object, like for example a cookie, is accessed.
+ void AddSiteDataObserver(SiteDataObserver* observer);
- void MaybeSendRendererContentSettingsRules(
- content::WebContents* web_contents);
+ // Removes the given |SiteDataObserver|.
+ void RemoveSiteDataObserver(SiteDataObserver* observer);
- // content::WebContentsObserver overrides.
- void RenderFrameForInterstitialPageCreated(
- content::RenderFrameHost* render_frame_host) override;
- void DidStartNavigation(
- content::NavigationHandle* navigation_handle) override;
- void ReadyToCommitNavigation(
- content::NavigationHandle* navigation_handle) override;
- void DidFinishNavigation(
- content::NavigationHandle* navigation_handle) override;
- void AppCacheAccessed(const GURL& manifest_url,
- bool blocked_by_policy) override;
- void OnCookiesAccessed(content::NavigationHandle* navigation,
- const content::CookieAccessDetails& details) override;
- void OnCookiesAccessed(content::RenderFrameHost* rfh,
- const content::CookieAccessDetails& details) override;
- // Called when a specific Service Worker scope was accessed.
- // If access was blocked due to the user's content settings,
- // |blocked_by_policy_javascript| or/and |blocked_by_policy_cookie| should be
- // true, and this function should invoke OnContentBlocked for JavaScript
- // or/and cookies respectively.
- void OnServiceWorkerAccessed(
- content::NavigationHandle* navigation,
- const GURL& scope,
- content::AllowServiceWorkerResult allowed) override;
- void OnServiceWorkerAccessed(
- content::RenderFrameHost* frame,
- const GURL& scope,
- content::AllowServiceWorkerResult allowed) override;
+ // Notifies all registered |SiteDataObserver|s.
+ void NotifySiteDataObservers();
+
+ private:
+ friend class content::WebContentsUserData<WebContentsHandler>;
+
+ // Keeps track of cookie and service worker access during a navigation.
+ // These types of access can happen for the current page or for a new
+ // navigation (think cookies sent in the HTTP request or service worker
+ // being run to serve a fetch request). A navigation might fail to
+ // commit in which case we have to handle it as if it had never
+ // occurred. So we cache all cookies and service worker accesses that
+ // happen during a navigation and only apply the changes if the
+ // navigation commits.
+ struct InflightNavigationContentSettings {
+ InflightNavigationContentSettings();
+ InflightNavigationContentSettings(
+ const InflightNavigationContentSettings&);
+ InflightNavigationContentSettings(InflightNavigationContentSettings&&);
+
+ ~InflightNavigationContentSettings();
+
+ InflightNavigationContentSettings& operator=(
+ InflightNavigationContentSettings&&);
+
+ std::vector<content::CookieAccessDetails> cookie_accesses;
+ std::vector<std::pair<GURL, content::AllowServiceWorkerResult>>
+ service_worker_accesses;
+ };
+
+ // Applies all stored events for the given navigation to the current main
+ // document.
+ void TransferNavigationContentSettingsToCommittedDocument(
+ const InflightNavigationContentSettings& navigation_settings,
+ content::RenderFrameHost* rfh);
+
+ // content::WebContentsObserver overrides.
+ void RenderFrameForInterstitialPageCreated(
+ content::RenderFrameHost* render_frame_host) override;
+ void DidStartNavigation(
+ content::NavigationHandle* navigation_handle) override;
+ void ReadyToCommitNavigation(
+ content::NavigationHandle* navigation_handle) override;
+ void DidFinishNavigation(
+ content::NavigationHandle* navigation_handle) override;
+ // TODO(carlscab): Change interface to pass target RenderFrameHost
+ void AppCacheAccessed(const GURL& manifest_url,
+ bool blocked_by_policy) override;
+ void OnCookiesAccessed(
+ content::NavigationHandle* navigation,
+ const content::CookieAccessDetails& details) override;
+ void OnCookiesAccessed(
+ content::RenderFrameHost* rfh,
+ const content::CookieAccessDetails& details) override;
+ // Called when a specific Service Worker scope was accessed.
+ // If access was blocked due to the user's content settings,
+ // |blocked_by_policy_javascript| or/and |blocked_by_policy_cookie|
+ // should be true, and this function should invoke OnContentBlocked for
+ // JavaScript or/and cookies respectively.
+ void OnServiceWorkerAccessed(
+ content::NavigationHandle* navigation,
+ const GURL& scope,
+ content::AllowServiceWorkerResult allowed) override;
+ void OnServiceWorkerAccessed(
+ content::RenderFrameHost* frame,
+ const GURL& scope,
+ content::AllowServiceWorkerResult allowed) override;
+
+ std::unique_ptr<Delegate> delegate_;
+
+ HostContentSettingsMap* map_;
+
+ // All currently registered |SiteDataObserver|s.
+ base::ObserverList<SiteDataObserver>::Unchecked observer_list_;
+
+ // Keeps track of currently inflight navigations. Updates for those are
+ // kept aside until the navigation commits.
+ std::unordered_map<content::NavigationHandle*,
+ InflightNavigationContentSettings>
+ inflight_navigation_settings_;
+
+ WEB_CONTENTS_USER_DATA_KEY_DECL();
+ };
+
+ explicit TabSpecificContentSettings(
+ TabSpecificContentSettings::WebContentsHandler& handler,
+ Delegate* delegate);
+
+ void AppCacheAccessed(const GURL& manifest_url, bool blocked_by_policy);
// content_settings::Observer implementation.
void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
@@ -392,25 +487,15 @@ class TabSpecificContentSettings
ContentSettingsType content_type,
const std::string& resource_identifier) override;
- // Notifies all registered |SiteDataObserver|s.
- void NotifySiteDataObservers();
-
// Clears settings changed by the user via PageInfo since the last navigation.
void ClearContentSettingsChangedViaPageInfo();
- // Updates Geolocation settings on navigation.
- void GeolocationDidNavigate(content::NavigationHandle* navigation_handle);
-
- // Updates MIDI settings on navigation.
- void MidiDidNavigate(content::NavigationHandle* navigation_handle);
+ WebContentsHandler& handler_;
+ content::RenderFrameHost* main_frame_;
- // Updates the list of allowed and blocked cookies.
- void OnCookiesAccessedImpl(const content::CookieAccessDetails& details);
+ Delegate* delegate_;
- std::unique_ptr<Delegate> delegate_;
-
- // All currently registered |SiteDataObserver|s.
- base::ObserverList<SiteDataObserver>::Unchecked observer_list_;
+ GURL visible_url_;
struct ContentSettingsStatus {
bool blocked;
@@ -427,10 +512,10 @@ class TabSpecificContentSettings
browsing_data::LocalSharedObjectsContainer blocked_local_shared_objects_;
// Manages information about Geolocation API usage in this page.
- ContentSettingsUsagesState geolocation_usages_state_;
+ std::unique_ptr<ContentSettingsUsagesState> geolocation_usages_state_;
// Manages information about MIDI usages in this page.
- ContentSettingsUsagesState midi_usages_state_;
+ std::unique_ptr<ContentSettingsUsagesState> midi_usages_state_;
// Stores whether the user can load blocked plugins on this page.
bool load_plugins_link_enabled_;
@@ -464,7 +549,9 @@ class TabSpecificContentSettings
// navigation. Used to determine whether to display the settings in page info.
std::set<ContentSettingsType> content_settings_changed_via_page_info_;
- WEB_CONTENTS_USER_DATA_KEY_DECL();
+ RENDER_DOCUMENT_HOST_USER_DATA_KEY_DECL();
+
+ base::WeakPtrFactory<TabSpecificContentSettings> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(TabSpecificContentSettings);
};
diff --git a/chromium/components/content_settings/browser/tab_specific_content_settings_unittest.cc b/chromium/components/content_settings/browser/tab_specific_content_settings_unittest.cc
index 2ac8dc5c645..9477ad9153b 100644
--- a/chromium/components/content_settings/browser/tab_specific_content_settings_unittest.cc
+++ b/chromium/components/content_settings/browser/tab_specific_content_settings_unittest.cc
@@ -9,10 +9,13 @@
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "components/content_settings/browser/test_tab_specific_content_settings_delegate.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/security_state/core/security_state.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/mock_navigation_handle.h"
+#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_options.h"
@@ -25,9 +28,8 @@ namespace {
class MockSiteDataObserver
: public TabSpecificContentSettings::SiteDataObserver {
public:
- explicit MockSiteDataObserver(
- TabSpecificContentSettings* tab_specific_content_settings)
- : SiteDataObserver(tab_specific_content_settings) {}
+ explicit MockSiteDataObserver(content::WebContents* web_contents)
+ : SiteDataObserver(web_contents) {}
~MockSiteDataObserver() override = default;
@@ -45,11 +47,12 @@ class TabSpecificContentSettingsTest
void SetUp() override {
RenderViewHostTestHarness::SetUp();
HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
- security_state::RegisterProfilePrefs(prefs_.registry());
settings_map_ = base::MakeRefCounted<HostContentSettingsMap>(
&prefs_, false, false, false, false);
TabSpecificContentSettings::CreateForWebContents(
- web_contents(), std::make_unique<TestDelegate>(this));
+ web_contents(),
+ std::make_unique<TestTabSpecificContentSettingsDelegate>(
+ &prefs_, settings_map_.get()));
}
void TearDown() override {
@@ -59,57 +62,18 @@ class TabSpecificContentSettingsTest
HostContentSettingsMap* settings_map() { return settings_map_.get(); }
- private:
- class TestDelegate : public TabSpecificContentSettings::Delegate {
- public:
- explicit TestDelegate(TabSpecificContentSettingsTest* test) : test_(test) {}
-
- void UpdateLocationBar() override {}
-
- void SetContentSettingRules(
- content::RenderProcessHost* process,
- const RendererContentSettingRules& rules) override {}
-
- PrefService* GetPrefs() override { return &test_->prefs_; }
-
- HostContentSettingsMap* GetSettingsMap() override {
- return test_->settings_map_.get();
- }
-
- std::vector<storage::FileSystemType> GetAdditionalFileSystemTypes()
- override {
- return {};
- }
-
- browsing_data::CookieHelper::IsDeletionDisabledCallback
- GetIsDeletionDisabledCallback() override {
- return base::NullCallback();
- }
-
- bool IsMicrophoneCameraStateChanged(
- TabSpecificContentSettings::MicrophoneCameraState
- microphone_camera_state,
- const std::string& media_stream_selected_audio_device,
- const std::string& media_stream_selected_video_device) override {
- return false;
- }
-
- TabSpecificContentSettings::MicrophoneCameraState GetMicrophoneCameraState()
- override {
- return TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED;
- }
-
- void OnContentBlocked(ContentSettingsType type) override {}
-
- private:
- TabSpecificContentSettingsTest* test_;
- };
+ content::WebContentsObserver* GetHandle() {
+ return TabSpecificContentSettings::GetWebContentsObserverForTest(
+ web_contents());
+ }
+ private:
sync_preferences::TestingPrefServiceSyncable prefs_;
scoped_refptr<HostContentSettingsMap> settings_map_;
};
TEST_F(TabSpecificContentSettingsTest, BlockedContent) {
+ NavigateAndCommit(GURL("http://google.com"));
TabSpecificContentSettings* content_settings =
TabSpecificContentSettings::FromWebContents(web_contents());
@@ -136,13 +100,14 @@ TEST_F(TabSpecificContentSettingsTest, BlockedContent) {
std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
origin, "A=B", base::Time::Now(), base::nullopt /* server_time */));
ASSERT_TRUE(cookie1);
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kChange,
- origin,
- origin,
- {*cookie1},
- false});
+ GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kChange,
+ origin,
+ origin,
+ {*cookie1},
+ false});
+ content_settings =
+ TabSpecificContentSettings::FromWebContents(web_contents());
#if !defined(OS_ANDROID)
content_settings->OnContentBlocked(ContentSettingsType::IMAGES);
#endif
@@ -173,64 +138,54 @@ TEST_F(TabSpecificContentSettingsTest, BlockedContent) {
content_settings->IsContentBlocked(ContentSettingsType::MEDIASTREAM_MIC));
EXPECT_TRUE(content_settings->IsContentBlocked(
ContentSettingsType::MEDIASTREAM_CAMERA));
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kChange,
- origin,
- origin,
- {*cookie1},
- false});
+ GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kChange,
+ origin,
+ origin,
+ {*cookie1},
+ false});
// Block a cookie.
std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
origin, "C=D", base::Time::Now(), base::nullopt /* server_time */));
ASSERT_TRUE(cookie2);
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kChange,
- origin,
- origin,
- {*cookie2},
- true});
+ GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kChange,
+ origin,
+ origin,
+ {*cookie2},
+ true});
EXPECT_TRUE(content_settings->IsContentBlocked(ContentSettingsType::COOKIES));
// Block a javascript during a navigation.
- content::MockNavigationHandle navigation_handle;
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnServiceWorkerAccessed(
- &navigation_handle, GURL("http://google.com"),
- content::AllowServiceWorkerResult::FromPolicy(true, false));
- EXPECT_TRUE(
+ // Create a pending navigation.
+ std::unique_ptr<content::NavigationSimulator> simulator =
+ content::NavigationSimulator::CreateBrowserInitiated(
+ GURL("http://google.com"), web_contents());
+ simulator->SetTransition(ui::PAGE_TRANSITION_LINK);
+ simulator->Start();
+ GetHandle()->OnServiceWorkerAccessed(
+ simulator->GetNavigationHandle(), GURL("http://google.com"),
+ content::AllowServiceWorkerResult::FromPolicy(true, false));
+ content_settings =
+ TabSpecificContentSettings::FromWebContents(web_contents());
+ EXPECT_FALSE(
content_settings->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
+ simulator->Commit();
+ content_settings =
+ TabSpecificContentSettings::FromWebContents(web_contents());
// Block a javascript when page starts to start ServiceWorker.
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnServiceWorkerAccessed(
- web_contents()->GetMainFrame(), GURL("http://google.com"),
- content::AllowServiceWorkerResult::FromPolicy(true, false));
+ GetHandle()->OnServiceWorkerAccessed(
+ web_contents()->GetMainFrame(), GURL("http://google.com"),
+ content::AllowServiceWorkerResult::FromPolicy(true, false));
EXPECT_TRUE(
content_settings->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
// Reset blocked content settings.
- content_settings->ClearContentSettingsExceptForNavigationRelatedSettings();
-
- // Reset blocked content settings.
- content_settings->ClearContentSettingsExceptForNavigationRelatedSettings();
-#if !defined(OS_ANDROID)
- EXPECT_FALSE(content_settings->IsContentBlocked(ContentSettingsType::IMAGES));
- EXPECT_FALSE(
- content_settings->IsContentBlocked(ContentSettingsType::PLUGINS));
-#endif
- EXPECT_TRUE(
- content_settings->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
- EXPECT_TRUE(content_settings->IsContentBlocked(ContentSettingsType::COOKIES));
- EXPECT_FALSE(content_settings->IsContentBlocked(ContentSettingsType::POPUPS));
- EXPECT_FALSE(
- content_settings->IsContentBlocked(ContentSettingsType::MEDIASTREAM_MIC));
- EXPECT_FALSE(content_settings->IsContentBlocked(
- ContentSettingsType::MEDIASTREAM_CAMERA));
-
- content_settings->ClearNavigationRelatedContentSettings();
+ NavigateAndCommit(GURL("http://google.com"));
+ content_settings =
+ TabSpecificContentSettings::FromWebContents(web_contents());
#if !defined(OS_ANDROID)
EXPECT_FALSE(content_settings->IsContentBlocked(ContentSettingsType::IMAGES));
EXPECT_FALSE(
@@ -248,6 +203,7 @@ TEST_F(TabSpecificContentSettingsTest, BlockedContent) {
}
TEST_F(TabSpecificContentSettingsTest, BlockedFileSystems) {
+ NavigateAndCommit(GURL("http://google.com"));
TabSpecificContentSettings* content_settings =
TabSpecificContentSettings::FromWebContents(web_contents());
@@ -262,6 +218,7 @@ TEST_F(TabSpecificContentSettingsTest, BlockedFileSystems) {
}
TEST_F(TabSpecificContentSettingsTest, AllowedContent) {
+ NavigateAndCommit(GURL("http://google.com"));
TabSpecificContentSettings* content_settings =
TabSpecificContentSettings::FromWebContents(web_contents());
@@ -281,13 +238,12 @@ TEST_F(TabSpecificContentSettingsTest, AllowedContent) {
std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
origin, "A=B", base::Time::Now(), base::nullopt /* server_time */));
ASSERT_TRUE(cookie1);
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kChange,
- origin,
- origin,
- {*cookie1},
- false});
+ GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kChange,
+ origin,
+ origin,
+ {*cookie1},
+ false});
ASSERT_TRUE(content_settings->IsContentAllowed(ContentSettingsType::COOKIES));
ASSERT_FALSE(
content_settings->IsContentBlocked(ContentSettingsType::COOKIES));
@@ -296,18 +252,18 @@ TEST_F(TabSpecificContentSettingsTest, AllowedContent) {
std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
origin, "C=D", base::Time::Now(), base::nullopt /* server_time */));
ASSERT_TRUE(cookie2);
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kChange,
- origin,
- origin,
- {*cookie2},
- true});
+ GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kChange,
+ origin,
+ origin,
+ {*cookie2},
+ true});
ASSERT_TRUE(content_settings->IsContentAllowed(ContentSettingsType::COOKIES));
ASSERT_TRUE(content_settings->IsContentBlocked(ContentSettingsType::COOKIES));
}
TEST_F(TabSpecificContentSettingsTest, EmptyCookieList) {
+ NavigateAndCommit(GURL("http://google.com"));
TabSpecificContentSettings* content_settings =
TabSpecificContentSettings::FromWebContents(web_contents());
@@ -315,11 +271,10 @@ TEST_F(TabSpecificContentSettingsTest, EmptyCookieList) {
content_settings->IsContentAllowed(ContentSettingsType::COOKIES));
ASSERT_FALSE(
content_settings->IsContentBlocked(ContentSettingsType::COOKIES));
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(
- web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kRead, GURL("http://google.com"),
- GURL("http://google.com"), net::CookieList(), true});
+ GetHandle()->OnCookiesAccessed(
+ web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kRead, GURL("http://google.com"),
+ GURL("http://google.com"), net::CookieList(), true});
ASSERT_FALSE(
content_settings->IsContentAllowed(ContentSettingsType::COOKIES));
ASSERT_FALSE(
@@ -327,9 +282,10 @@ TEST_F(TabSpecificContentSettingsTest, EmptyCookieList) {
}
TEST_F(TabSpecificContentSettingsTest, SiteDataObserver) {
+ NavigateAndCommit(GURL("http://google.com"));
TabSpecificContentSettings* content_settings =
TabSpecificContentSettings::FromWebContents(web_contents());
- MockSiteDataObserver mock_observer(content_settings);
+ MockSiteDataObserver mock_observer(web_contents());
EXPECT_CALL(mock_observer, OnSiteDataAccessed()).Times(6);
bool blocked_by_policy = false;
@@ -337,13 +293,12 @@ TEST_F(TabSpecificContentSettingsTest, SiteDataObserver) {
std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
origin, "A=B", base::Time::Now(), base::nullopt /* server_time */));
ASSERT_TRUE(cookie);
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kChange,
- origin,
- origin,
- {*cookie},
- blocked_by_policy});
+ GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kChange,
+ origin,
+ origin,
+ {*cookie},
+ blocked_by_policy});
net::CookieList cookie_list;
std::unique_ptr<net::CanonicalCookie> other_cookie(
@@ -353,11 +308,10 @@ TEST_F(TabSpecificContentSettingsTest, SiteDataObserver) {
ASSERT_TRUE(other_cookie);
cookie_list.push_back(*other_cookie);
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(
- web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kRead, GURL("http://google.com"),
- GURL("http://google.com"), cookie_list, blocked_by_policy});
+ GetHandle()->OnCookiesAccessed(
+ web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kRead, GURL("http://google.com"),
+ GURL("http://google.com"), cookie_list, blocked_by_policy});
content_settings->OnFileSystemAccessed(GURL("http://google.com"),
blocked_by_policy);
content_settings->OnIndexedDBAccessed(GURL("http://google.com"),
@@ -369,19 +323,19 @@ TEST_F(TabSpecificContentSettingsTest, SiteDataObserver) {
}
TEST_F(TabSpecificContentSettingsTest, LocalSharedObjectsContainer) {
+ NavigateAndCommit(GURL("http://google.com"));
TabSpecificContentSettings* content_settings =
TabSpecificContentSettings::FromWebContents(web_contents());
bool blocked_by_policy = false;
auto cookie = net::CanonicalCookie::Create(GURL("http://google.com"), "k=v",
base::Time::Now(),
base::nullopt /* server_time */);
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kRead,
- GURL("http://google.com"),
- GURL("http://google.com"),
- {*cookie},
- blocked_by_policy});
+ GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kRead,
+ GURL("http://google.com"),
+ GURL("http://google.com"),
+ {*cookie},
+ blocked_by_policy});
content_settings->OnFileSystemAccessed(GURL("https://www.google.com"),
blocked_by_policy);
content_settings->OnIndexedDBAccessed(GURL("https://localhost"),
@@ -406,6 +360,7 @@ TEST_F(TabSpecificContentSettingsTest, LocalSharedObjectsContainer) {
}
TEST_F(TabSpecificContentSettingsTest, LocalSharedObjectsContainerCookie) {
+ NavigateAndCommit(GURL("http://google.com"));
TabSpecificContentSettings* content_settings =
TabSpecificContentSettings::FromWebContents(web_contents());
bool blocked_by_policy = false;
@@ -421,24 +376,22 @@ TEST_F(TabSpecificContentSettingsTest, LocalSharedObjectsContainerCookie) {
auto cookie4 = net::CanonicalCookie::Create(
GURL("http://www.google.com"), "k4=v; Domain=.www.google.com",
base::Time::Now(), base::nullopt /* server_time */);
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kRead,
- GURL("http://www.google.com"),
- GURL("http://www.google.com"),
- {*cookie1, *cookie2, *cookie3, *cookie4},
- blocked_by_policy});
+ GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kRead,
+ GURL("http://www.google.com"),
+ GURL("http://www.google.com"),
+ {*cookie1, *cookie2, *cookie3, *cookie4},
+ blocked_by_policy});
auto cookie5 = net::CanonicalCookie::Create(GURL("https://www.google.com"),
"k5=v", base::Time::Now(),
base::nullopt /* server_time */);
- static_cast<content::WebContentsObserver*>(content_settings)
- ->OnCookiesAccessed(web_contents()->GetMainFrame(),
- {content::CookieAccessDetails::Type::kRead,
- GURL("https://www.google.com"),
- GURL("https://www.google.com"),
- {*cookie5},
- blocked_by_policy});
+ GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
+ {content::CookieAccessDetails::Type::kRead,
+ GURL("https://www.google.com"),
+ GURL("https://www.google.com"),
+ {*cookie5},
+ blocked_by_policy});
const auto& objects = content_settings->allowed_local_shared_objects();
EXPECT_EQ(5u, objects.GetObjectCount());
diff --git a/chromium/components/content_settings/browser/test_tab_specific_content_settings_delegate.cc b/chromium/components/content_settings/browser/test_tab_specific_content_settings_delegate.cc
new file mode 100644
index 00000000000..bfe9e77af54
--- /dev/null
+++ b/chromium/components/content_settings/browser/test_tab_specific_content_settings_delegate.cc
@@ -0,0 +1,63 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/content_settings/browser/test_tab_specific_content_settings_delegate.h"
+
+namespace content_settings {
+
+TestTabSpecificContentSettingsDelegate::TestTabSpecificContentSettingsDelegate(
+ PrefService* prefs,
+ HostContentSettingsMap* settings_map)
+ : prefs_(prefs), settings_map_(settings_map) {}
+
+TestTabSpecificContentSettingsDelegate::
+ ~TestTabSpecificContentSettingsDelegate() = default;
+
+void TestTabSpecificContentSettingsDelegate::UpdateLocationBar() {}
+
+void TestTabSpecificContentSettingsDelegate::SetContentSettingRules(
+ content::RenderProcessHost* process,
+ const RendererContentSettingRules& rules) {}
+
+PrefService* TestTabSpecificContentSettingsDelegate::GetPrefs() {
+ return prefs_;
+}
+
+HostContentSettingsMap*
+TestTabSpecificContentSettingsDelegate::GetSettingsMap() {
+ return settings_map_.get();
+}
+
+ContentSetting TestTabSpecificContentSettingsDelegate::GetEmbargoSetting(
+ const GURL& request_origin,
+ ContentSettingsType permission) {
+ return ContentSetting::CONTENT_SETTING_ASK;
+}
+
+std::vector<storage::FileSystemType>
+TestTabSpecificContentSettingsDelegate::GetAdditionalFileSystemTypes() {
+ return {};
+}
+
+browsing_data::CookieHelper::IsDeletionDisabledCallback
+TestTabSpecificContentSettingsDelegate::GetIsDeletionDisabledCallback() {
+ return base::NullCallback();
+}
+
+bool TestTabSpecificContentSettingsDelegate::IsMicrophoneCameraStateChanged(
+ TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state,
+ const std::string& media_stream_selected_audio_device,
+ const std::string& media_stream_selected_video_device) {
+ return false;
+}
+
+TabSpecificContentSettings::MicrophoneCameraState
+TestTabSpecificContentSettingsDelegate::GetMicrophoneCameraState() {
+ return TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED;
+}
+
+void TestTabSpecificContentSettingsDelegate::OnContentBlocked(
+ ContentSettingsType type) {}
+
+} // namespace content_settings
diff --git a/chromium/components/content_settings/browser/test_tab_specific_content_settings_delegate.h b/chromium/components/content_settings/browser/test_tab_specific_content_settings_delegate.h
new file mode 100644
index 00000000000..9fde1406745
--- /dev/null
+++ b/chromium/components/content_settings/browser/test_tab_specific_content_settings_delegate.h
@@ -0,0 +1,47 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CONTENT_SETTINGS_BROWSER_TEST_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_
+#define COMPONENTS_CONTENT_SETTINGS_BROWSER_TEST_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "components/content_settings/browser/tab_specific_content_settings.h"
+
+namespace content_settings {
+
+class TestTabSpecificContentSettingsDelegate
+ : public TabSpecificContentSettings::Delegate {
+ public:
+ TestTabSpecificContentSettingsDelegate(PrefService* prefs,
+ HostContentSettingsMap* settings_map);
+ ~TestTabSpecificContentSettingsDelegate() override;
+
+ // TabSpecificContentSettings::Delegate:
+ void UpdateLocationBar() override;
+ void SetContentSettingRules(
+ content::RenderProcessHost* process,
+ const RendererContentSettingRules& rules) override;
+ PrefService* GetPrefs() override;
+ HostContentSettingsMap* GetSettingsMap() override;
+ ContentSetting GetEmbargoSetting(const GURL& request_origin,
+ ContentSettingsType permission) override;
+ std::vector<storage::FileSystemType> GetAdditionalFileSystemTypes() override;
+ browsing_data::CookieHelper::IsDeletionDisabledCallback
+ GetIsDeletionDisabledCallback() override;
+ bool IsMicrophoneCameraStateChanged(
+ TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state,
+ const std::string& media_stream_selected_audio_device,
+ const std::string& media_stream_selected_video_device) override;
+ TabSpecificContentSettings::MicrophoneCameraState GetMicrophoneCameraState()
+ override;
+ void OnContentBlocked(ContentSettingsType type) override;
+
+ private:
+ PrefService* prefs_;
+ scoped_refptr<HostContentSettingsMap> settings_map_;
+};
+
+} // namespace content_settings
+
+#endif // COMPONENTS_CONTENT_SETTINGS_BROWSER_TEST_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_
diff --git a/chromium/components/content_settings/browser/ui/BUILD.gn b/chromium/components/content_settings/browser/ui/BUILD.gn
new file mode 100644
index 00000000000..0f3e91d4da0
--- /dev/null
+++ b/chromium/components/content_settings/browser/ui/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2020 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.
+
+source_set("ui") {
+ sources = [
+ "cookie_controls_controller.cc",
+ "cookie_controls_controller.h",
+ "cookie_controls_view.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/browsing_data/content",
+ "//components/content_settings/browser",
+ "//components/content_settings/core/browser",
+ "//components/prefs",
+ "//content/public/browser",
+ "//content/public/common",
+ ]
+}
diff --git a/chromium/components/content_settings/browser/ui/cookie_controls_controller.cc b/chromium/components/content_settings/browser/ui/cookie_controls_controller.cc
new file mode 100644
index 00000000000..ef908305ac0
--- /dev/null
+++ b/chromium/components/content_settings/browser/ui/cookie_controls_controller.cc
@@ -0,0 +1,161 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/content_settings/browser/ui/cookie_controls_controller.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
+#include "components/browsing_data/content/local_shared_objects_container.h"
+#include "components/content_settings/browser/tab_specific_content_settings.h"
+#include "components/content_settings/browser/ui/cookie_controls_view.h"
+#include "components/content_settings/core/browser/content_settings_utils.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
+#include "components/content_settings/core/common/content_settings.h"
+#include "components/content_settings/core/common/cookie_controls_enforcement.h"
+#include "components/content_settings/core/common/cookie_controls_status.h"
+#include "components/content_settings/core/common/pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/reload_type.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/url_constants.h"
+
+using base::UserMetricsAction;
+
+namespace content_settings {
+
+CookieControlsController::CookieControlsController(
+ scoped_refptr<CookieSettings> cookie_settings,
+ scoped_refptr<CookieSettings> original_cookie_settings)
+ : cookie_settings_(cookie_settings),
+ original_cookie_settings_(original_cookie_settings) {
+ cookie_observer_.Add(cookie_settings_.get());
+}
+
+CookieControlsController::~CookieControlsController() = default;
+
+void CookieControlsController::OnUiClosing() {
+ auto* web_contents = GetWebContents();
+ if (should_reload_ && web_contents && !web_contents->IsBeingDestroyed())
+ web_contents->GetController().Reload(content::ReloadType::NORMAL, true);
+ should_reload_ = false;
+}
+
+void CookieControlsController::Update(content::WebContents* web_contents) {
+ DCHECK(web_contents);
+ if (!tab_observer_ || GetWebContents() != web_contents)
+ tab_observer_ = std::make_unique<TabObserver>(this, web_contents);
+ auto status = GetStatus(web_contents);
+ int blocked_count = GetBlockedCookieCount();
+ for (auto& observer : observers_)
+ observer.OnStatusChanged(status.first, status.second, blocked_count);
+}
+
+std::pair<CookieControlsStatus, CookieControlsEnforcement>
+CookieControlsController::GetStatus(content::WebContents* web_contents) {
+ if (!cookie_settings_->IsCookieControlsEnabled()) {
+ return {CookieControlsStatus::kDisabled,
+ CookieControlsEnforcement::kNoEnforcement};
+ }
+ const GURL& url = web_contents->GetURL();
+ if (url.SchemeIs(content::kChromeUIScheme) ||
+ url.SchemeIs(kExtensionScheme)) {
+ return {CookieControlsStatus::kDisabled,
+ CookieControlsEnforcement::kNoEnforcement};
+ }
+
+ SettingSource source;
+ bool is_allowed = cookie_settings_->IsThirdPartyAccessAllowed(
+ web_contents->GetURL(), &source);
+
+ CookieControlsStatus status = is_allowed
+ ? CookieControlsStatus::kDisabledForSite
+ : CookieControlsStatus::kEnabled;
+ CookieControlsEnforcement enforcement;
+ if (source == SETTING_SOURCE_POLICY) {
+ enforcement = CookieControlsEnforcement::kEnforcedByPolicy;
+ } else if (is_allowed && original_cookie_settings_ &&
+ original_cookie_settings_->ShouldBlockThirdPartyCookies() &&
+ original_cookie_settings_->IsThirdPartyAccessAllowed(
+ web_contents->GetURL(), nullptr /* source */)) {
+ // TODO(crbug.com/1015767): Rules from regular mode can't be temporarily
+ // overridden in incognito.
+ enforcement = CookieControlsEnforcement::kEnforcedByCookieSetting;
+ } else {
+ enforcement = CookieControlsEnforcement::kNoEnforcement;
+ }
+ return {status, enforcement};
+}
+
+void CookieControlsController::OnCookieBlockingEnabledForSite(
+ bool block_third_party_cookies) {
+ if (block_third_party_cookies) {
+ base::RecordAction(UserMetricsAction("CookieControls.Bubble.TurnOn"));
+ should_reload_ = false;
+ cookie_settings_->ResetThirdPartyCookieSetting(GetWebContents()->GetURL());
+ } else {
+ base::RecordAction(UserMetricsAction("CookieControls.Bubble.TurnOff"));
+ should_reload_ = true;
+ cookie_settings_->SetThirdPartyCookieSetting(
+ GetWebContents()->GetURL(), ContentSetting::CONTENT_SETTING_ALLOW);
+ }
+}
+
+int CookieControlsController::GetBlockedCookieCount() {
+ auto* tscs =
+ content_settings::TabSpecificContentSettings::GetForCurrentDocument(
+ tab_observer_->web_contents()->GetMainFrame());
+ if (tscs) {
+ return tscs->blocked_local_shared_objects().GetObjectCount();
+ } else {
+ return 0;
+ }
+}
+
+void CookieControlsController::PresentBlockedCookieCounter() {
+ int blocked_cookies = GetBlockedCookieCount();
+ for (auto& observer : observers_)
+ observer.OnBlockedCookiesCountChanged(blocked_cookies);
+}
+
+void CookieControlsController::OnThirdPartyCookieBlockingChanged(
+ bool block_third_party_cookies) {
+ if (GetWebContents())
+ Update(GetWebContents());
+}
+
+void CookieControlsController::OnCookieSettingChanged() {
+ if (GetWebContents())
+ Update(GetWebContents());
+}
+
+content::WebContents* CookieControlsController::GetWebContents() {
+ if (!tab_observer_)
+ return nullptr;
+ return tab_observer_->web_contents();
+}
+
+void CookieControlsController::AddObserver(CookieControlsView* obs) {
+ observers_.AddObserver(obs);
+}
+
+void CookieControlsController::RemoveObserver(CookieControlsView* obs) {
+ observers_.RemoveObserver(obs);
+}
+
+CookieControlsController::TabObserver::TabObserver(
+ CookieControlsController* cookie_controls,
+ content::WebContents* web_contents)
+ : content_settings::TabSpecificContentSettings::SiteDataObserver(
+ web_contents),
+ cookie_controls_(cookie_controls) {}
+
+void CookieControlsController::TabObserver::OnSiteDataAccessed() {
+ cookie_controls_->PresentBlockedCookieCounter();
+}
+
+} // namespace content_settings
diff --git a/chromium/components/content_settings/browser/ui/cookie_controls_controller.h b/chromium/components/content_settings/browser/ui/cookie_controls_controller.h
new file mode 100644
index 00000000000..f7aeb504d6d
--- /dev/null
+++ b/chromium/components/content_settings/browser/ui/cookie_controls_controller.h
@@ -0,0 +1,106 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CONTENT_SETTINGS_BROWSER_UI_COOKIE_CONTROLS_CONTROLLER_H_
+#define COMPONENTS_CONTENT_SETTINGS_BROWSER_UI_COOKIE_CONTROLS_CONTROLLER_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/observer_list.h"
+#include "components/content_settings/browser/tab_specific_content_settings.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
+#include "components/content_settings/core/common/cookie_controls_enforcement.h"
+#include "components/content_settings/core/common/cookie_controls_status.h"
+#include "components/prefs/pref_change_registrar.h"
+#include "content/public/browser/web_contents.h"
+
+namespace content {
+class WebContents;
+} // namespace content
+
+namespace content_settings {
+
+class CookieSettings;
+class CookieControlsView;
+
+// Handles the tab specific state for cookie controls.
+class CookieControlsController : content_settings::CookieSettings::Observer {
+ public:
+ CookieControlsController(
+ scoped_refptr<content_settings::CookieSettings> cookie_settings,
+ scoped_refptr<content_settings::CookieSettings> original_cookie_settings);
+ CookieControlsController(const CookieControlsController& other) = delete;
+ CookieControlsController& operator=(const CookieControlsController& other) =
+ delete;
+ ~CookieControlsController() override;
+
+ // Called when the web_contents has changed.
+ void Update(content::WebContents* web_contents);
+
+ // Called when CookieControlsView is closing.
+ void OnUiClosing();
+
+ // Called when the user clicks on the button to enable/disable cookie
+ // blocking.
+ void OnCookieBlockingEnabledForSite(bool block_third_party_cookies);
+
+ void AddObserver(CookieControlsView* obs);
+ void RemoveObserver(CookieControlsView* obs);
+
+ private:
+ // The observed WebContents changes during the lifetime of the
+ // CookieControlsController. SiteDataObserver can't change the observed
+ // object, so we need an inner class that can be recreated when necessary.
+ // TODO(dullweber): Make it possible to change the observed class and maybe
+ // convert SiteDataObserver to a pure virtual interface.
+ class TabObserver
+ : public content_settings::TabSpecificContentSettings::SiteDataObserver {
+ public:
+ TabObserver(CookieControlsController* cookie_controls,
+ content::WebContents* web_contents);
+
+ // TabSpecificContentSettings::SiteDataObserver:
+ void OnSiteDataAccessed() override;
+
+ private:
+ CookieControlsController* cookie_controls_;
+
+ DISALLOW_COPY_AND_ASSIGN(TabObserver);
+ };
+
+ void OnThirdPartyCookieBlockingChanged(
+ bool block_third_party_cookies) override;
+ void OnCookieSettingChanged() override;
+
+ // Determine the CookieControlsStatus based on |web_contents|.
+ std::pair<CookieControlsStatus, CookieControlsEnforcement> GetStatus(
+ content::WebContents* web_contents);
+
+ // Updates the blocked cookie count of |icon_|.
+ void PresentBlockedCookieCounter();
+
+ // Returns the number of blocked cookies.
+ int GetBlockedCookieCount();
+
+ content::WebContents* GetWebContents();
+
+ std::unique_ptr<TabObserver> tab_observer_;
+ scoped_refptr<content_settings::CookieSettings> cookie_settings_;
+ // Cookie_settings for the original profile associated with
+ // |cookie_settings_|, if there is one. For example, in Chrome, this
+ // corresponds to the regular profile when |cookie_settings_| is incognito.
+ // This may be null.
+ scoped_refptr<content_settings::CookieSettings> original_cookie_settings_;
+
+ ScopedObserver<content_settings::CookieSettings,
+ content_settings::CookieSettings::Observer>
+ cookie_observer_{this};
+
+ bool should_reload_ = false;
+
+ base::ObserverList<CookieControlsView> observers_;
+};
+
+} // namespace content_settings
+
+#endif // COMPONENTS_CONTENT_SETTINGS_BROWSER_UI_COOKIE_CONTROLS_CONTROLLER_H_
diff --git a/chromium/components/content_settings/browser/ui/cookie_controls_view.h b/chromium/components/content_settings/browser/ui/cookie_controls_view.h
new file mode 100644
index 00000000000..f833db0b6d7
--- /dev/null
+++ b/chromium/components/content_settings/browser/ui/cookie_controls_view.h
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CONTENT_SETTINGS_BROWSER_UI_COOKIE_CONTROLS_VIEW_H_
+#define COMPONENTS_CONTENT_SETTINGS_BROWSER_UI_COOKIE_CONTROLS_VIEW_H_
+
+#include "base/observer_list_types.h"
+#include "components/content_settings/core/common/cookie_controls_enforcement.h"
+#include "components/content_settings/core/common/cookie_controls_status.h"
+
+namespace content_settings {
+
+// Interface for the CookieControls UI.
+class CookieControlsView : public base::CheckedObserver {
+ public:
+ virtual void OnStatusChanged(CookieControlsStatus status,
+ CookieControlsEnforcement enforcement,
+ int blocked_cookies) = 0;
+ virtual void OnBlockedCookiesCountChanged(int blocked_cookies) = 0;
+};
+
+} // namespace content_settings
+
+#endif // COMPONENTS_CONTENT_SETTINGS_BROWSER_UI_COOKIE_CONTROLS_VIEW_H_
diff --git a/chromium/components/content_settings/core/browser/BUILD.gn b/chromium/components/content_settings/core/browser/BUILD.gn
index f4d4b5ab6d9..6d543a430d7 100644
--- a/chromium/components/content_settings/core/browser/BUILD.gn
+++ b/chromium/components/content_settings/core/browser/BUILD.gn
@@ -30,6 +30,7 @@ jumbo_static_library("browser") {
"content_settings_pref.h",
"content_settings_pref_provider.cc",
"content_settings_pref_provider.h",
+ "content_settings_provider.cc",
"content_settings_provider.h",
"content_settings_registry.cc",
"content_settings_registry.h",
diff --git a/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc b/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc
index e3a67aabb60..1b5f782d66b 100644
--- a/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc
@@ -20,16 +20,21 @@
#include "components/content_settings/core/browser/website_settings_info.h"
#include "components/content_settings/core/browser/website_settings_registry.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
+#include "components/content_settings/core/common/features.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
+namespace content_settings {
+
namespace {
struct PrefsForManagedContentSettingsMapEntry {
const char* pref_name;
ContentSettingsType content_type;
ContentSetting setting;
+ content_settings::WildcardsInPrimaryPattern wildcards_in_primary_pattern =
+ content_settings::WildcardsInPrimaryPattern::ALLOWED;
};
const PrefsForManagedContentSettingsMapEntry
@@ -57,9 +62,11 @@ const PrefsForManagedContentSettingsMapEntry
{prefs::kManagedNotificationsBlockedForUrls,
ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_BLOCK},
{prefs::kManagedPluginsAllowedForUrls, ContentSettingsType::PLUGINS,
- CONTENT_SETTING_ALLOW},
+ CONTENT_SETTING_ALLOW,
+ content_settings::WildcardsInPrimaryPattern::NOT_ALLOWED},
{prefs::kManagedPluginsBlockedForUrls, ContentSettingsType::PLUGINS,
- CONTENT_SETTING_BLOCK},
+ CONTENT_SETTING_BLOCK,
+ content_settings::WildcardsInPrimaryPattern::NOT_ALLOWED},
{prefs::kManagedPopupsAllowedForUrls, ContentSettingsType::POPUPS,
CONTENT_SETTING_ALLOW},
{prefs::kManagedPopupsBlockedForUrls, ContentSettingsType::POPUPS,
@@ -71,9 +78,30 @@ const PrefsForManagedContentSettingsMapEntry
{prefs::kManagedLegacyCookieAccessAllowedForDomains,
ContentSettingsType::LEGACY_COOKIE_ACCESS, CONTENT_SETTING_ALLOW}};
-} // namespace
+class VectorRuleIterator : public RuleIterator {
+ public:
+ VectorRuleIterator(const std::vector<Rule>::const_iterator& begin,
+ const std::vector<Rule>::const_iterator& end)
+ : current_rule(begin), end_rule(end) {}
-namespace content_settings {
+ ~VectorRuleIterator() override {}
+
+ bool HasNext() const override { return current_rule != end_rule; }
+
+ Rule Next() override {
+ Rule rule(current_rule->primary_pattern, current_rule->secondary_pattern,
+ current_rule->value.Clone(), current_rule->expiration,
+ current_rule->session_model);
+ current_rule++;
+ return rule;
+ }
+
+ private:
+ std::vector<Rule>::const_iterator current_rule;
+ std::vector<Rule>::const_iterator end_rule;
+};
+
+} // namespace
// The preferences used to manage the default policy value for
// ContentSettingsTypes.
@@ -236,6 +264,18 @@ std::unique_ptr<RuleIterator> PolicyProvider::GetRuleIterator(
return value_map_.GetRuleIterator(content_type, resource_identifier, &lock_);
}
+std::unique_ptr<RuleIterator> PolicyProvider::GetDiscardedRuleIterator(
+ ContentSettingsType content_type,
+ const ResourceIdentifier& resource_identifier,
+ bool incognito) const {
+ auto it = discarded_rules_value_map_.find(content_type);
+ if (it == discarded_rules_value_map_.end()) {
+ return std::make_unique<EmptyRuleIterator>(EmptyRuleIterator());
+ }
+ return std::make_unique<VectorRuleIterator>(it->second.begin(),
+ it->second.end());
+}
+
void PolicyProvider::GetContentSettingsFromPreferences(
OriginIdentifierValueMap* value_map) {
for (size_t i = 0; i < base::size(kPrefsForManagedContentSettingsMap); ++i) {
@@ -296,6 +336,18 @@ void PolicyProvider::GetContentSettingsFromPreferences(
->Get(content_type)
->SupportsEmbeddedExceptions());
+ if (base::FeatureList::IsEnabled(
+ content_settings::kDisallowWildcardsInPluginContentSettings) &&
+ kPrefsForManagedContentSettingsMap[i].wildcards_in_primary_pattern ==
+ WildcardsInPrimaryPattern::NOT_ALLOWED &&
+ pattern_pair.first.HasHostWildcards()) {
+ discarded_rules_value_map_[content_type].push_back(
+ Rule(pattern_pair.first, secondary_pattern,
+ base::Value(kPrefsForManagedContentSettingsMap[i].setting),
+ base::Time(), content_settings::SessionModel::Durable));
+ continue;
+ }
+
// Don't set a timestamp for policy settings.
value_map->SetValue(
pattern_pair.first, secondary_pattern, content_type,
diff --git a/chromium/components/content_settings/core/browser/content_settings_policy_provider.h b/chromium/components/content_settings/core/browser/content_settings_policy_provider.h
index 8b9e30d7413..f92702ba187 100644
--- a/chromium/components/content_settings/core/browser/content_settings_policy_provider.h
+++ b/chromium/components/content_settings/core/browser/content_settings_policy_provider.h
@@ -36,6 +36,11 @@ class PolicyProvider : public ObservableProvider {
const ResourceIdentifier& resource_identifier,
bool incognito) const override;
+ std::unique_ptr<RuleIterator> GetDiscardedRuleIterator(
+ ContentSettingsType content_type,
+ const ResourceIdentifier& resource_identifier,
+ bool incognito) const override;
+
bool SetWebsiteSetting(
const ContentSettingsPattern& primary_pattern,
const ContentSettingsPattern& secondary_pattern,
@@ -73,6 +78,8 @@ class PolicyProvider : public ObservableProvider {
OriginIdentifierValueMap value_map_;
+ std::map<ContentSettingsType, std::vector<Rule>> discarded_rules_value_map_;
+
PrefService* prefs_;
PrefChangeRegistrar pref_change_registrar_;
diff --git a/chromium/components/content_settings/core/browser/content_settings_pref.cc b/chromium/components/content_settings/core/browser/content_settings_pref.cc
index 9e8c7bf15d7..cd57f1a2a0b 100644
--- a/chromium/components/content_settings/core/browser/content_settings_pref.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_pref.cc
@@ -10,6 +10,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
+#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
diff --git a/chromium/components/content_settings/core/browser/content_settings_provider.cc b/chromium/components/content_settings/core/browser/content_settings_provider.cc
new file mode 100644
index 00000000000..f46f9682a4e
--- /dev/null
+++ b/chromium/components/content_settings/core/browser/content_settings_provider.cc
@@ -0,0 +1,14 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/content_settings/core/browser/content_settings_provider.h"
+
+namespace content_settings {
+std::unique_ptr<RuleIterator> ProviderInterface::GetDiscardedRuleIterator(
+ ContentSettingsType content_type,
+ const ResourceIdentifier& resource_identifier,
+ bool incognito) const {
+ return std::make_unique<EmptyRuleIterator>();
+}
+} // namespace content_settings \ No newline at end of file
diff --git a/chromium/components/content_settings/core/browser/content_settings_provider.h b/chromium/components/content_settings/core/browser/content_settings_provider.h
index edd22466003..b23e3c7bf80 100644
--- a/chromium/components/content_settings/core/browser/content_settings_provider.h
+++ b/chromium/components/content_settings/core/browser/content_settings_provider.h
@@ -38,6 +38,16 @@ class ProviderInterface {
const ResourceIdentifier& resource_identifier,
bool incognito) const = 0;
+ // Returns a |RuleIterator| over the discarded content setting rules stored
+ // by this provider. If |incognito| is true, the iterator returns only the
+ // content settings which are applicable to the incognito mode. Otherwise,
+ // it returns the content settings which are applicable only to the normal
+ // mode.
+ virtual std::unique_ptr<RuleIterator> GetDiscardedRuleIterator(
+ ContentSettingsType content_type,
+ const ResourceIdentifier& resource_identifier,
+ bool incognito) const;
+
// Asks the provider to set the website setting for a particular
// |primary_pattern|, |secondary_pattern|, |content_type| tuple. If the
// provider accepts the setting it returns true and takes the ownership of the
diff --git a/chromium/components/content_settings/core/browser/content_settings_registry.cc b/chromium/components/content_settings/core/browser/content_settings_registry.cc
index 3aa7c4054cf..6941b2f1cba 100644
--- a/chromium/components/content_settings/core/browser/content_settings_registry.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_registry.cc
@@ -561,7 +561,7 @@ void ContentSettingsRegistry::Init() {
WhitelistedSchemes(),
ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK,
CONTENT_SETTING_BLOCK, CONTENT_SETTING_SESSION_ONLY),
- WebsiteSettingsInfo::COOKIES_SCOPE,
+ WebsiteSettingsInfo::REQUESTING_ORIGIN_AND_TOP_LEVEL_ORIGIN_SCOPE,
WebsiteSettingsRegistry::ALL_PLATFORMS,
ContentSettingsInfo::INHERIT_IN_INCOGNITO,
ContentSettingsInfo::PERSISTENT,
diff --git a/chromium/components/content_settings/core/browser/content_settings_rule.cc b/chromium/components/content_settings/core/browser/content_settings_rule.cc
index 416cbee50c7..20c44d4b911 100644
--- a/chromium/components/content_settings/core/browser/content_settings_rule.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_rule.cc
@@ -63,4 +63,14 @@ Rule ConcatenationIterator::Next() {
return to_return;
}
+EmptyRuleIterator::~EmptyRuleIterator() = default;
+
+bool EmptyRuleIterator::HasNext() const {
+ return false;
+}
+
+Rule EmptyRuleIterator::Next() {
+ return Rule();
+}
+
} // namespace content_settings
diff --git a/chromium/components/content_settings/core/browser/content_settings_rule.h b/chromium/components/content_settings/core/browser/content_settings_rule.h
index ef1c0bec686..c58fe6c8d58 100644
--- a/chromium/components/content_settings/core/browser/content_settings_rule.h
+++ b/chromium/components/content_settings/core/browser/content_settings_rule.h
@@ -46,6 +46,16 @@ class RuleIterator {
virtual Rule Next() = 0;
};
+class EmptyRuleIterator : public RuleIterator {
+ public:
+ ~EmptyRuleIterator() override;
+
+ protected:
+ // RuleIterator:
+ bool HasNext() const override;
+ Rule Next() override;
+};
+
class ConcatenationIterator : public RuleIterator {
public:
// |auto_lock| can be null if no locking is needed.
diff --git a/chromium/components/content_settings/core/browser/cookie_settings.cc b/chromium/components/content_settings/core/browser/cookie_settings.cc
index 7246be6c667..a7868548eaa 100644
--- a/chromium/components/content_settings/core/browser/cookie_settings.cc
+++ b/chromium/components/content_settings/core/browser/cookie_settings.cc
@@ -208,6 +208,11 @@ void CookieSettings::GetCookieSettingInternal(
ContentSetting setting = ValueToContentSetting(value.get());
bool block = block_third && is_third_party_request;
+ if (!block) {
+ FireStorageAccessHistogram(
+ net::cookie_util::StorageAccessResult::ACCESS_ALLOWED);
+ }
+
#if !defined(OS_IOS)
// IOS doesn't use blink and as such cannot check our feature flag. Disabling
// by default there should be no-op as the lack of Blink also means no grants
@@ -221,11 +226,19 @@ void CookieSettings::GetCookieSettingInternal(
url, first_party_url, ContentSettingsType::STORAGE_ACCESS,
std::string());
- if (setting == CONTENT_SETTING_ALLOW)
+ if (setting == CONTENT_SETTING_ALLOW) {
block = false;
+ FireStorageAccessHistogram(net::cookie_util::StorageAccessResult::
+ ACCESS_ALLOWED_STORAGE_ACCESS_GRANT);
+ }
}
#endif
+ if (block) {
+ FireStorageAccessHistogram(
+ net::cookie_util::StorageAccessResult::ACCESS_BLOCKED);
+ }
+
*cookie_setting = block ? CONTENT_SETTING_BLOCK : setting;
}
diff --git a/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc b/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc
index 7d1944bafc2..fabcf2b9f19 100644
--- a/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc
+++ b/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc
@@ -7,6 +7,7 @@
#include <cstddef>
#include "base/scoped_observer.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/values.h"
@@ -22,11 +23,16 @@
#include "extensions/buildflags/buildflags.h"
#include "net/base/features.h"
#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#if !defined(OS_IOS)
#include "third_party/blink/public/common/features.h"
+namespace {
+constexpr char kAllowedRequestsHistogram[] =
+ "API.StorageAccess.AllowedRequests";
+}
#endif
namespace content_settings {
@@ -425,6 +431,25 @@ TEST_F(CookieSettingsTest, CookiesBlockEverythingExceptAllowed) {
}
#if !defined(OS_IOS)
+TEST_F(CookieSettingsTest, GetCookieSettingAllowedTelemetry) {
+ const GURL top_level_url = GURL(kFirstPartySite);
+ const GURL url = GURL(kAllowedSite);
+
+ prefs_.SetBoolean(prefs::kBlockThirdPartyCookies, false);
+
+ base::HistogramTester histogram_tester;
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 0);
+
+ ContentSetting setting;
+ cookie_settings_->GetCookieSetting(url, top_level_url, nullptr, &setting);
+ EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 1);
+ histogram_tester.ExpectBucketCount(
+ kAllowedRequestsHistogram,
+ static_cast<int>(net::cookie_util::StorageAccessResult::ACCESS_ALLOWED),
+ 1);
+}
+
// When the Storage Access API is disabled, block third party cookie setting
// should behave like normal.
TEST_F(CookieSettingsTest, GetCookieSettingDisabledSAA) {
@@ -453,6 +478,9 @@ TEST_F(CookieSettingsTest, GetCookieSettingDefaultSAA) {
const GURL top_level_url = GURL(kFirstPartySite);
const GURL url = GURL(kAllowedSite);
+ base::HistogramTester histogram_tester;
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 0);
+
prefs_.SetBoolean(prefs::kBlockThirdPartyCookies, true);
settings_map_->SetContentSettingCustomScope(
@@ -464,6 +492,11 @@ TEST_F(CookieSettingsTest, GetCookieSettingDefaultSAA) {
ContentSetting setting;
cookie_settings_->GetCookieSetting(url, top_level_url, nullptr, &setting);
EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 1);
+ histogram_tester.ExpectBucketCount(
+ kAllowedRequestsHistogram,
+ static_cast<int>(net::cookie_util::StorageAccessResult::ACCESS_BLOCKED),
+ 1);
}
// When enabled, the Storage Access API should unblock storage access that would
@@ -476,6 +509,9 @@ TEST_F(CookieSettingsTest, GetCookieSettingEnabledSAA) {
const GURL url = GURL(kAllowedSite);
const GURL third_url = GURL(kBlockedSite);
+ base::HistogramTester histogram_tester;
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 0);
+
prefs_.SetBoolean(prefs::kBlockThirdPartyCookies, true);
settings_map_->SetContentSettingCustomScope(
@@ -490,6 +526,12 @@ TEST_F(CookieSettingsTest, GetCookieSettingEnabledSAA) {
ContentSetting setting;
cookie_settings_->GetCookieSetting(url, top_level_url, nullptr, &setting);
EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 1);
+ histogram_tester.ExpectBucketCount(
+ kAllowedRequestsHistogram,
+ static_cast<int>(net::cookie_util::StorageAccessResult::
+ ACCESS_ALLOWED_STORAGE_ACCESS_GRANT),
+ 1);
// Invalid pair the |top_level_url| granting access to |url| is now
// being loaded under |url| as the top level url.
diff --git a/chromium/components/content_settings/core/browser/host_content_settings_map.cc b/chromium/components/content_settings/core/browser/host_content_settings_map.cc
index 7f1d698632c..65d3892343a 100644
--- a/chromium/components/content_settings/core/browser/host_content_settings_map.cc
+++ b/chromium/components/content_settings/core/browser/host_content_settings_map.cc
@@ -433,6 +433,30 @@ void HostContentSettingsMap::GetSettingsForOneType(
}
}
+void HostContentSettingsMap::GetDiscardedSettingsForOneType(
+ ContentSettingsType content_type,
+ const std::string& resource_identifier,
+ ContentSettingsForOneType* settings) const {
+ DCHECK(SupportsResourceIdentifier(content_type) ||
+ resource_identifier.empty());
+ DCHECK(settings);
+ UsedContentSettingsProviders();
+
+ for (const auto& provider_pair : content_settings_providers_) {
+ std::unique_ptr<content_settings::RuleIterator> discarded_rule_iterator(
+ provider_pair.second->GetDiscardedRuleIterator(
+ content_type, resource_identifier, is_off_the_record_));
+ while (discarded_rule_iterator->HasNext()) {
+ content_settings::Rule discarded_rule = discarded_rule_iterator->Next();
+ settings->emplace_back(
+ discarded_rule.primary_pattern, discarded_rule.secondary_pattern,
+ std::move(discarded_rule.value),
+ kProviderNamesSourceMap[provider_pair.first].provider_name,
+ is_off_the_record_, discarded_rule.expiration);
+ }
+ }
+}
+
void HostContentSettingsMap::SetDefaultContentSetting(
ContentSettingsType content_type,
ContentSetting setting) {
diff --git a/chromium/components/content_settings/core/browser/host_content_settings_map.h b/chromium/components/content_settings/core/browser/host_content_settings_map.h
index 0342ee0957d..94c9e8398c7 100644
--- a/chromium/components/content_settings/core/browser/host_content_settings_map.h
+++ b/chromium/components/content_settings/core/browser/host_content_settings_map.h
@@ -162,6 +162,11 @@ class HostContentSettingsMap : public content_settings::Observer,
base::Optional<content_settings::SessionModel>
session_model = base::nullopt) const;
+ void GetDiscardedSettingsForOneType(
+ ContentSettingsType content_type,
+ const std::string& resource_identifier,
+ ContentSettingsForOneType* settings) const;
+
// Sets the default setting for a particular content type. This method must
// not be invoked on an incognito map.
//
diff --git a/chromium/components/content_settings/core/browser/uma_util.h b/chromium/components/content_settings/core/browser/uma_util.h
index 011f1bc0950..7276e548d6f 100644
--- a/chromium/components/content_settings/core/browser/uma_util.h
+++ b/chromium/components/content_settings/core/browser/uma_util.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_UMA_UTIL_H_
#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_UMA_UTIL_H_
-#include "base/logging.h"
#include "base/macros.h"
#include "components/content_settings/core/common/content_settings.h"
diff --git a/chromium/components/content_settings/core/common/content_settings.mojom b/chromium/components/content_settings/core/common/content_settings.mojom
index 8ef573d3aaa..cb8b3d2aaa2 100644
--- a/chromium/components/content_settings/core/common/content_settings.mojom
+++ b/chromium/components/content_settings/core/common/content_settings.mojom
@@ -4,6 +4,7 @@
module content_settings.mojom;
+import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/values.mojom";
[Native]
@@ -65,6 +66,7 @@ struct ContentSettingPatternSource {
ContentSettingsPattern primary_pattern;
ContentSettingsPattern secondary_pattern;
mojo_base.mojom.Value setting_value;
+ mojo_base.mojom.Time expiration;
string source;
bool incognito;
};
diff --git a/chromium/components/content_settings/core/common/content_settings_mojom_traits.cc b/chromium/components/content_settings/core/common/content_settings_mojom_traits.cc
index 7db7683e5a8..3cdb9450d83 100644
--- a/chromium/components/content_settings/core/common/content_settings_mojom_traits.cc
+++ b/chromium/components/content_settings/core/common/content_settings_mojom_traits.cc
@@ -89,7 +89,7 @@ bool StructTraits<content_settings::mojom::ContentSettingPatternSourceDataView,
return data.ReadPrimaryPattern(&out->primary_pattern) &&
data.ReadSecondaryPattern(&out->secondary_pattern) &&
data.ReadSettingValue(&out->setting_value) &&
- data.ReadSource(&out->source);
+ data.ReadExpiration(&out->expiration) && data.ReadSource(&out->source);
}
// static
diff --git a/chromium/components/content_settings/core/common/content_settings_mojom_traits.h b/chromium/components/content_settings/core/common/content_settings_mojom_traits.h
index d342c755a42..2192c55d2b7 100644
--- a/chromium/components/content_settings/core/common/content_settings_mojom_traits.h
+++ b/chromium/components/content_settings/core/common/content_settings_mojom_traits.h
@@ -103,6 +103,10 @@ struct StructTraits<
return r.setting_value;
}
+ static const base::Time& expiration(const ContentSettingPatternSource& r) {
+ return r.expiration;
+ }
+
static const std::string& source(const ContentSettingPatternSource& r) {
return r.source;
}
diff --git a/chromium/components/content_settings/core/common/content_settings_pattern.cc b/chromium/components/content_settings/core/common/content_settings_pattern.cc
index b8eacf8deb5..85b7b24701f 100644
--- a/chromium/components/content_settings/core/common/content_settings_pattern.cc
+++ b/chromium/components/content_settings/core/common/content_settings_pattern.cc
@@ -604,6 +604,10 @@ ContentSettingsPattern::Relation ContentSettingsPattern::Compare(
return path_relation;
}
+bool ContentSettingsPattern::HasHostWildcards() const {
+ return parts_.has_domain_wildcard;
+}
+
bool ContentSettingsPattern::operator==(
const ContentSettingsPattern& other) const {
return Compare(other) == IDENTITY;
diff --git a/chromium/components/content_settings/core/common/content_settings_pattern.h b/chromium/components/content_settings/core/common/content_settings_pattern.h
index 09338d1492e..6d168ef8408 100644
--- a/chromium/components/content_settings/core/common/content_settings_pattern.h
+++ b/chromium/components/content_settings/core/common/content_settings_pattern.h
@@ -22,6 +22,11 @@ class PatternParser;
namespace mojom {
class ContentSettingsPatternDataView;
}
+
+enum class WildcardsInPrimaryPattern {
+ NOT_ALLOWED,
+ ALLOWED,
+};
}
// A pattern used in content setting rules. See |IsValid| for a description of
@@ -218,6 +223,9 @@ class ContentSettingsPattern {
// |Relation| of the two patterns.
Relation Compare(const ContentSettingsPattern& other) const;
+ // True if the host in the pattern has a wildcard.
+ bool HasHostWildcards() const;
+
// Returns true if the pattern and the |other| pattern are identical.
bool operator==(const ContentSettingsPattern& other) const;
diff --git a/chromium/components/content_settings/core/common/content_settings_pattern_unittest.cc b/chromium/components/content_settings/core/common/content_settings_pattern_unittest.cc
index 8ae5c634931..636c82e56a2 100644
--- a/chromium/components/content_settings/core/common/content_settings_pattern_unittest.cc
+++ b/chromium/components/content_settings/core/common/content_settings_pattern_unittest.cc
@@ -808,3 +808,22 @@ TEST(ContentSettingsPatternTest, FileSchemeHasPath) {
EXPECT_TRUE(Pattern("file:///foo/bar/").HasPath());
EXPECT_TRUE(Pattern("file:///foo/bar/test.html").HasPath());
}
+
+TEST(ContentSettingsPatternTest, PatternHasWildcards) {
+ // scheme wildcard are allowed
+ EXPECT_FALSE(Pattern("mail.google.com:443/home").HasHostWildcards());
+ EXPECT_FALSE(Pattern("*://mail.google.com:443/home").HasHostWildcards());
+ // domain wildcard
+ EXPECT_TRUE(Pattern("https://[*.]google.com:443/home").HasHostWildcards());
+ // path wildcard are allowed
+ EXPECT_FALSE(Pattern("https://mail.google.com:443/*").HasHostWildcards());
+ // port wildcards are allowed
+ EXPECT_FALSE(Pattern("https://mail.google.com/home").HasHostWildcards());
+ EXPECT_FALSE(Pattern("https://mail.google.com:*/home").HasHostWildcards());
+ // full wildcard pattern
+ EXPECT_TRUE(Pattern("*").HasHostWildcards());
+ // full wildcard pattern
+ EXPECT_TRUE(ContentSettingsPattern::Wildcard().HasHostWildcards());
+ // no wildcards
+ EXPECT_FALSE(Pattern("https://mail.google.com:443/home").HasHostWildcards());
+}
diff --git a/chromium/components/content_settings/core/common/features.cc b/chromium/components/content_settings/core/common/features.cc
index 17dceed1a0d..4900f2f794c 100644
--- a/chromium/components/content_settings/core/common/features.cc
+++ b/chromium/components/content_settings/core/common/features.cc
@@ -21,4 +21,9 @@ const base::FeatureParam<bool> kImprovedCookieControlsDefaultInIncognito{
const base::Feature kImprovedCookieControlsForThirdPartyCookieBlocking{
"ImprovedCookieControlsForThirdPartyCookieBlocking",
base::FEATURE_DISABLED_BY_DEFAULT};
-} \ No newline at end of file
+
+const base::Feature kDisallowWildcardsInPluginContentSettings{
+ "DisallowWildcardsInPluginContentSettings",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+} // namespace content_settings \ No newline at end of file
diff --git a/chromium/components/content_settings/core/common/features.h b/chromium/components/content_settings/core/common/features.h
index 9d6965be065..162841fe3d2 100644
--- a/chromium/components/content_settings/core/common/features.h
+++ b/chromium/components/content_settings/core/common/features.h
@@ -26,6 +26,10 @@ extern const base::FeatureParam<bool> kImprovedCookieControlsDefaultInIncognito;
COMPONENT_EXPORT(CONTENT_SETTINGS_FEATURES)
extern const base::Feature kImprovedCookieControlsForThirdPartyCookieBlocking;
+// Feature to disallow wildcard pattern matching for plugin content settings
+COMPONENT_EXPORT(CONTENT_SETTINGS_FEATURES)
+extern const base::Feature kDisallowWildcardsInPluginContentSettings;
+
} // namespace content_settings
-#endif // COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_FEATURES_H_ \ No newline at end of file
+#endif // COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_FEATURES_H_
diff --git a/chromium/components/content_settings/core/common/pref_names.h b/chromium/components/content_settings/core/common/pref_names.h
index a4c4bffdbd1..84bf8ba3d83 100644
--- a/chromium/components/content_settings/core/common/pref_names.h
+++ b/chromium/components/content_settings/core/common/pref_names.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_PREF_NAMES_H_
#define COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_PREF_NAMES_H_
-#include "base/logging.h"
namespace prefs {
diff --git a/chromium/components/content_settings/renderer/content_settings_agent_impl.cc b/chromium/components/content_settings/renderer/content_settings_agent_impl.cc
index 33389449005..660223c0bf2 100644
--- a/chromium/components/content_settings/renderer/content_settings_agent_impl.cc
+++ b/chromium/components/content_settings/renderer/content_settings_agent_impl.cc
@@ -214,30 +214,29 @@ void ContentSettingsAgentImpl::BindContentSettingsManager(
}
void ContentSettingsAgentImpl::DidCommitProvisionalLoad(
- bool is_same_document_navigation,
ui::PageTransition transition) {
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
if (frame->Parent())
return; // Not a top-level navigation.
- if (!is_same_document_navigation) {
- // Clear "block" flags for the new page. This needs to happen before any of
- // |allowScript()|, |allowScriptFromSource()|, |allowImage()|, or
- // |allowPlugins()| is called for the new page so that these functions can
- // correctly detect that a piece of content flipped from "not blocked" to
- // "blocked".
- ClearBlockedContentSettings();
-
- // The BrowserInterfaceBroker is reset on navigation, so we will need to
- // re-acquire the ContentSettingsManager.
- content_settings_manager_.reset();
- }
+ // Clear "block" flags for the new page. This needs to happen before any of
+ // |allowScript()|, |allowScriptFromSource()|, |allowImage()|, or
+ // |allowPlugins()| is called for the new page so that these functions can
+ // correctly detect that a piece of content flipped from "not blocked" to
+ // "blocked".
+ ClearBlockedContentSettings();
+
+ // The BrowserInterfaceBroker is reset on navigation, so we will need to
+ // re-acquire the ContentSettingsManager.
+ content_settings_manager_.reset();
+#if DCHECK_IS_ON()
GURL url = frame->GetDocument().Url();
// If we start failing this DCHECK, please makes sure we don't regress
// this bug: http://code.google.com/p/chromium/issues/detail?id=79304
DCHECK(frame->GetDocument().GetSecurityOrigin().ToString() == "null" ||
!url.SchemeIs(url::kDataScheme));
+#endif
}
void ContentSettingsAgentImpl::OnDestruct() {
diff --git a/chromium/components/content_settings/renderer/content_settings_agent_impl.h b/chromium/components/content_settings/renderer/content_settings_agent_impl.h
index 2522fdb1971..3484035136c 100644
--- a/chromium/components/content_settings/renderer/content_settings_agent_impl.h
+++ b/chromium/components/content_settings/renderer/content_settings_agent_impl.h
@@ -137,8 +137,7 @@ class ContentSettingsAgentImpl
ContentSettingsInterstitialPages);
// RenderFrameObserver implementation.
- void DidCommitProvisionalLoad(bool is_same_document_navigation,
- ui::PageTransition transition) override;
+ void DidCommitProvisionalLoad(ui::PageTransition transition) override;
void OnDestruct() override;
// mojom::ContentSettingsAgent:
diff --git a/chromium/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc b/chromium/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc
index ad56e6f35e4..c0e36cd97fa 100644
--- a/chromium/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc
+++ b/chromium/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc
@@ -152,8 +152,7 @@ class CommitTimeConditionChecker : public content::RenderFrameObserver {
protected:
// RenderFrameObserver:
void OnDestruct() override {}
- void DidCommitProvisionalLoad(bool is_same_document_navigation,
- ui::PageTransition transition) override {
+ void DidCommitProvisionalLoad(ui::PageTransition transition) override {
EXPECT_EQ(expectation_, predicate_.Run());
}