content_settings_manager_impl.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/content_settings/browser/content_settings_manager_impl.h"
  5. #include "base/memory/ptr_util.h"
  6. #include "base/task/thread_pool.h"
  7. #include "components/content_settings/browser/page_specific_content_settings.h"
  8. #include "components/content_settings/core/browser/cookie_settings.h"
  9. #include "components/page_load_metrics/browser/metrics_web_contents_observer.h"
  10. #include "components/page_load_metrics/browser/page_load_metrics_observer.h"
  11. #include "content/public/browser/browser_task_traits.h"
  12. #include "content/public/browser/browser_thread.h"
  13. #include "content/public/browser/render_frame_host.h"
  14. #include "content/public/browser/render_process_host.h"
  15. #include "content/public/common/content_features.h"
  16. #include "mojo/public/cpp/bindings/self_owned_receiver.h"
  17. #include "net/cookies/site_for_cookies.h"
  18. using content_settings::PageSpecificContentSettings;
  19. namespace content_settings {
  20. namespace {
  21. using StorageType = mojom::ContentSettingsManager::StorageType;
  22. void OnStorageAccessed(int process_id,
  23. int frame_id,
  24. const GURL& origin_url,
  25. const GURL& top_origin_url,
  26. bool blocked_by_policy,
  27. page_load_metrics::StorageType storage_type) {
  28. content::RenderFrameHost* render_frame_host =
  29. content::RenderFrameHost::FromID(process_id, frame_id);
  30. content::WebContents* web_contents =
  31. content::WebContents::FromRenderFrameHost(render_frame_host);
  32. if (!web_contents)
  33. return;
  34. page_load_metrics::MetricsWebContentsObserver* metrics_observer =
  35. page_load_metrics::MetricsWebContentsObserver::FromWebContents(
  36. web_contents);
  37. if (metrics_observer) {
  38. metrics_observer->OnStorageAccessed(render_frame_host, origin_url,
  39. top_origin_url, blocked_by_policy,
  40. storage_type);
  41. }
  42. }
  43. void NotifyStorageAccess(int render_process_id,
  44. int32_t render_frame_id,
  45. StorageType storage_type,
  46. const GURL& url,
  47. const url::Origin& top_frame_origin,
  48. bool allowed) {
  49. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  50. bool should_notify_pscs = ([storage_type]() {
  51. switch (storage_type) {
  52. case StorageType::DATABASE:
  53. case StorageType::LOCAL_STORAGE:
  54. case StorageType::SESSION_STORAGE:
  55. case StorageType::FILE_SYSTEM:
  56. case StorageType::INDEXED_DB:
  57. case StorageType::CACHE:
  58. return true;
  59. case StorageType::WEB_LOCKS:
  60. // State not persisted, no need to record anything;
  61. return false;
  62. }
  63. })();
  64. auto metrics_type =
  65. ([storage_type]() -> absl::optional<page_load_metrics::StorageType> {
  66. switch (storage_type) {
  67. case StorageType::LOCAL_STORAGE:
  68. return page_load_metrics::StorageType::kLocalStorage;
  69. case StorageType::SESSION_STORAGE:
  70. return page_load_metrics::StorageType::kSessionStorage;
  71. case StorageType::FILE_SYSTEM:
  72. return page_load_metrics::StorageType::kFileSystem;
  73. case StorageType::INDEXED_DB:
  74. return page_load_metrics::StorageType::kIndexedDb;
  75. case StorageType::CACHE:
  76. return page_load_metrics::StorageType::kCacheStorage;
  77. case StorageType::DATABASE:
  78. case StorageType::WEB_LOCKS:
  79. return absl::nullopt;
  80. }
  81. })();
  82. if (should_notify_pscs) {
  83. PageSpecificContentSettings::StorageAccessed(
  84. storage_type, render_process_id, render_frame_id, url, !allowed);
  85. }
  86. if (metrics_type) {
  87. OnStorageAccessed(render_process_id, render_frame_id, url,
  88. top_frame_origin.GetURL(), !allowed,
  89. metrics_type.value());
  90. }
  91. }
  92. void OnContentBlockedOnUI(int render_process_id,
  93. int32_t render_frame_id,
  94. ContentSettingsType type) {
  95. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  96. PageSpecificContentSettings::ContentBlocked(render_process_id,
  97. render_frame_id, type);
  98. }
  99. // We may or may not be on the UI thread depending on whether the
  100. // NavigationThreadingOptimizations feature is enabled.
  101. // TODO(https://crbug.com/1187753): Clean this up once the feature is
  102. // shipped and the code path is removed.
  103. void RunOrPostTaskOnUI(const base::Location& location, base::OnceClosure task) {
  104. if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI))
  105. std::move(task).Run();
  106. else
  107. content::GetUIThreadTaskRunner({})->PostTask(location, std::move(task));
  108. }
  109. } // namespace
  110. ContentSettingsManagerImpl::~ContentSettingsManagerImpl() = default;
  111. // static
  112. void ContentSettingsManagerImpl::Create(
  113. content::RenderProcessHost* render_process_host,
  114. mojo::PendingReceiver<content_settings::mojom::ContentSettingsManager>
  115. receiver,
  116. std::unique_ptr<Delegate> delegate) {
  117. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  118. auto create = base::BindOnce(
  119. &ContentSettingsManagerImpl::CreateOnThread, render_process_host->GetID(),
  120. std::move(receiver),
  121. delegate->GetCookieSettings(render_process_host->GetBrowserContext()),
  122. std::move(delegate));
  123. if (base::FeatureList::IsEnabled(
  124. features::kNavigationThreadingOptimizations)) {
  125. if (base::FeatureList::IsEnabled(features::kThreadingOptimizationsOnIO)) {
  126. content::GetIOThreadTaskRunner({})->PostTask(FROM_HERE,
  127. std::move(create));
  128. } else {
  129. base::ThreadPool::CreateSingleThreadTaskRunner(
  130. {base::TaskPriority::USER_BLOCKING})
  131. ->PostTask(FROM_HERE, std::move(create));
  132. }
  133. } else {
  134. std::move(create).Run();
  135. }
  136. }
  137. void ContentSettingsManagerImpl::Clone(
  138. mojo::PendingReceiver<content_settings::mojom::ContentSettingsManager>
  139. receiver) {
  140. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  141. mojo::MakeSelfOwnedReceiver(
  142. base::WrapUnique(new ContentSettingsManagerImpl(*this)),
  143. std::move(receiver));
  144. }
  145. void ContentSettingsManagerImpl::AllowStorageAccess(
  146. int32_t render_frame_id,
  147. StorageType storage_type,
  148. const url::Origin& origin,
  149. const net::SiteForCookies& site_for_cookies,
  150. const url::Origin& top_frame_origin,
  151. base::OnceCallback<void(bool)> callback) {
  152. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  153. GURL url = origin.GetURL();
  154. bool allowed = cookie_settings_->IsFullCookieAccessAllowed(
  155. url, site_for_cookies, top_frame_origin,
  156. CookieSettings::QueryReason::kSiteStorage);
  157. if (delegate_->AllowStorageAccess(render_process_id_, render_frame_id,
  158. storage_type, url, allowed, &callback)) {
  159. DCHECK(!callback);
  160. return;
  161. }
  162. RunOrPostTaskOnUI(
  163. FROM_HERE,
  164. base::BindOnce(&NotifyStorageAccess, render_process_id_, render_frame_id,
  165. storage_type, url, top_frame_origin, allowed));
  166. std::move(callback).Run(allowed);
  167. }
  168. void ContentSettingsManagerImpl::OnContentBlocked(int32_t render_frame_id,
  169. ContentSettingsType type) {
  170. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  171. RunOrPostTaskOnUI(FROM_HERE,
  172. base::BindOnce(&OnContentBlockedOnUI, render_process_id_,
  173. render_frame_id, type));
  174. }
  175. ContentSettingsManagerImpl::ContentSettingsManagerImpl(
  176. int render_process_id,
  177. std::unique_ptr<Delegate> delegate,
  178. scoped_refptr<CookieSettings> cookie_settings)
  179. : delegate_(std::move(delegate)),
  180. render_process_id_(render_process_id),
  181. cookie_settings_(cookie_settings) {}
  182. ContentSettingsManagerImpl::ContentSettingsManagerImpl(
  183. const ContentSettingsManagerImpl& other)
  184. : delegate_(other.delegate_->Clone()),
  185. render_process_id_(other.render_process_id_),
  186. cookie_settings_(other.cookie_settings_) {}
  187. // static
  188. void ContentSettingsManagerImpl::CreateOnThread(
  189. int render_process_id,
  190. mojo::PendingReceiver<content_settings::mojom::ContentSettingsManager>
  191. receiver,
  192. scoped_refptr<CookieSettings> cookie_settings,
  193. std::unique_ptr<Delegate> delegate) {
  194. mojo::MakeSelfOwnedReceiver(
  195. base::WrapUnique(new ContentSettingsManagerImpl(
  196. render_process_id, std::move(delegate), cookie_settings)),
  197. std::move(receiver));
  198. }
  199. } // namespace content_settings