Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / content_settings / tab_specific_content_settings.cc
blob9cba89a265777b6f6bece4f91b818d5df854d6b8
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.
5 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
7 #include <list>
9 #include "base/command_line.h"
10 #include "base/lazy_instance.h"
11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/browsing_data/browsing_data_appcache_helper.h"
13 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
14 #include "chrome/browser/browsing_data/browsing_data_database_helper.h"
15 #include "chrome/browser/browsing_data/browsing_data_file_system_helper.h"
16 #include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h"
17 #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h"
18 #include "chrome/browser/browsing_data/cookies_tree_model.h"
19 #include "chrome/browser/content_settings/content_settings_details.h"
20 #include "chrome/browser/content_settings/content_settings_utils.h"
21 #include "chrome/browser/content_settings/host_content_settings_map.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/common/chrome_notification_types.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/render_messages.h"
26 #include "content/public/browser/navigation_controller.h"
27 #include "content/public/browser/navigation_details.h"
28 #include "content/public/browser/navigation_entry.h"
29 #include "content/public/browser/notification_service.h"
30 #include "content/public/browser/render_view_host.h"
31 #include "content/public/browser/render_view_host_observer.h"
32 #include "content/public/browser/web_contents.h"
33 #include "content/public/browser/web_contents_delegate.h"
34 #include "net/cookies/canonical_cookie.h"
35 #include "webkit/fileapi/file_system_types.h"
37 using content::BrowserThread;
38 using content::NavigationController;
39 using content::NavigationEntry;
40 using content::RenderViewHost;
41 using content::WebContents;
43 DEFINE_WEB_CONTENTS_USER_DATA_KEY(TabSpecificContentSettings)
45 namespace {
47 class InterstitialHostObserver : public content::RenderViewHostObserver {
48 public:
49 explicit InterstitialHostObserver(RenderViewHost* rvh)
50 : content::RenderViewHostObserver(rvh) {}
52 // content::RenderViewHostObserver overrides.
53 virtual void RenderViewHostInitialized() OVERRIDE {
54 Send(new ChromeViewMsg_SetAsInterstitial(routing_id()));
55 delete this;
59 } // namespace
61 TabSpecificContentSettings::SiteDataObserver::SiteDataObserver(
62 TabSpecificContentSettings* tab_specific_content_settings)
63 : tab_specific_content_settings_(tab_specific_content_settings) {
64 tab_specific_content_settings_->AddSiteDataObserver(this);
67 TabSpecificContentSettings::SiteDataObserver::~SiteDataObserver() {
68 if (tab_specific_content_settings_)
69 tab_specific_content_settings_->RemoveSiteDataObserver(this);
72 void TabSpecificContentSettings::SiteDataObserver::ContentSettingsDestroyed() {
73 tab_specific_content_settings_ = NULL;
76 TabSpecificContentSettings::TabSpecificContentSettings(WebContents* tab)
77 : content::WebContentsObserver(tab),
78 profile_(Profile::FromBrowserContext(tab->GetBrowserContext())),
79 allowed_local_shared_objects_(profile_),
80 blocked_local_shared_objects_(profile_),
81 geolocation_settings_state_(profile_),
82 pending_protocol_handler_(ProtocolHandler::EmptyProtocolHandler()),
83 previous_protocol_handler_(ProtocolHandler::EmptyProtocolHandler()),
84 pending_protocol_handler_setting_(CONTENT_SETTING_DEFAULT),
85 load_plugins_link_enabled_(true) {
86 ClearBlockedContentSettingsExceptForCookies();
87 ClearCookieSpecificContentSettings();
89 registrar_.Add(this, chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
90 content::Source<HostContentSettingsMap>(
91 profile_->GetHostContentSettingsMap()));
94 TabSpecificContentSettings::~TabSpecificContentSettings() {
95 FOR_EACH_OBSERVER(
96 SiteDataObserver, observer_list_, ContentSettingsDestroyed());
99 TabSpecificContentSettings* TabSpecificContentSettings::Get(
100 int render_process_id, int render_view_id) {
101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
103 RenderViewHost* view = RenderViewHost::FromID(render_process_id,
104 render_view_id);
105 if (!view)
106 return NULL;
108 return TabSpecificContentSettings::FromWebContents(
109 WebContents::FromRenderViewHost(view));
112 // static
113 void TabSpecificContentSettings::CookiesRead(int render_process_id,
114 int render_view_id,
115 const GURL& url,
116 const GURL& frame_url,
117 const net::CookieList& cookie_list,
118 bool blocked_by_policy) {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
120 TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
121 if (settings) {
122 settings->OnCookiesRead(url, frame_url, cookie_list,
123 blocked_by_policy);
127 // static
128 void TabSpecificContentSettings::CookieChanged(
129 int render_process_id,
130 int render_view_id,
131 const GURL& url,
132 const GURL& frame_url,
133 const std::string& cookie_line,
134 const net::CookieOptions& options,
135 bool blocked_by_policy) {
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
137 TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
138 if (settings)
139 settings->OnCookieChanged(url, frame_url, cookie_line, options,
140 blocked_by_policy);
143 // static
144 void TabSpecificContentSettings::WebDatabaseAccessed(
145 int render_process_id,
146 int render_view_id,
147 const GURL& url,
148 const string16& name,
149 const string16& display_name,
150 bool blocked_by_policy) {
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
152 TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
153 if (settings)
154 settings->OnWebDatabaseAccessed(url, name, display_name, blocked_by_policy);
157 // static
158 void TabSpecificContentSettings::DOMStorageAccessed(int render_process_id,
159 int render_view_id,
160 const GURL& url,
161 bool local,
162 bool blocked_by_policy) {
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
164 TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
165 if (settings)
166 settings->OnLocalStorageAccessed(url, local, blocked_by_policy);
169 // static
170 void TabSpecificContentSettings::IndexedDBAccessed(int render_process_id,
171 int render_view_id,
172 const GURL& url,
173 const string16& description,
174 bool blocked_by_policy) {
175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
176 TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
177 if (settings)
178 settings->OnIndexedDBAccessed(url, description, blocked_by_policy);
181 // static
182 void TabSpecificContentSettings::FileSystemAccessed(int render_process_id,
183 int render_view_id,
184 const GURL& url,
185 bool blocked_by_policy) {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
187 TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
188 if (settings)
189 settings->OnFileSystemAccessed(url, blocked_by_policy);
192 bool TabSpecificContentSettings::IsContentBlocked(
193 ContentSettingsType content_type) const {
194 DCHECK(content_type != CONTENT_SETTINGS_TYPE_GEOLOCATION)
195 << "Geolocation settings handled by ContentSettingGeolocationImageModel";
196 DCHECK(content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS)
197 << "Notifications settings handled by "
198 << "ContentSettingsNotificationsImageModel";
200 if (content_type == CONTENT_SETTINGS_TYPE_IMAGES ||
201 content_type == CONTENT_SETTINGS_TYPE_JAVASCRIPT ||
202 content_type == CONTENT_SETTINGS_TYPE_PLUGINS ||
203 content_type == CONTENT_SETTINGS_TYPE_COOKIES ||
204 content_type == CONTENT_SETTINGS_TYPE_POPUPS ||
205 content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT)
206 return content_blocked_[content_type];
208 return false;
211 bool TabSpecificContentSettings::IsBlockageIndicated(
212 ContentSettingsType content_type) const {
213 return content_blockage_indicated_to_user_[content_type];
216 void TabSpecificContentSettings::SetBlockageHasBeenIndicated(
217 ContentSettingsType content_type) {
218 content_blockage_indicated_to_user_[content_type] = true;
221 bool TabSpecificContentSettings::IsContentAccessed(
222 ContentSettingsType content_type) const {
223 // This method currently only returns meaningful values for cookies.
224 if (content_type != CONTENT_SETTINGS_TYPE_COOKIES)
225 return false;
227 return content_accessed_[content_type];
230 const std::set<std::string>&
231 TabSpecificContentSettings::BlockedResourcesForType(
232 ContentSettingsType content_type) const {
233 if (blocked_resources_[content_type].get()) {
234 return *blocked_resources_[content_type];
235 } else {
236 CR_DEFINE_STATIC_LOCAL(std::set<std::string>, empty_set, ());
237 return empty_set;
241 void TabSpecificContentSettings::AddBlockedResource(
242 ContentSettingsType content_type,
243 const std::string& resource_identifier) {
244 if (!blocked_resources_[content_type].get())
245 blocked_resources_[content_type].reset(new std::set<std::string>());
246 blocked_resources_[content_type]->insert(resource_identifier);
249 void TabSpecificContentSettings::OnContentBlocked(
250 ContentSettingsType type,
251 const std::string& resource_identifier) {
252 DCHECK(type != CONTENT_SETTINGS_TYPE_GEOLOCATION)
253 << "Geolocation settings handled by OnGeolocationPermissionSet";
254 content_accessed_[type] = true;
255 // Unless UI for resource content settings is enabled, ignore the resource
256 // identifier.
257 // TODO(bauerb): The UI to unblock content should be disabled if the content
258 // setting was not set by the user.
259 std::string identifier;
260 if (CommandLine::ForCurrentProcess()->HasSwitch(
261 switches::kEnableResourceContentSettings)) {
262 identifier = resource_identifier;
264 if (!identifier.empty())
265 AddBlockedResource(type, identifier);
267 #if defined (OS_ANDROID)
268 if (type == CONTENT_SETTINGS_TYPE_POPUPS) {
269 // For Android we do not have a persistent button that will always be
270 // visible for blocked popups. Instead we have info bars which could be
271 // dismissed. Have to clear the blocked state so we properly notify the
272 // relevant pieces again.
273 content_blocked_[type] = false;
274 content_blockage_indicated_to_user_[type] = false;
276 #endif
278 if (!content_blocked_[type]) {
279 content_blocked_[type] = true;
280 // TODO: it would be nice to have a way of mocking this in tests.
281 content::NotificationService::current()->Notify(
282 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
283 content::Source<WebContents>(web_contents()),
284 content::NotificationService::NoDetails());
288 void TabSpecificContentSettings::OnContentAccessed(ContentSettingsType type) {
289 DCHECK(type != CONTENT_SETTINGS_TYPE_GEOLOCATION)
290 << "Geolocation settings handled by OnGeolocationPermissionSet";
291 if (!content_accessed_[type]) {
292 content_accessed_[type] = true;
293 content::NotificationService::current()->Notify(
294 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
295 content::Source<WebContents>(web_contents()),
296 content::NotificationService::NoDetails());
300 void TabSpecificContentSettings::OnCookiesRead(
301 const GURL& url,
302 const GURL& frame_url,
303 const net::CookieList& cookie_list,
304 bool blocked_by_policy) {
305 if (cookie_list.empty())
306 return;
307 if (blocked_by_policy) {
308 blocked_local_shared_objects_.cookies()->AddReadCookies(
309 frame_url, url, cookie_list);
310 OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
311 } else {
312 allowed_local_shared_objects_.cookies()->AddReadCookies(
313 frame_url, url, cookie_list);
314 OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
317 NotifySiteDataObservers();
320 void TabSpecificContentSettings::OnCookieChanged(
321 const GURL& url,
322 const GURL& frame_url,
323 const std::string& cookie_line,
324 const net::CookieOptions& options,
325 bool blocked_by_policy) {
326 if (blocked_by_policy) {
327 blocked_local_shared_objects_.cookies()->AddChangedCookie(
328 frame_url, url, cookie_line, options);
329 OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
330 } else {
331 allowed_local_shared_objects_.cookies()->AddChangedCookie(
332 frame_url, url, cookie_line, options);
333 OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
336 NotifySiteDataObservers();
339 void TabSpecificContentSettings::OnIndexedDBAccessed(
340 const GURL& url,
341 const string16& description,
342 bool blocked_by_policy) {
343 if (blocked_by_policy) {
344 blocked_local_shared_objects_.indexed_dbs()->AddIndexedDB(
345 url, description);
346 OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
347 } else {
348 allowed_local_shared_objects_.indexed_dbs()->AddIndexedDB(
349 url, description);
350 OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
353 NotifySiteDataObservers();
356 void TabSpecificContentSettings::OnLocalStorageAccessed(
357 const GURL& url,
358 bool local,
359 bool blocked_by_policy) {
360 LocalSharedObjectsContainer& container = blocked_by_policy ?
361 blocked_local_shared_objects_ : allowed_local_shared_objects_;
362 CannedBrowsingDataLocalStorageHelper* helper =
363 local ? container.local_storages() : container.session_storages();
364 helper->AddLocalStorage(url);
366 if (blocked_by_policy)
367 OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
368 else
369 OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
371 NotifySiteDataObservers();
374 void TabSpecificContentSettings::OnWebDatabaseAccessed(
375 const GURL& url,
376 const string16& name,
377 const string16& display_name,
378 bool blocked_by_policy) {
379 if (blocked_by_policy) {
380 blocked_local_shared_objects_.databases()->AddDatabase(
381 url, UTF16ToUTF8(name), UTF16ToUTF8(display_name));
382 OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
383 } else {
384 allowed_local_shared_objects_.databases()->AddDatabase(
385 url, UTF16ToUTF8(name), UTF16ToUTF8(display_name));
386 OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
389 NotifySiteDataObservers();
392 void TabSpecificContentSettings::OnFileSystemAccessed(
393 const GURL& url,
394 bool blocked_by_policy) {
395 if (blocked_by_policy) {
396 blocked_local_shared_objects_.file_systems()->AddFileSystem(url,
397 fileapi::kFileSystemTypeTemporary, 0);
398 OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
399 } else {
400 allowed_local_shared_objects_.file_systems()->AddFileSystem(url,
401 fileapi::kFileSystemTypeTemporary, 0);
402 OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
405 NotifySiteDataObservers();
408 void TabSpecificContentSettings::OnGeolocationPermissionSet(
409 const GURL& requesting_origin,
410 bool allowed) {
411 geolocation_settings_state_.OnGeolocationPermissionSet(requesting_origin,
412 allowed);
413 content::NotificationService::current()->Notify(
414 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
415 content::Source<WebContents>(web_contents()),
416 content::NotificationService::NoDetails());
419 void TabSpecificContentSettings::ClearBlockedContentSettingsExceptForCookies() {
420 for (size_t i = 0; i < arraysize(content_blocked_); ++i) {
421 if (i == CONTENT_SETTINGS_TYPE_COOKIES)
422 continue;
423 blocked_resources_[i].reset();
424 content_blocked_[i] = false;
425 content_accessed_[i] = false;
426 content_blockage_indicated_to_user_[i] = false;
428 load_plugins_link_enabled_ = true;
429 content::NotificationService::current()->Notify(
430 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
431 content::Source<WebContents>(web_contents()),
432 content::NotificationService::NoDetails());
435 void TabSpecificContentSettings::ClearCookieSpecificContentSettings() {
436 blocked_local_shared_objects_.Reset();
437 allowed_local_shared_objects_.Reset();
438 content_blocked_[CONTENT_SETTINGS_TYPE_COOKIES] = false;
439 content_accessed_[CONTENT_SETTINGS_TYPE_COOKIES] = false;
440 content_blockage_indicated_to_user_[CONTENT_SETTINGS_TYPE_COOKIES] = false;
441 content::NotificationService::current()->Notify(
442 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
443 content::Source<WebContents>(web_contents()),
444 content::NotificationService::NoDetails());
447 void TabSpecificContentSettings::SetPopupsBlocked(bool blocked) {
448 content_blocked_[CONTENT_SETTINGS_TYPE_POPUPS] = blocked;
449 content_blockage_indicated_to_user_[CONTENT_SETTINGS_TYPE_POPUPS] = false;
450 content::NotificationService::current()->Notify(
451 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
452 content::Source<WebContents>(web_contents()),
453 content::NotificationService::NoDetails());
456 void TabSpecificContentSettings::GeolocationDidNavigate(
457 const content::LoadCommittedDetails& details) {
458 geolocation_settings_state_.DidNavigate(details);
461 void TabSpecificContentSettings::ClearGeolocationContentSettings() {
462 geolocation_settings_state_.ClearStateMap();
465 void TabSpecificContentSettings::RenderViewForInterstitialPageCreated(
466 RenderViewHost* render_view_host) {
467 // We want to tell the renderer-side code to ignore content settings for this
468 // page but we must wait until the RenderView is created.
469 new InterstitialHostObserver(render_view_host);
472 bool TabSpecificContentSettings::OnMessageReceived(
473 const IPC::Message& message) {
474 bool handled = true;
475 IPC_BEGIN_MESSAGE_MAP(TabSpecificContentSettings, message)
476 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ContentBlocked, OnContentBlocked)
477 IPC_MESSAGE_UNHANDLED(handled = false)
478 IPC_END_MESSAGE_MAP()
479 return handled;
482 void TabSpecificContentSettings::DidNavigateMainFrame(
483 const content::LoadCommittedDetails& details,
484 const content::FrameNavigateParams& params) {
485 if (!details.is_in_page) {
486 // Clear "blocked" flags.
487 ClearBlockedContentSettingsExceptForCookies();
488 GeolocationDidNavigate(details);
492 void TabSpecificContentSettings::DidStartProvisionalLoadForFrame(
493 int64 frame_id,
494 int64 parent_frame_id,
495 bool is_main_frame,
496 const GURL& validated_url,
497 bool is_error_page,
498 RenderViewHost* render_view_host) {
499 if (!is_main_frame)
500 return;
502 // If we're displaying a network error page do not reset the content
503 // settings delegate's cookies so the user has a chance to modify cookie
504 // settings.
505 if (!is_error_page)
506 ClearCookieSpecificContentSettings();
507 ClearGeolocationContentSettings();
510 void TabSpecificContentSettings::AppCacheAccessed(const GURL& manifest_url,
511 bool blocked_by_policy) {
512 if (blocked_by_policy) {
513 blocked_local_shared_objects_.appcaches()->AddAppCache(manifest_url);
514 OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
515 } else {
516 allowed_local_shared_objects_.appcaches()->AddAppCache(manifest_url);
517 OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
521 void TabSpecificContentSettings::Observe(
522 int type,
523 const content::NotificationSource& source,
524 const content::NotificationDetails& details) {
525 DCHECK(type == chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED);
527 content::Details<const ContentSettingsDetails> settings_details(details);
528 const NavigationController& controller = web_contents()->GetController();
529 NavigationEntry* entry = controller.GetActiveEntry();
530 GURL entry_url;
531 if (entry)
532 entry_url = entry->GetURL();
533 if (settings_details.ptr()->update_all() ||
534 // The active NavigationEntry is the URL in the URL field of a tab.
535 // Currently this should be matched by the |primary_pattern|.
536 settings_details.ptr()->primary_pattern().Matches(entry_url)) {
537 Profile* profile =
538 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
539 RendererContentSettingRules rules;
540 GetRendererContentSettingRules(profile->GetHostContentSettingsMap(),
541 &rules);
542 Send(new ChromeViewMsg_SetContentSettingRules(rules));
546 void TabSpecificContentSettings::AddSiteDataObserver(
547 SiteDataObserver* observer) {
548 observer_list_.AddObserver(observer);
551 void TabSpecificContentSettings::RemoveSiteDataObserver(
552 SiteDataObserver* observer) {
553 observer_list_.RemoveObserver(observer);
556 void TabSpecificContentSettings::NotifySiteDataObservers() {
557 FOR_EACH_OBSERVER(SiteDataObserver, observer_list_, OnSiteDataAccessed());