page_specific_content_settings.cc 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100
  1. // Copyright (c) 2012 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/page_specific_content_settings.h"
  5. #include <list>
  6. #include <vector>
  7. #include "base/command_line.h"
  8. #include "base/lazy_instance.h"
  9. #include "base/memory/ptr_util.h"
  10. #include "base/observer_list.h"
  11. #include "base/strings/string_util.h"
  12. #include "base/strings/utf_string_conversions.h"
  13. #include "build/build_config.h"
  14. #include "build/chromeos_buildflags.h"
  15. #include "components/browsing_data/content/cache_storage_helper.h"
  16. #include "components/browsing_data/content/cookie_helper.h"
  17. #include "components/browsing_data/content/database_helper.h"
  18. #include "components/browsing_data/content/file_system_helper.h"
  19. #include "components/browsing_data/content/indexed_db_helper.h"
  20. #include "components/browsing_data/content/local_storage_helper.h"
  21. #include "components/browsing_data/content/service_worker_helper.h"
  22. #include "components/browsing_data/content/shared_worker_helper.h"
  23. #include "components/content_settings/common/content_settings_agent.mojom.h"
  24. #include "components/content_settings/core/browser/content_settings_info.h"
  25. #include "components/content_settings/core/browser/content_settings_registry.h"
  26. #include "components/content_settings/core/browser/content_settings_utils.h"
  27. #include "components/content_settings/core/common/content_settings_utils.h"
  28. #include "components/prefs/pref_service.h"
  29. #include "components/privacy_sandbox/canonical_topic.h"
  30. #include "components/privacy_sandbox/privacy_sandbox_features.h"
  31. #include "content/public/browser/browser_thread.h"
  32. #include "content/public/browser/cookie_access_details.h"
  33. #include "content/public/browser/navigation_handle.h"
  34. #include "content/public/browser/navigation_handle_user_data.h"
  35. #include "content/public/browser/page.h"
  36. #include "content/public/browser/render_frame_host.h"
  37. #include "content/public/browser/render_process_host.h"
  38. #include "content/public/browser/render_view_host.h"
  39. #include "content/public/browser/web_contents.h"
  40. #include "content/public/browser/web_contents_delegate.h"
  41. #include "content/public/browser/web_contents_observer.h"
  42. #include "content/public/browser/web_contents_user_data.h"
  43. #include "content/public/common/content_constants.h"
  44. #include "third_party/abseil-cpp/absl/types/optional.h"
  45. #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
  46. #include "third_party/blink/public/common/storage_key/storage_key.h"
  47. #include "url/origin.h"
  48. using content::BrowserThread;
  49. using StorageType =
  50. content_settings::mojom::ContentSettingsManager::StorageType;
  51. using LifecycleState = content::RenderFrameHost::LifecycleState;
  52. namespace content_settings {
  53. namespace {
  54. bool WillNavigationCreateNewPageSpecificContentSettingsOnCommit(
  55. content::NavigationHandle* navigation_handle) {
  56. return navigation_handle->IsInMainFrame() &&
  57. !navigation_handle->IsSameDocument() &&
  58. !navigation_handle->IsServedFromBackForwardCache() &&
  59. !navigation_handle->IsPrerenderedPageActivation();
  60. }
  61. // Keeps track of cookie and service worker access during a navigation.
  62. // These types of access can happen for the current page or for a new
  63. // navigation (think cookies sent in the HTTP request or service worker
  64. // being run to serve a fetch request). A navigation might fail to
  65. // commit in which case we have to handle it as if it had never
  66. // occurred. So we cache all cookies and service worker accesses that
  67. // happen during a navigation and only apply the changes if the
  68. // navigation commits.
  69. class InflightNavigationContentSettings
  70. : public content::NavigationHandleUserData<
  71. InflightNavigationContentSettings> {
  72. public:
  73. ~InflightNavigationContentSettings() override;
  74. std::vector<content::CookieAccessDetails> cookie_accesses;
  75. std::vector<std::pair<GURL, content::AllowServiceWorkerResult>>
  76. service_worker_accesses;
  77. private:
  78. explicit InflightNavigationContentSettings(
  79. content::NavigationHandle& navigation_handle);
  80. friend class content::NavigationHandleUserData<
  81. InflightNavigationContentSettings>;
  82. NAVIGATION_HANDLE_USER_DATA_KEY_DECL();
  83. };
  84. // This class attaches to WebContents to listen to events and route them to
  85. // appropriate PageSpecificContentSettings, store navigation related events
  86. // until the navigation finishes and then transferring the
  87. // navigation-associated state to the newly-created page.
  88. class WebContentsHandler
  89. : public content::WebContentsObserver,
  90. public content::WebContentsUserData<WebContentsHandler> {
  91. public:
  92. using Delegate = PageSpecificContentSettings::Delegate;
  93. using SiteDataObserver = PageSpecificContentSettings::SiteDataObserver;
  94. explicit WebContentsHandler(content::WebContents* web_contents,
  95. std::unique_ptr<Delegate> delegate);
  96. ~WebContentsHandler() override;
  97. // Adds the given |SiteDataObserver|. The |observer| is notified when a
  98. // locale shared object, like for example a cookie, is accessed.
  99. void AddSiteDataObserver(SiteDataObserver* observer);
  100. // Removes the given |SiteDataObserver|.
  101. void RemoveSiteDataObserver(SiteDataObserver* observer);
  102. // Notifies all registered |SiteDataObserver|s.
  103. void NotifySiteDataObservers();
  104. // Queues update sent while the navigation is still in progress. The update
  105. // is run after the navigation completes (DidFinishNavigation).
  106. void AddPendingCommitUpdate(content::GlobalRenderFrameHostId id,
  107. base::OnceClosure update);
  108. Delegate* delegate() { return delegate_.get(); }
  109. private:
  110. friend class content::WebContentsUserData<WebContentsHandler>;
  111. // Applies all stored events for the given navigation to the current main
  112. // document.
  113. void TransferNavigationContentSettingsToCommittedDocument(
  114. const InflightNavigationContentSettings& navigation_settings,
  115. content::RenderFrameHost* rfh);
  116. // content::WebContentsObserver overrides.
  117. void ReadyToCommitNavigation(
  118. content::NavigationHandle* navigation_handle) override;
  119. void DidFinishNavigation(
  120. content::NavigationHandle* navigation_handle) override;
  121. void OnCookiesAccessed(content::NavigationHandle* navigation,
  122. const content::CookieAccessDetails& details) override;
  123. void OnCookiesAccessed(content::RenderFrameHost* rfh,
  124. const content::CookieAccessDetails& details) override;
  125. // Called when a specific Service Worker scope was accessed.
  126. // If access was blocked due to the user's content settings,
  127. // |blocked_by_policy_javascript| or/and |blocked_by_policy_cookie|
  128. // should be true, and this function should invoke OnContentBlocked for
  129. // JavaScript or/and cookies respectively.
  130. void OnServiceWorkerAccessed(
  131. content::NavigationHandle* navigation,
  132. const GURL& scope,
  133. content::AllowServiceWorkerResult allowed) override;
  134. void OnServiceWorkerAccessed(
  135. content::RenderFrameHost* frame,
  136. const GURL& scope,
  137. content::AllowServiceWorkerResult allowed) override;
  138. std::unique_ptr<Delegate> delegate_;
  139. raw_ptr<HostContentSettingsMap> map_;
  140. // All currently registered |SiteDataObserver|s.
  141. base::ObserverList<SiteDataObserver>::Unchecked observer_list_;
  142. std::map<content::GlobalRenderFrameHostId, std::vector<base::OnceClosure>>
  143. pending_commit_updates_;
  144. WEB_CONTENTS_USER_DATA_KEY_DECL();
  145. };
  146. // Certain notifications for content accesses (script/storage) can be
  147. // received from the renderer while the RFH is in the kPendingCommit lifecycle
  148. // state. At this point, no PageSpecificContentSettings object is created (as
  149. // this only happens in DidFinishNavigation), so we queue up the update until
  150. // DidFinishNavigation is called. This method returns true if the update is
  151. // queued, false otherwise.
  152. template <typename Method, typename... Args>
  153. bool DelayUntilCommitIfNecessary(content::RenderFrameHost* rfh,
  154. Method method,
  155. Args... args) {
  156. if (!rfh)
  157. return false;
  158. if (rfh->GetLifecycleState() == LifecycleState::kPendingCommit) {
  159. auto* handler = WebContentsHandler::FromWebContents(
  160. content::WebContents::FromRenderFrameHost(rfh));
  161. if (!handler)
  162. return false;
  163. handler->AddPendingCommitUpdate(rfh->GetGlobalId(),
  164. base::BindOnce(method, args...));
  165. return true;
  166. }
  167. return false;
  168. }
  169. } // namespace
  170. InflightNavigationContentSettings::InflightNavigationContentSettings(
  171. content::NavigationHandle&) {}
  172. InflightNavigationContentSettings::~InflightNavigationContentSettings() =
  173. default;
  174. NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(InflightNavigationContentSettings);
  175. WebContentsHandler::WebContentsHandler(content::WebContents* web_contents,
  176. std::unique_ptr<Delegate> delegate)
  177. : WebContentsObserver(web_contents),
  178. content::WebContentsUserData<WebContentsHandler>(*web_contents),
  179. delegate_(std::move(delegate)),
  180. map_(delegate_->GetSettingsMap()) {
  181. DCHECK(
  182. !PageSpecificContentSettings::GetForPage(web_contents->GetPrimaryPage()));
  183. content::PageUserData<PageSpecificContentSettings>::CreateForPage(
  184. web_contents->GetPrimaryPage(), delegate_.get());
  185. }
  186. WebContentsHandler::~WebContentsHandler() {
  187. for (SiteDataObserver& observer : observer_list_)
  188. observer.WebContentsDestroyed();
  189. }
  190. void WebContentsHandler::TransferNavigationContentSettingsToCommittedDocument(
  191. const InflightNavigationContentSettings& navigation_settings,
  192. content::RenderFrameHost* rfh) {
  193. for (const auto& cookie_access : navigation_settings.cookie_accesses) {
  194. OnCookiesAccessed(rfh, cookie_access);
  195. }
  196. for (const auto& service_worker_access :
  197. navigation_settings.service_worker_accesses) {
  198. OnServiceWorkerAccessed(rfh, service_worker_access.first,
  199. service_worker_access.second);
  200. }
  201. }
  202. void WebContentsHandler::OnCookiesAccessed(
  203. content::NavigationHandle* navigation,
  204. const content::CookieAccessDetails& details) {
  205. if (WillNavigationCreateNewPageSpecificContentSettingsOnCommit(navigation)) {
  206. auto* inflight_navigation_settings =
  207. content::NavigationHandleUserData<InflightNavigationContentSettings>::
  208. GetOrCreateForNavigationHandle(*navigation);
  209. inflight_navigation_settings->cookie_accesses.push_back(details);
  210. return;
  211. }
  212. // All accesses during main frame navigations should enter the block above and
  213. // not reach here. We also don't expect any accesses to be made during page
  214. // activations or same-document navigations.
  215. DCHECK(navigation->GetParentFrame());
  216. OnCookiesAccessed(navigation->GetParentFrame()->GetMainFrame(), details);
  217. }
  218. void WebContentsHandler::OnCookiesAccessed(
  219. content::RenderFrameHost* rfh,
  220. const content::CookieAccessDetails& details) {
  221. auto* pscs = PageSpecificContentSettings::GetForPage(rfh->GetPage());
  222. if (pscs)
  223. pscs->OnCookiesAccessed(details);
  224. }
  225. void WebContentsHandler::OnServiceWorkerAccessed(
  226. content::NavigationHandle* navigation,
  227. const GURL& scope,
  228. content::AllowServiceWorkerResult allowed) {
  229. DCHECK(scope.is_valid());
  230. if (WillNavigationCreateNewPageSpecificContentSettingsOnCommit(navigation)) {
  231. auto* inflight_navigation_settings =
  232. content::NavigationHandleUserData<InflightNavigationContentSettings>::
  233. GetOrCreateForNavigationHandle(*navigation);
  234. inflight_navigation_settings->service_worker_accesses.emplace_back(
  235. std::make_pair(scope, allowed));
  236. return;
  237. }
  238. // All accesses during main frame navigations should enter the block above and
  239. // not reach here. We also don't expect any accesses to be made during page
  240. // activations or same-document navigations.
  241. DCHECK(navigation->GetParentFrame());
  242. OnServiceWorkerAccessed(navigation->GetParentFrame()->GetMainFrame(), scope,
  243. allowed);
  244. }
  245. void WebContentsHandler::OnServiceWorkerAccessed(
  246. content::RenderFrameHost* frame,
  247. const GURL& scope,
  248. content::AllowServiceWorkerResult allowed) {
  249. auto* pscs = PageSpecificContentSettings::GetForPage(frame->GetPage());
  250. if (pscs)
  251. pscs->OnServiceWorkerAccessed(scope, allowed);
  252. }
  253. void WebContentsHandler::ReadyToCommitNavigation(
  254. content::NavigationHandle* navigation_handle) {
  255. content::RenderFrameHost* rfh = navigation_handle->GetRenderFrameHost();
  256. RendererContentSettingRules rules;
  257. content_settings::GetRendererContentSettingRules(map_, &rules);
  258. delegate()->SetDefaultRendererContentSettingRules(rfh, &rules);
  259. const GURL& primary_url =
  260. navigation_handle->GetParentFrameOrOuterDocument()
  261. ? navigation_handle->GetParentFrameOrOuterDocument()
  262. ->GetLastCommittedURL()
  263. : navigation_handle->GetURL();
  264. rules.FilterRulesByOutermostMainFrameURL(primary_url);
  265. mojo::AssociatedRemote<content_settings::mojom::ContentSettingsAgent> agent;
  266. rfh->GetRemoteAssociatedInterfaces()->GetInterface(&agent);
  267. // TODO(crbug.com/1187618): We shouldn't be sending the primary patterns here
  268. // because: a) we have already filtered based on them and they are not needed
  269. // in the renderer, and b) they could leak the embedder origin to embedded
  270. // pages like fenced frames.
  271. agent->SendRendererContentSettingRules(std::move(rules));
  272. }
  273. void WebContentsHandler::DidFinishNavigation(
  274. content::NavigationHandle* navigation_handle) {
  275. if (!navigation_handle->HasCommitted())
  276. return;
  277. if (WillNavigationCreateNewPageSpecificContentSettingsOnCommit(
  278. navigation_handle)) {
  279. content::PageUserData<PageSpecificContentSettings>::CreateForPage(
  280. navigation_handle->GetRenderFrameHost()->GetPage(), delegate_.get());
  281. InflightNavigationContentSettings* inflight_settings =
  282. content::NavigationHandleUserData<InflightNavigationContentSettings>::
  283. GetForNavigationHandle(*navigation_handle);
  284. if (inflight_settings) {
  285. TransferNavigationContentSettingsToCommittedDocument(
  286. *inflight_settings, navigation_handle->GetRenderFrameHost());
  287. }
  288. content::GlobalRenderFrameHostId rfh_id =
  289. navigation_handle->GetRenderFrameHost()->GetGlobalId();
  290. auto it = pending_commit_updates_.find(rfh_id);
  291. if (it != pending_commit_updates_.end()) {
  292. for (auto& update : it->second) {
  293. std::move(update).Run();
  294. }
  295. pending_commit_updates_.erase(it);
  296. }
  297. }
  298. if (navigation_handle->IsPrerenderedPageActivation()) {
  299. auto* pscs = PageSpecificContentSettings::GetForFrame(
  300. navigation_handle->GetRenderFrameHost());
  301. DCHECK(pscs);
  302. pscs->OnPrerenderingPageActivation();
  303. }
  304. if (navigation_handle->IsInPrimaryMainFrame())
  305. delegate_->UpdateLocationBar();
  306. }
  307. void WebContentsHandler::AddSiteDataObserver(SiteDataObserver* observer) {
  308. observer_list_.AddObserver(observer);
  309. }
  310. void WebContentsHandler::RemoveSiteDataObserver(SiteDataObserver* observer) {
  311. observer_list_.RemoveObserver(observer);
  312. }
  313. void WebContentsHandler::NotifySiteDataObservers() {
  314. for (SiteDataObserver& observer : observer_list_)
  315. observer.OnSiteDataAccessed();
  316. }
  317. void WebContentsHandler::AddPendingCommitUpdate(
  318. content::GlobalRenderFrameHostId id,
  319. base::OnceClosure update) {
  320. #if DCHECK_IS_ON()
  321. content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(id);
  322. DCHECK(rfh);
  323. DCHECK_EQ(rfh->GetLifecycleState(), LifecycleState::kPendingCommit);
  324. #endif
  325. pending_commit_updates_[id].push_back(std::move(update));
  326. }
  327. WEB_CONTENTS_USER_DATA_KEY_IMPL(WebContentsHandler);
  328. PageSpecificContentSettings::SiteDataObserver::SiteDataObserver(
  329. content::WebContents* web_contents)
  330. : web_contents_(web_contents) {
  331. // Make sure the handler was attached to the WebContents as some UT might skip
  332. // this.
  333. auto* handler = WebContentsHandler::FromWebContents(web_contents_);
  334. if (handler)
  335. handler->AddSiteDataObserver(this);
  336. }
  337. PageSpecificContentSettings::SiteDataObserver::~SiteDataObserver() {
  338. if (!web_contents_)
  339. return;
  340. auto* handler = WebContentsHandler::FromWebContents(web_contents_);
  341. if (handler)
  342. handler->RemoveSiteDataObserver(this);
  343. }
  344. void PageSpecificContentSettings::SiteDataObserver::WebContentsDestroyed() {
  345. web_contents_ = nullptr;
  346. }
  347. PageSpecificContentSettings::PendingUpdates::PendingUpdates() = default;
  348. PageSpecificContentSettings::PendingUpdates::~PendingUpdates() = default;
  349. PageSpecificContentSettings::PageSpecificContentSettings(content::Page& page,
  350. Delegate* delegate)
  351. : content::PageUserData<PageSpecificContentSettings>(page),
  352. delegate_(delegate),
  353. map_(delegate_->GetSettingsMap()),
  354. allowed_local_shared_objects_(GetWebContents()->GetBrowserContext(),
  355. /*ignore_empty_localstorage=*/true,
  356. delegate_->GetAdditionalFileSystemTypes(),
  357. delegate_->GetIsDeletionDisabledCallback()),
  358. blocked_local_shared_objects_(GetWebContents()->GetBrowserContext(),
  359. /*ignore_empty_localstorage=*/false,
  360. delegate_->GetAdditionalFileSystemTypes(),
  361. delegate_->GetIsDeletionDisabledCallback()),
  362. microphone_camera_state_(MICROPHONE_CAMERA_NOT_ACCESSED) {
  363. observation_.Observe(map_.get());
  364. if (page.GetMainDocument().GetLifecycleState() ==
  365. LifecycleState::kPrerendering) {
  366. updates_queued_during_prerender_ = std::make_unique<PendingUpdates>();
  367. }
  368. }
  369. PageSpecificContentSettings::~PageSpecificContentSettings() = default;
  370. // static
  371. void PageSpecificContentSettings::CreateForWebContents(
  372. content::WebContents* web_contents,
  373. std::unique_ptr<Delegate> delegate) {
  374. WebContentsHandler::CreateForWebContents(web_contents, std::move(delegate));
  375. }
  376. // static
  377. void PageSpecificContentSettings::DeleteForWebContentsForTest(
  378. content::WebContents* web_contents) {
  379. PageSpecificContentSettings::DeleteForPage(web_contents->GetPrimaryPage());
  380. web_contents->RemoveUserData(WebContentsHandler::UserDataKey());
  381. }
  382. // static
  383. PageSpecificContentSettings* PageSpecificContentSettings::GetForFrame(
  384. int render_process_id,
  385. int render_frame_id) {
  386. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  387. return GetForFrame(
  388. content::RenderFrameHost::FromID(render_process_id, render_frame_id));
  389. }
  390. // static
  391. PageSpecificContentSettings* PageSpecificContentSettings::GetForFrame(
  392. content::RenderFrameHost* rfh) {
  393. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  394. return rfh ? PageSpecificContentSettings::GetForPage(rfh->GetPage())
  395. : nullptr;
  396. }
  397. // static
  398. PageSpecificContentSettings::Delegate*
  399. PageSpecificContentSettings::GetDelegateForWebContents(
  400. content::WebContents* web_contents) {
  401. auto* handler = WebContentsHandler::FromWebContents(web_contents);
  402. return handler ? handler->delegate() : nullptr;
  403. }
  404. // static
  405. void PageSpecificContentSettings::StorageAccessed(StorageType storage_type,
  406. int render_process_id,
  407. int render_frame_id,
  408. const GURL& url,
  409. bool blocked_by_policy) {
  410. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  411. content::RenderFrameHost* rfh =
  412. content::RenderFrameHost::FromID(render_process_id, render_frame_id);
  413. if (DelayUntilCommitIfNecessary(
  414. rfh, &PageSpecificContentSettings::StorageAccessed, storage_type,
  415. render_process_id, render_frame_id, url, blocked_by_policy))
  416. return;
  417. PageSpecificContentSettings* settings =
  418. GetForFrame(render_process_id, render_frame_id);
  419. if (settings)
  420. settings->OnStorageAccessed(storage_type, url, blocked_by_policy);
  421. }
  422. // static
  423. void PageSpecificContentSettings::ContentBlocked(int render_process_id,
  424. int render_frame_id,
  425. ContentSettingsType type) {
  426. content::RenderFrameHost* rfh =
  427. content::RenderFrameHost::FromID(render_process_id, render_frame_id);
  428. if (DelayUntilCommitIfNecessary(rfh,
  429. &PageSpecificContentSettings::ContentBlocked,
  430. render_process_id, render_frame_id, type))
  431. return;
  432. PageSpecificContentSettings* settings = GetForFrame(rfh);
  433. if (settings)
  434. settings->OnContentBlocked(type);
  435. }
  436. // static
  437. void PageSpecificContentSettings::SharedWorkerAccessed(
  438. int render_process_id,
  439. int render_frame_id,
  440. const GURL& worker_url,
  441. const std::string& name,
  442. const blink::StorageKey& storage_key,
  443. bool blocked_by_policy) {
  444. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  445. PageSpecificContentSettings* settings =
  446. GetForFrame(render_process_id, render_frame_id);
  447. if (settings)
  448. settings->OnSharedWorkerAccessed(worker_url, name, storage_key,
  449. blocked_by_policy);
  450. }
  451. // static
  452. void PageSpecificContentSettings::InterestGroupJoined(
  453. content::RenderFrameHost* rfh,
  454. const url::Origin api_origin,
  455. bool blocked_by_policy) {
  456. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  457. PageSpecificContentSettings* settings = GetForFrame(rfh);
  458. if (settings)
  459. settings->OnInterestGroupJoined(api_origin, blocked_by_policy);
  460. }
  461. // static
  462. void PageSpecificContentSettings::TopicAccessed(
  463. content::RenderFrameHost* rfh,
  464. const url::Origin api_origin,
  465. bool blocked_by_policy,
  466. privacy_sandbox::CanonicalTopic topic) {
  467. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  468. PageSpecificContentSettings* settings = GetForFrame(rfh);
  469. if (settings)
  470. settings->OnTopicAccessed(api_origin, blocked_by_policy, topic);
  471. }
  472. // static
  473. content::WebContentsObserver*
  474. PageSpecificContentSettings::GetWebContentsObserverForTest(
  475. content::WebContents* web_contents) {
  476. return WebContentsHandler::FromWebContents(web_contents);
  477. }
  478. bool PageSpecificContentSettings::IsContentBlocked(
  479. ContentSettingsType content_type) const {
  480. DCHECK_NE(ContentSettingsType::NOTIFICATIONS, content_type)
  481. << "Notifications settings handled by "
  482. << "ContentSettingsNotificationsImageModel";
  483. DCHECK_NE(ContentSettingsType::AUTOMATIC_DOWNLOADS, content_type)
  484. << "Automatic downloads handled by DownloadRequestLimiter";
  485. if (content_type == ContentSettingsType::IMAGES ||
  486. content_type == ContentSettingsType::JAVASCRIPT ||
  487. content_type == ContentSettingsType::COOKIES ||
  488. content_type == ContentSettingsType::POPUPS ||
  489. content_type == ContentSettingsType::MIXEDSCRIPT ||
  490. content_type == ContentSettingsType::MEDIASTREAM_MIC ||
  491. content_type == ContentSettingsType::MEDIASTREAM_CAMERA ||
  492. content_type == ContentSettingsType::PPAPI_BROKER ||
  493. content_type == ContentSettingsType::MIDI_SYSEX ||
  494. content_type == ContentSettingsType::ADS ||
  495. content_type == ContentSettingsType::SOUND ||
  496. content_type == ContentSettingsType::CLIPBOARD_READ_WRITE ||
  497. content_type == ContentSettingsType::SENSORS ||
  498. content_type == ContentSettingsType::GEOLOCATION) {
  499. const auto& it = content_settings_status_.find(content_type);
  500. if (it != content_settings_status_.end())
  501. return it->second.blocked;
  502. }
  503. return false;
  504. }
  505. bool PageSpecificContentSettings::IsContentAllowed(
  506. ContentSettingsType content_type) const {
  507. DCHECK_NE(ContentSettingsType::AUTOMATIC_DOWNLOADS, content_type)
  508. << "Automatic downloads handled by DownloadRequestLimiter";
  509. // This method currently only returns meaningful values for the types listed
  510. // below.
  511. if (content_type != ContentSettingsType::COOKIES &&
  512. content_type != ContentSettingsType::MEDIASTREAM_MIC &&
  513. content_type != ContentSettingsType::MEDIASTREAM_CAMERA &&
  514. content_type != ContentSettingsType::PPAPI_BROKER &&
  515. content_type != ContentSettingsType::MIDI_SYSEX &&
  516. content_type != ContentSettingsType::CLIPBOARD_READ_WRITE &&
  517. content_type != ContentSettingsType::SENSORS &&
  518. content_type != ContentSettingsType::GEOLOCATION) {
  519. return false;
  520. }
  521. const auto& it = content_settings_status_.find(content_type);
  522. if (it != content_settings_status_.end())
  523. return it->second.allowed;
  524. return false;
  525. }
  526. void PageSpecificContentSettings::OnContentBlocked(ContentSettingsType type) {
  527. DCHECK(type != ContentSettingsType::MEDIASTREAM_MIC &&
  528. type != ContentSettingsType::MEDIASTREAM_CAMERA)
  529. << "Media stream settings handled by OnMediaStreamPermissionSet";
  530. if (!content_settings::ContentSettingsRegistry::GetInstance()->Get(type))
  531. return;
  532. ContentSettingsStatus& status = content_settings_status_[type];
  533. if (!status.blocked) {
  534. status.blocked = true;
  535. MaybeUpdateLocationBar();
  536. NotifyDelegate(&Delegate::OnContentBlocked, type);
  537. MaybeUpdateParent(&PageSpecificContentSettings::OnContentBlocked, type);
  538. }
  539. }
  540. void PageSpecificContentSettings::OnContentAllowed(ContentSettingsType type) {
  541. DCHECK(type != ContentSettingsType::MEDIASTREAM_MIC &&
  542. type != ContentSettingsType::MEDIASTREAM_CAMERA)
  543. << "Media stream settings handled by OnMediaStreamPermissionSet";
  544. bool access_changed = false;
  545. ContentSettingsStatus& status = content_settings_status_[type];
  546. // Whether to reset status for the |blocked| setting to avoid ending up
  547. // with both |allowed| and |blocked| set, which can mean multiple things
  548. // (allowed setting that got disabled, disabled setting that got enabled).
  549. bool must_reset_blocked_status = false;
  550. // For sensors, the status with both allowed/blocked flags set means that
  551. // access was previously allowed but the last decision was to block.
  552. // Reset the blocked flag so that the UI will properly indicate that the
  553. // last decision here instead was to allow sensor access.
  554. if (type == ContentSettingsType::SENSORS)
  555. must_reset_blocked_status = true;
  556. #if BUILDFLAG(IS_ANDROID)
  557. // content_settings_status_[type].allowed is always set to true in
  558. // OnContentBlocked, so we have to use
  559. // content_settings_status_[type].blocked to detect whether the protected
  560. // media setting has changed.
  561. if (type == ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER)
  562. must_reset_blocked_status = true;
  563. #endif
  564. if (must_reset_blocked_status && status.blocked) {
  565. status.blocked = false;
  566. access_changed = true;
  567. }
  568. if (!status.allowed) {
  569. status.allowed = true;
  570. access_changed = true;
  571. NotifyDelegate(&Delegate::OnContentAllowed, type);
  572. }
  573. if (access_changed) {
  574. MaybeUpdateLocationBar();
  575. MaybeUpdateParent(&PageSpecificContentSettings::OnContentAllowed, type);
  576. }
  577. }
  578. namespace {
  579. void AddToContainer(browsing_data::LocalSharedObjectsContainer& container,
  580. StorageType storage_type,
  581. const GURL& url) {
  582. url::Origin origin = url::Origin::Create(url);
  583. switch (storage_type) {
  584. case StorageType::DATABASE:
  585. container.databases()->Add(origin);
  586. return;
  587. case StorageType::LOCAL_STORAGE:
  588. // TODO(https://crbug.com/1199077): Pass the real StorageKey into this
  589. // function directly.
  590. container.local_storages()->Add(blink::StorageKey(origin));
  591. return;
  592. case StorageType::SESSION_STORAGE:
  593. // TODO(https://crbug.com/1199077): Pass the real StorageKey into this
  594. // function directly.
  595. container.session_storages()->Add(blink::StorageKey(origin));
  596. return;
  597. case StorageType::INDEXED_DB:
  598. // TODO(https://crbug.com/1199077): Pass the real StorageKey into this
  599. // function directly.
  600. container.indexed_dbs()->Add(blink::StorageKey(origin));
  601. return;
  602. case StorageType::CACHE:
  603. container.cache_storages()->Add(origin);
  604. return;
  605. case StorageType::FILE_SYSTEM:
  606. container.file_systems()->Add(origin);
  607. return;
  608. case StorageType::WEB_LOCKS:
  609. NOTREACHED();
  610. return;
  611. }
  612. }
  613. } // namespace
  614. void PageSpecificContentSettings::OnStorageAccessed(
  615. StorageType storage_type,
  616. const GURL& url,
  617. bool blocked_by_policy,
  618. content::Page* originating_page) {
  619. originating_page = originating_page ? originating_page : &page();
  620. if (blocked_by_policy) {
  621. AddToContainer(blocked_local_shared_objects_, storage_type, url);
  622. OnContentBlocked(ContentSettingsType::COOKIES);
  623. } else {
  624. AddToContainer(allowed_local_shared_objects_, storage_type, url);
  625. NotifyDelegate(&Delegate::OnStorageAccessAllowed, storage_type,
  626. url::Origin::Create(url), std::ref(*originating_page));
  627. OnContentAllowed(ContentSettingsType::COOKIES);
  628. }
  629. MaybeUpdateParent(&PageSpecificContentSettings::OnStorageAccessed,
  630. storage_type, url, blocked_by_policy, originating_page);
  631. MaybeNotifySiteDataObservers();
  632. }
  633. void PageSpecificContentSettings::OnCookiesAccessed(
  634. const content::CookieAccessDetails& details,
  635. content::Page* originating_page) {
  636. originating_page = originating_page ? originating_page : &page();
  637. if (details.cookie_list.empty())
  638. return;
  639. if (details.blocked_by_policy) {
  640. blocked_local_shared_objects_.cookies()->AddCookies(details);
  641. OnContentBlocked(ContentSettingsType::COOKIES);
  642. } else {
  643. allowed_local_shared_objects_.cookies()->AddCookies(details);
  644. OnContentAllowed(ContentSettingsType::COOKIES);
  645. NotifyDelegate(&Delegate::OnCookieAccessAllowed, details.cookie_list,
  646. std::ref(*originating_page));
  647. }
  648. MaybeUpdateParent(&PageSpecificContentSettings::OnCookiesAccessed, details,
  649. originating_page);
  650. MaybeNotifySiteDataObservers();
  651. }
  652. void PageSpecificContentSettings::OnServiceWorkerAccessed(
  653. const GURL& scope,
  654. content::AllowServiceWorkerResult allowed,
  655. content::Page* originating_page) {
  656. DCHECK(scope.is_valid());
  657. originating_page = originating_page ? originating_page : &page();
  658. if (allowed) {
  659. allowed_local_shared_objects_.service_workers()->Add(
  660. url::Origin::Create(scope));
  661. NotifyDelegate(&Delegate::OnServiceWorkerAccessAllowed,
  662. url::Origin::Create(scope), std::ref(*originating_page));
  663. } else {
  664. blocked_local_shared_objects_.service_workers()->Add(
  665. url::Origin::Create(scope));
  666. }
  667. if (allowed.javascript_blocked_by_policy()) {
  668. OnContentBlocked(ContentSettingsType::JAVASCRIPT);
  669. } else {
  670. OnContentAllowed(ContentSettingsType::JAVASCRIPT);
  671. }
  672. if (allowed.cookies_blocked_by_policy()) {
  673. OnContentBlocked(ContentSettingsType::COOKIES);
  674. } else {
  675. OnContentAllowed(ContentSettingsType::COOKIES);
  676. }
  677. MaybeUpdateParent(&PageSpecificContentSettings::OnServiceWorkerAccessed,
  678. scope, allowed, originating_page);
  679. }
  680. void PageSpecificContentSettings::OnSharedWorkerAccessed(
  681. const GURL& worker_url,
  682. const std::string& name,
  683. const blink::StorageKey& storage_key,
  684. bool blocked_by_policy) {
  685. DCHECK(worker_url.is_valid());
  686. if (blocked_by_policy) {
  687. blocked_local_shared_objects_.shared_workers()->AddSharedWorker(
  688. worker_url, name, storage_key);
  689. OnContentBlocked(ContentSettingsType::COOKIES);
  690. } else {
  691. allowed_local_shared_objects_.shared_workers()->AddSharedWorker(
  692. worker_url, name, storage_key);
  693. OnContentAllowed(ContentSettingsType::COOKIES);
  694. }
  695. MaybeUpdateParent(&PageSpecificContentSettings::OnSharedWorkerAccessed,
  696. worker_url, name, storage_key, blocked_by_policy);
  697. }
  698. void PageSpecificContentSettings::OnInterestGroupJoined(
  699. const url::Origin api_origin,
  700. bool blocked_by_policy) {
  701. if (blocked_by_policy) {
  702. blocked_interest_group_api_.push_back(api_origin);
  703. OnContentBlocked(ContentSettingsType::COOKIES);
  704. } else {
  705. allowed_interest_group_api_.push_back(api_origin);
  706. OnContentAllowed(ContentSettingsType::COOKIES);
  707. }
  708. MaybeUpdateParent(&PageSpecificContentSettings::OnInterestGroupJoined,
  709. api_origin, blocked_by_policy);
  710. MaybeNotifySiteDataObservers();
  711. }
  712. void PageSpecificContentSettings::OnTopicAccessed(
  713. const url::Origin api_origin,
  714. bool blocked_by_policy,
  715. privacy_sandbox::CanonicalTopic topic) {
  716. // TODO(crbug.com/1286276): Add URL and Topic to local_shared_objects?
  717. accessed_topics_.insert(topic);
  718. MaybeUpdateParent(&PageSpecificContentSettings::OnTopicAccessed, api_origin,
  719. blocked_by_policy, topic);
  720. }
  721. #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
  722. void PageSpecificContentSettings::OnProtectedMediaIdentifierPermissionSet(
  723. const GURL& requesting_origin,
  724. bool allowed) {
  725. if (allowed) {
  726. OnContentAllowed(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER);
  727. } else {
  728. OnContentBlocked(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER);
  729. }
  730. }
  731. #endif
  732. PageSpecificContentSettings::MicrophoneCameraState
  733. PageSpecificContentSettings::GetMicrophoneCameraState() const {
  734. return microphone_camera_state_ | delegate_->GetMicrophoneCameraState();
  735. }
  736. bool PageSpecificContentSettings::IsMicrophoneCameraStateChanged() const {
  737. if ((microphone_camera_state_ & MICROPHONE_ACCESSED) &&
  738. ((microphone_camera_state_ & MICROPHONE_BLOCKED)
  739. ? !IsContentBlocked(ContentSettingsType::MEDIASTREAM_MIC)
  740. : !IsContentAllowed(ContentSettingsType::MEDIASTREAM_MIC)))
  741. return true;
  742. if ((microphone_camera_state_ & CAMERA_ACCESSED) &&
  743. ((microphone_camera_state_ & CAMERA_BLOCKED)
  744. ? !IsContentBlocked(ContentSettingsType::MEDIASTREAM_CAMERA)
  745. : !IsContentAllowed(ContentSettingsType::MEDIASTREAM_CAMERA)))
  746. return true;
  747. return delegate_->IsMicrophoneCameraStateChanged(
  748. microphone_camera_state_, media_stream_selected_audio_device(),
  749. media_stream_selected_video_device());
  750. }
  751. void PageSpecificContentSettings::OnMediaStreamPermissionSet(
  752. const GURL& request_origin,
  753. MicrophoneCameraState new_microphone_camera_state,
  754. const std::string& media_stream_selected_audio_device,
  755. const std::string& media_stream_selected_video_device,
  756. const std::string& media_stream_requested_audio_device,
  757. const std::string& media_stream_requested_video_device) {
  758. DCHECK(!IsEmbeddedPage());
  759. media_stream_access_origin_ = request_origin;
  760. if (new_microphone_camera_state & MICROPHONE_ACCESSED) {
  761. media_stream_requested_audio_device_ = media_stream_requested_audio_device;
  762. media_stream_selected_audio_device_ = media_stream_selected_audio_device;
  763. bool mic_blocked = (new_microphone_camera_state & MICROPHONE_BLOCKED) != 0;
  764. ContentSettingsStatus& status =
  765. content_settings_status_[ContentSettingsType::MEDIASTREAM_MIC];
  766. if (!status.allowed && !mic_blocked) {
  767. NotifyDelegate(&Delegate::OnContentAllowed,
  768. ContentSettingsType::MEDIASTREAM_MIC);
  769. }
  770. status.allowed = !mic_blocked;
  771. status.blocked = mic_blocked;
  772. }
  773. if (new_microphone_camera_state & CAMERA_ACCESSED) {
  774. media_stream_requested_video_device_ = media_stream_requested_video_device;
  775. media_stream_selected_video_device_ = media_stream_selected_video_device;
  776. bool cam_blocked = (new_microphone_camera_state & CAMERA_BLOCKED) != 0;
  777. ContentSettingsStatus& status =
  778. content_settings_status_[ContentSettingsType::MEDIASTREAM_CAMERA];
  779. if (!status.allowed && !cam_blocked) {
  780. NotifyDelegate(&Delegate::OnContentAllowed,
  781. ContentSettingsType::MEDIASTREAM_CAMERA);
  782. }
  783. status.allowed = !cam_blocked;
  784. status.blocked = cam_blocked;
  785. }
  786. if (microphone_camera_state_ != new_microphone_camera_state) {
  787. microphone_camera_state_ = new_microphone_camera_state;
  788. MaybeUpdateLocationBar();
  789. }
  790. }
  791. void PageSpecificContentSettings::ClearPopupsBlocked() {
  792. ContentSettingsStatus& status =
  793. content_settings_status_[ContentSettingsType::POPUPS];
  794. status.blocked = false;
  795. MaybeUpdateLocationBar();
  796. }
  797. void PageSpecificContentSettings::OnAudioBlocked() {
  798. OnContentBlocked(ContentSettingsType::SOUND);
  799. }
  800. void PageSpecificContentSettings::SetPepperBrokerAllowed(bool allowed) {
  801. if (allowed) {
  802. OnContentAllowed(ContentSettingsType::PPAPI_BROKER);
  803. } else {
  804. OnContentBlocked(ContentSettingsType::PPAPI_BROKER);
  805. }
  806. }
  807. void PageSpecificContentSettings::OnContentSettingChanged(
  808. const ContentSettingsPattern& primary_pattern,
  809. const ContentSettingsPattern& secondary_pattern,
  810. ContentSettingsType content_type) {
  811. if (IsEmbeddedPage())
  812. return;
  813. const GURL current_url = page().GetMainDocument().GetLastCommittedURL();
  814. if (!primary_pattern.Matches(current_url)) {
  815. return;
  816. }
  817. ContentSettingsStatus& status = content_settings_status_[content_type];
  818. switch (content_type) {
  819. case ContentSettingsType::MEDIASTREAM_MIC:
  820. case ContentSettingsType::MEDIASTREAM_CAMERA: {
  821. const GURL media_origin = media_stream_access_origin();
  822. ContentSetting setting =
  823. map_->GetContentSetting(media_origin, media_origin, content_type);
  824. if (content_type == ContentSettingsType::MEDIASTREAM_MIC &&
  825. setting == CONTENT_SETTING_ALLOW) {
  826. mic_was_just_granted_on_site_level_ = true;
  827. }
  828. if (content_type == ContentSettingsType::MEDIASTREAM_CAMERA &&
  829. setting == CONTENT_SETTING_ALLOW) {
  830. camera_was_just_granted_on_site_level_ = true;
  831. }
  832. status.allowed = setting == CONTENT_SETTING_ALLOW;
  833. status.blocked = setting == CONTENT_SETTING_BLOCK;
  834. break;
  835. }
  836. case ContentSettingsType::GEOLOCATION: {
  837. ContentSetting geolocation_setting =
  838. map_->GetContentSetting(current_url, current_url, content_type);
  839. if (geolocation_setting == CONTENT_SETTING_ALLOW)
  840. geolocation_was_just_granted_on_site_level_ = true;
  841. [[fallthrough]];
  842. }
  843. case ContentSettingsType::IMAGES:
  844. case ContentSettingsType::JAVASCRIPT:
  845. case ContentSettingsType::COOKIES:
  846. case ContentSettingsType::POPUPS:
  847. case ContentSettingsType::MIXEDSCRIPT:
  848. case ContentSettingsType::PPAPI_BROKER:
  849. case ContentSettingsType::MIDI_SYSEX:
  850. case ContentSettingsType::ADS:
  851. case ContentSettingsType::SOUND:
  852. case ContentSettingsType::CLIPBOARD_READ_WRITE:
  853. case ContentSettingsType::SENSORS: {
  854. ContentSetting setting =
  855. map_->GetContentSetting(current_url, current_url, content_type);
  856. // If an indicator is shown and the content settings has changed, swap the
  857. // indicator for the one with the opposite meaning (allowed <=> blocked).
  858. if (setting == CONTENT_SETTING_BLOCK && status.allowed) {
  859. status.blocked = false;
  860. status.allowed = false;
  861. OnContentBlocked(content_type);
  862. } else if (setting == CONTENT_SETTING_ALLOW && status.blocked) {
  863. status.blocked = false;
  864. status.allowed = false;
  865. OnContentAllowed(content_type);
  866. }
  867. break;
  868. }
  869. default:
  870. break;
  871. }
  872. }
  873. void PageSpecificContentSettings::ClearContentSettingsChangedViaPageInfo() {
  874. content_settings_changed_via_page_info_.clear();
  875. }
  876. void PageSpecificContentSettings::BlockAllContentForTesting() {
  877. content_settings::ContentSettingsRegistry* registry =
  878. content_settings::ContentSettingsRegistry::GetInstance();
  879. for (const content_settings::ContentSettingsInfo* info : *registry) {
  880. ContentSettingsType type = info->website_settings_info()->type();
  881. if (type != ContentSettingsType::MEDIASTREAM_MIC &&
  882. type != ContentSettingsType::MEDIASTREAM_CAMERA) {
  883. OnContentBlocked(type);
  884. }
  885. }
  886. // Media must be blocked separately, as the generic
  887. // PageSpecificContentSettings::OnContentBlocked does not apply to them.
  888. MicrophoneCameraStateFlags media_blocked =
  889. static_cast<MicrophoneCameraStateFlags>(
  890. PageSpecificContentSettings::MICROPHONE_ACCESSED |
  891. PageSpecificContentSettings::MICROPHONE_BLOCKED |
  892. PageSpecificContentSettings::CAMERA_ACCESSED |
  893. PageSpecificContentSettings::CAMERA_BLOCKED);
  894. OnMediaStreamPermissionSet(page().GetMainDocument().GetLastCommittedURL(),
  895. media_blocked, std::string(), std::string(),
  896. std::string(), std::string());
  897. }
  898. void PageSpecificContentSettings::ContentSettingChangedViaPageInfo(
  899. ContentSettingsType type) {
  900. content_settings_changed_via_page_info_.insert(type);
  901. }
  902. bool PageSpecificContentSettings::HasContentSettingChangedViaPageInfo(
  903. ContentSettingsType type) const {
  904. return content_settings_changed_via_page_info_.find(type) !=
  905. content_settings_changed_via_page_info_.end();
  906. }
  907. bool PageSpecificContentSettings::HasAccessedTopics() const {
  908. return !GetAccessedTopics().empty();
  909. }
  910. std::vector<privacy_sandbox::CanonicalTopic>
  911. PageSpecificContentSettings::GetAccessedTopics() const {
  912. if (accessed_topics_.empty() &&
  913. privacy_sandbox::kPrivacySandboxSettings3ShowSampleDataForTesting.Get() &&
  914. page().GetMainDocument().GetLastCommittedURL().host() == "example.com") {
  915. // TODO(crbug.com/1286276): Remove sample topic when API is ready.
  916. return {privacy_sandbox::CanonicalTopic(
  917. browsing_topics::Topic(1),
  918. privacy_sandbox::CanonicalTopic::AVAILABLE_TAXONOMY)};
  919. }
  920. return {accessed_topics_.begin(), accessed_topics_.end()};
  921. }
  922. bool PageSpecificContentSettings::HasJoinedUserToInterestGroup() const {
  923. return !allowed_interest_group_api_.empty();
  924. }
  925. bool PageSpecificContentSettings::IsPagePrerendering() const {
  926. // We consider the Page to be prerendering iff
  927. // |updates_queued_during_prerender_| is non null. Note, the page already may
  928. // already have exited prerendering as |updates_queued_during_prerender_| is
  929. // flushed in DidFinishNavigation for the prerender activation but other
  930. // observers may come before this and call into here. In that case we'll still
  931. // queue their updates.
  932. return !!updates_queued_during_prerender_;
  933. }
  934. bool PageSpecificContentSettings::IsEmbeddedPage() const {
  935. return page().GetMainDocument().GetParentOrOuterDocument();
  936. }
  937. void PageSpecificContentSettings::OnPrerenderingPageActivation() {
  938. DCHECK(updates_queued_during_prerender_);
  939. for (auto& delegate_update :
  940. updates_queued_during_prerender_->delegate_updates) {
  941. std::move(delegate_update).Run();
  942. }
  943. if (updates_queued_during_prerender_->site_data_accessed) {
  944. WebContentsHandler::FromWebContents(GetWebContents())
  945. ->NotifySiteDataObservers();
  946. }
  947. updates_queued_during_prerender_.reset();
  948. }
  949. void PageSpecificContentSettings::MaybeNotifySiteDataObservers() {
  950. if (IsEmbeddedPage())
  951. return;
  952. if (IsPagePrerendering()) {
  953. updates_queued_during_prerender_->site_data_accessed = true;
  954. return;
  955. }
  956. WebContentsHandler::FromWebContents(GetWebContents())
  957. ->NotifySiteDataObservers();
  958. }
  959. void PageSpecificContentSettings::MaybeUpdateLocationBar() {
  960. if (IsEmbeddedPage())
  961. return;
  962. if (IsPagePrerendering())
  963. return;
  964. delegate_->UpdateLocationBar();
  965. }
  966. content::WebContents* PageSpecificContentSettings::GetWebContents() const {
  967. return content::WebContents::FromRenderFrameHost(&page().GetMainDocument());
  968. }
  969. PAGE_USER_DATA_KEY_IMPL(PageSpecificContentSettings);
  970. } // namespace content_settings