tab_specific_content_settings.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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
5#include "chrome/browser/content_settings/tab_specific_content_settings.h"
6
7#include <list>
8
9#include "base/command_line.h"
10#include "base/lazy_instance.h"
11#include "base/strings/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/chrome_notification_types.h"
20#include "chrome/browser/content_settings/content_settings_details.h"
21#include "chrome/browser/content_settings/content_settings_utils.h"
22#include "chrome/browser/content_settings/host_content_settings_map.h"
23#include "chrome/browser/profiles/profile.h"
24#include "chrome/common/chrome_switches.h"
25#include "chrome/common/render_messages.h"
26#include "content/public/browser/browser_thread.h"
27#include "content/public/browser/navigation_controller.h"
28#include "content/public/browser/navigation_details.h"
29#include "content/public/browser/navigation_entry.h"
30#include "content/public/browser/notification_service.h"
31#include "content/public/browser/render_view_host.h"
32#include "content/public/browser/render_view_host_observer.h"
33#include "content/public/browser/web_contents.h"
34#include "content/public/browser/web_contents_delegate.h"
35#include "net/cookies/canonical_cookie.h"
36#include "webkit/common/fileapi/file_system_types.h"
37
38using content::BrowserThread;
39using content::NavigationController;
40using content::NavigationEntry;
41using content::RenderViewHost;
42using content::WebContents;
43
44DEFINE_WEB_CONTENTS_USER_DATA_KEY(TabSpecificContentSettings);
45
46namespace {
47
48class InterstitialHostObserver : public content::RenderViewHostObserver {
49 public:
50  explicit InterstitialHostObserver(RenderViewHost* rvh)
51      : content::RenderViewHostObserver(rvh) {}
52
53  // content::RenderViewHostObserver overrides.
54  virtual void RenderViewHostInitialized() OVERRIDE {
55    Send(new ChromeViewMsg_SetAsInterstitial(routing_id()));
56    delete this;
57  }
58};
59
60}  // namespace
61
62TabSpecificContentSettings::SiteDataObserver::SiteDataObserver(
63    TabSpecificContentSettings* tab_specific_content_settings)
64    : tab_specific_content_settings_(tab_specific_content_settings) {
65  tab_specific_content_settings_->AddSiteDataObserver(this);
66}
67
68TabSpecificContentSettings::SiteDataObserver::~SiteDataObserver() {
69  if (tab_specific_content_settings_)
70    tab_specific_content_settings_->RemoveSiteDataObserver(this);
71}
72
73void TabSpecificContentSettings::SiteDataObserver::ContentSettingsDestroyed() {
74  tab_specific_content_settings_ = NULL;
75}
76
77TabSpecificContentSettings::TabSpecificContentSettings(WebContents* tab)
78    : content::WebContentsObserver(tab),
79      profile_(Profile::FromBrowserContext(tab->GetBrowserContext())),
80      allowed_local_shared_objects_(profile_),
81      blocked_local_shared_objects_(profile_),
82      geolocation_settings_state_(profile_),
83      pending_protocol_handler_(ProtocolHandler::EmptyProtocolHandler()),
84      previous_protocol_handler_(ProtocolHandler::EmptyProtocolHandler()),
85      pending_protocol_handler_setting_(CONTENT_SETTING_DEFAULT),
86      load_plugins_link_enabled_(true) {
87  ClearBlockedContentSettingsExceptForCookies();
88  ClearCookieSpecificContentSettings();
89
90  registrar_.Add(this, chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
91                 content::Source<HostContentSettingsMap>(
92                     profile_->GetHostContentSettingsMap()));
93}
94
95TabSpecificContentSettings::~TabSpecificContentSettings() {
96  FOR_EACH_OBSERVER(
97      SiteDataObserver, observer_list_, ContentSettingsDestroyed());
98}
99
100TabSpecificContentSettings* TabSpecificContentSettings::Get(
101    int render_process_id, int render_view_id) {
102  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
103
104  RenderViewHost* view = RenderViewHost::FromID(render_process_id,
105                                                render_view_id);
106  if (!view)
107    return NULL;
108
109  WebContents* web_contents = WebContents::FromRenderViewHost(view);
110  if (!web_contents)
111    return NULL;
112
113  return TabSpecificContentSettings::FromWebContents(web_contents);
114}
115
116// static
117void TabSpecificContentSettings::CookiesRead(int render_process_id,
118                                             int render_view_id,
119                                             const GURL& url,
120                                             const GURL& frame_url,
121                                             const net::CookieList& cookie_list,
122                                             bool blocked_by_policy) {
123  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
124  TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
125  if (settings) {
126    settings->OnCookiesRead(url, frame_url, cookie_list,
127                            blocked_by_policy);
128  }
129}
130
131// static
132void TabSpecificContentSettings::CookieChanged(
133    int render_process_id,
134    int render_view_id,
135    const GURL& url,
136    const GURL& frame_url,
137    const std::string& cookie_line,
138    const net::CookieOptions& options,
139    bool blocked_by_policy) {
140  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
141  TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
142  if (settings)
143    settings->OnCookieChanged(url, frame_url, cookie_line, options,
144                              blocked_by_policy);
145}
146
147// static
148void TabSpecificContentSettings::WebDatabaseAccessed(
149    int render_process_id,
150    int render_view_id,
151    const GURL& url,
152    const string16& name,
153    const string16& display_name,
154    bool blocked_by_policy) {
155  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
156  TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
157  if (settings)
158    settings->OnWebDatabaseAccessed(url, name, display_name, blocked_by_policy);
159}
160
161// static
162void TabSpecificContentSettings::DOMStorageAccessed(int render_process_id,
163                                                    int render_view_id,
164                                                    const GURL& url,
165                                                    bool local,
166                                                    bool blocked_by_policy) {
167  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168  TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
169  if (settings)
170    settings->OnLocalStorageAccessed(url, local, blocked_by_policy);
171}
172
173// static
174void TabSpecificContentSettings::IndexedDBAccessed(int render_process_id,
175                                                   int render_view_id,
176                                                   const GURL& url,
177                                                   const string16& description,
178                                                   bool blocked_by_policy) {
179  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
180  TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
181  if (settings)
182    settings->OnIndexedDBAccessed(url, description, blocked_by_policy);
183}
184
185// static
186void TabSpecificContentSettings::FileSystemAccessed(int render_process_id,
187                                                    int render_view_id,
188                                                    const GURL& url,
189                                                    bool blocked_by_policy) {
190  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
191  TabSpecificContentSettings* settings = Get(render_process_id, render_view_id);
192  if (settings)
193    settings->OnFileSystemAccessed(url, blocked_by_policy);
194}
195
196bool TabSpecificContentSettings::IsContentBlocked(
197    ContentSettingsType content_type) const {
198  DCHECK(content_type != CONTENT_SETTINGS_TYPE_GEOLOCATION)
199      << "Geolocation settings handled by ContentSettingGeolocationImageModel";
200  DCHECK(content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS)
201      << "Notifications settings handled by "
202      << "ContentSettingsNotificationsImageModel";
203
204  if (content_type == CONTENT_SETTINGS_TYPE_IMAGES ||
205      content_type == CONTENT_SETTINGS_TYPE_JAVASCRIPT ||
206      content_type == CONTENT_SETTINGS_TYPE_PLUGINS ||
207      content_type == CONTENT_SETTINGS_TYPE_COOKIES ||
208      content_type == CONTENT_SETTINGS_TYPE_POPUPS ||
209      content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
210      content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM ||
211      content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
212      content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA ||
213      content_type == CONTENT_SETTINGS_TYPE_PPAPI_BROKER ||
214      content_type == CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS) {
215    return content_blocked_[content_type];
216  }
217
218  return false;
219}
220
221bool TabSpecificContentSettings::IsBlockageIndicated(
222    ContentSettingsType content_type) const {
223  return content_blockage_indicated_to_user_[content_type];
224}
225
226void TabSpecificContentSettings::SetBlockageHasBeenIndicated(
227    ContentSettingsType content_type) {
228  content_blockage_indicated_to_user_[content_type] = true;
229}
230
231bool TabSpecificContentSettings::IsContentAllowed(
232    ContentSettingsType content_type) const {
233  // This method currently only returns meaningful values for the content type
234  // cookies, mediastream, PPAPI broker, and downloads.
235  if (content_type != CONTENT_SETTINGS_TYPE_COOKIES &&
236      content_type != CONTENT_SETTINGS_TYPE_MEDIASTREAM &&
237      content_type != CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC &&
238      content_type != CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA &&
239      content_type != CONTENT_SETTINGS_TYPE_PPAPI_BROKER &&
240      content_type != CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS) {
241    return false;
242  }
243
244  return content_allowed_[content_type];
245}
246
247const std::set<std::string>&
248    TabSpecificContentSettings::BlockedResourcesForType(
249        ContentSettingsType content_type) const {
250  if (blocked_resources_[content_type].get()) {
251    return *blocked_resources_[content_type];
252  } else {
253    CR_DEFINE_STATIC_LOCAL(std::set<std::string>, empty_set, ());
254    return empty_set;
255  }
256}
257
258void TabSpecificContentSettings::AddBlockedResource(
259    ContentSettingsType content_type,
260    const std::string& resource_identifier) {
261  if (!blocked_resources_[content_type].get())
262    blocked_resources_[content_type].reset(new std::set<std::string>());
263  blocked_resources_[content_type]->insert(resource_identifier);
264}
265
266void TabSpecificContentSettings::OnContentBlocked(
267    ContentSettingsType type,
268    const std::string& resource_identifier) {
269  DCHECK(type != CONTENT_SETTINGS_TYPE_GEOLOCATION)
270      << "Geolocation settings handled by OnGeolocationPermissionSet";
271  if (type < 0 || type >= CONTENT_SETTINGS_NUM_TYPES)
272    return;
273
274  // Media is different from other content setting types since it allows new
275  // setting to kick in without reloading the page, and the UI for media is
276  // always reflecting the newest permission setting.
277  if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
278      type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)
279    content_allowed_[type] = false;
280  else
281    content_allowed_[type] = true;
282
283  // Unless UI for resource content settings is enabled, ignore the resource
284  // identifier.
285  // TODO(bauerb): The UI to unblock content should be disabled if the content
286  // setting was not set by the user.
287  std::string identifier;
288  if (CommandLine::ForCurrentProcess()->HasSwitch(
289      switches::kEnableResourceContentSettings)) {
290    identifier = resource_identifier;
291  }
292  if (!identifier.empty())
293    AddBlockedResource(type, identifier);
294
295#if defined (OS_ANDROID)
296  if (type == CONTENT_SETTINGS_TYPE_POPUPS) {
297    // For Android we do not have a persistent button that will always be
298    // visible for blocked popups.  Instead we have info bars which could be
299    // dismissed.  Have to clear the blocked state so we properly notify the
300    // relevant pieces again.
301    content_blocked_[type] = false;
302    content_blockage_indicated_to_user_[type] = false;
303  }
304#endif
305
306  if (!content_blocked_[type]) {
307    content_blocked_[type] = true;
308    // TODO: it would be nice to have a way of mocking this in tests.
309    content::NotificationService::current()->Notify(
310        chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
311        content::Source<WebContents>(web_contents()),
312        content::NotificationService::NoDetails());
313  }
314}
315
316void TabSpecificContentSettings::OnContentAllowed(ContentSettingsType type) {
317  DCHECK(type != CONTENT_SETTINGS_TYPE_GEOLOCATION)
318      << "Geolocation settings handled by OnGeolocationPermissionSet";
319  bool access_changed = false;
320  if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
321    // The setting for media is overwritten here because media does not need to
322    // reload the page to have the new setting kick in. See issue/175993.
323    if (content_blocked_[type]) {
324      content_blocked_[type] = false;
325      access_changed = true;
326    }
327  }
328
329  if (!content_allowed_[type]) {
330    content_allowed_[type] = true;
331    access_changed = true;
332  }
333
334  if (access_changed) {
335    content::NotificationService::current()->Notify(
336        chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
337        content::Source<WebContents>(web_contents()),
338        content::NotificationService::NoDetails());
339  }
340}
341
342void TabSpecificContentSettings::OnCookiesRead(
343    const GURL& url,
344    const GURL& frame_url,
345    const net::CookieList& cookie_list,
346    bool blocked_by_policy) {
347  if (cookie_list.empty())
348    return;
349  if (blocked_by_policy) {
350    blocked_local_shared_objects_.cookies()->AddReadCookies(
351        frame_url, url, cookie_list);
352    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
353  } else {
354    allowed_local_shared_objects_.cookies()->AddReadCookies(
355        frame_url, url, cookie_list);
356    OnContentAllowed(CONTENT_SETTINGS_TYPE_COOKIES);
357  }
358
359  NotifySiteDataObservers();
360}
361
362void TabSpecificContentSettings::OnCookieChanged(
363    const GURL& url,
364    const GURL& frame_url,
365    const std::string& cookie_line,
366    const net::CookieOptions& options,
367    bool blocked_by_policy) {
368  if (blocked_by_policy) {
369    blocked_local_shared_objects_.cookies()->AddChangedCookie(
370        frame_url, url, cookie_line, options);
371    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
372  } else {
373    allowed_local_shared_objects_.cookies()->AddChangedCookie(
374        frame_url, url, cookie_line, options);
375    OnContentAllowed(CONTENT_SETTINGS_TYPE_COOKIES);
376  }
377
378  NotifySiteDataObservers();
379}
380
381void TabSpecificContentSettings::OnIndexedDBAccessed(
382    const GURL& url,
383    const string16& description,
384    bool blocked_by_policy) {
385  if (blocked_by_policy) {
386    blocked_local_shared_objects_.indexed_dbs()->AddIndexedDB(
387        url, description);
388    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
389  } else {
390    allowed_local_shared_objects_.indexed_dbs()->AddIndexedDB(
391        url, description);
392    OnContentAllowed(CONTENT_SETTINGS_TYPE_COOKIES);
393  }
394
395  NotifySiteDataObservers();
396}
397
398void TabSpecificContentSettings::OnLocalStorageAccessed(
399    const GURL& url,
400    bool local,
401    bool blocked_by_policy) {
402  LocalSharedObjectsContainer& container = blocked_by_policy ?
403      blocked_local_shared_objects_ : allowed_local_shared_objects_;
404  CannedBrowsingDataLocalStorageHelper* helper =
405      local ? container.local_storages() : container.session_storages();
406  helper->AddLocalStorage(url);
407
408  if (blocked_by_policy)
409    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
410  else
411    OnContentAllowed(CONTENT_SETTINGS_TYPE_COOKIES);
412
413  NotifySiteDataObservers();
414}
415
416void TabSpecificContentSettings::OnWebDatabaseAccessed(
417    const GURL& url,
418    const string16& name,
419    const string16& display_name,
420    bool blocked_by_policy) {
421  if (blocked_by_policy) {
422    blocked_local_shared_objects_.databases()->AddDatabase(
423        url, UTF16ToUTF8(name), UTF16ToUTF8(display_name));
424    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
425  } else {
426    allowed_local_shared_objects_.databases()->AddDatabase(
427        url, UTF16ToUTF8(name), UTF16ToUTF8(display_name));
428    OnContentAllowed(CONTENT_SETTINGS_TYPE_COOKIES);
429  }
430
431  NotifySiteDataObservers();
432}
433
434void TabSpecificContentSettings::OnFileSystemAccessed(
435    const GURL& url,
436    bool blocked_by_policy) {
437  if (blocked_by_policy) {
438    blocked_local_shared_objects_.file_systems()->AddFileSystem(url,
439        fileapi::kFileSystemTypeTemporary, 0);
440    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
441  } else {
442    allowed_local_shared_objects_.file_systems()->AddFileSystem(url,
443        fileapi::kFileSystemTypeTemporary, 0);
444    OnContentAllowed(CONTENT_SETTINGS_TYPE_COOKIES);
445  }
446
447  NotifySiteDataObservers();
448}
449
450void TabSpecificContentSettings::OnGeolocationPermissionSet(
451    const GURL& requesting_origin,
452    bool allowed) {
453  geolocation_settings_state_.OnGeolocationPermissionSet(requesting_origin,
454                                                         allowed);
455  content::NotificationService::current()->Notify(
456      chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
457      content::Source<WebContents>(web_contents()),
458      content::NotificationService::NoDetails());
459}
460
461TabSpecificContentSettings::MicrophoneCameraState
462TabSpecificContentSettings::GetMicrophoneCameraState() const {
463  if (IsContentAllowed(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) &&
464      IsContentAllowed(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)) {
465    return MICROPHONE_CAMERA_ACCESSED;
466  } else if (IsContentAllowed(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)) {
467    return MICROPHONE_ACCESSED;
468  } else if (IsContentAllowed(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)) {
469    return CAMERA_ACCESSED;
470  }
471
472  if (IsContentBlocked(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) &&
473      IsContentBlocked(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)) {
474    return MICROPHONE_CAMERA_BLOCKED;
475  } else if (IsContentBlocked(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)) {
476    return MICROPHONE_BLOCKED;
477  } else if (IsContentBlocked(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)) {
478    return CAMERA_BLOCKED;
479  }
480
481  return MICROPHONE_CAMERA_NOT_ACCESSED;
482}
483
484void TabSpecificContentSettings::OnMicrophoneAccessed() {
485  OnContentAllowed(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
486}
487
488void TabSpecificContentSettings::OnMicrophoneAccessBlocked() {
489  OnContentBlocked(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string());
490}
491
492void TabSpecificContentSettings::OnCameraAccessed() {
493  OnContentAllowed(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
494}
495
496void TabSpecificContentSettings::OnCameraAccessBlocked() {
497  OnContentBlocked(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string());
498}
499
500void TabSpecificContentSettings::ClearBlockedContentSettingsExceptForCookies() {
501  for (size_t i = 0; i < arraysize(content_blocked_); ++i) {
502    if (i == CONTENT_SETTINGS_TYPE_COOKIES)
503      continue;
504    blocked_resources_[i].reset();
505    content_blocked_[i] = false;
506    content_allowed_[i] = false;
507    content_blockage_indicated_to_user_[i] = false;
508  }
509  load_plugins_link_enabled_ = true;
510  content::NotificationService::current()->Notify(
511      chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
512      content::Source<WebContents>(web_contents()),
513      content::NotificationService::NoDetails());
514}
515
516void TabSpecificContentSettings::ClearCookieSpecificContentSettings() {
517  blocked_local_shared_objects_.Reset();
518  allowed_local_shared_objects_.Reset();
519  content_blocked_[CONTENT_SETTINGS_TYPE_COOKIES] = false;
520  content_allowed_[CONTENT_SETTINGS_TYPE_COOKIES] = false;
521  content_blockage_indicated_to_user_[CONTENT_SETTINGS_TYPE_COOKIES] = false;
522  content::NotificationService::current()->Notify(
523      chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
524      content::Source<WebContents>(web_contents()),
525      content::NotificationService::NoDetails());
526}
527
528void TabSpecificContentSettings::SetDownloadsBlocked(bool blocked) {
529  content_blocked_[CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS] = blocked;
530  content_allowed_[CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS] = !blocked;
531  content_blockage_indicated_to_user_[
532    CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS] = false;
533  content::NotificationService::current()->Notify(
534      chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
535      content::Source<WebContents>(web_contents()),
536      content::NotificationService::NoDetails());
537}
538
539void TabSpecificContentSettings::SetPopupsBlocked(bool blocked) {
540  content_blocked_[CONTENT_SETTINGS_TYPE_POPUPS] = blocked;
541  content_blockage_indicated_to_user_[CONTENT_SETTINGS_TYPE_POPUPS] = false;
542  content::NotificationService::current()->Notify(
543      chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
544      content::Source<WebContents>(web_contents()),
545      content::NotificationService::NoDetails());
546}
547
548void TabSpecificContentSettings::GeolocationDidNavigate(
549      const content::LoadCommittedDetails& details) {
550  geolocation_settings_state_.DidNavigate(details);
551}
552
553void TabSpecificContentSettings::ClearGeolocationContentSettings() {
554  geolocation_settings_state_.ClearStateMap();
555}
556
557void TabSpecificContentSettings::SetPepperBrokerAllowed(bool allowed) {
558  if (allowed) {
559    OnContentAllowed(CONTENT_SETTINGS_TYPE_PPAPI_BROKER);
560  } else {
561    OnContentBlocked(CONTENT_SETTINGS_TYPE_PPAPI_BROKER, std::string());
562  }
563}
564
565void TabSpecificContentSettings::RenderViewForInterstitialPageCreated(
566    RenderViewHost* render_view_host) {
567  // We want to tell the renderer-side code to ignore content settings for this
568  // page but we must wait until the RenderView is created.
569  new InterstitialHostObserver(render_view_host);
570}
571
572bool TabSpecificContentSettings::OnMessageReceived(
573    const IPC::Message& message) {
574  bool handled = true;
575  IPC_BEGIN_MESSAGE_MAP(TabSpecificContentSettings, message)
576    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ContentBlocked, OnContentBlocked)
577    IPC_MESSAGE_UNHANDLED(handled = false)
578  IPC_END_MESSAGE_MAP()
579  return handled;
580}
581
582void TabSpecificContentSettings::DidNavigateMainFrame(
583    const content::LoadCommittedDetails& details,
584    const content::FrameNavigateParams& params) {
585  if (!details.is_in_page) {
586    // Clear "blocked" flags.
587    ClearBlockedContentSettingsExceptForCookies();
588    GeolocationDidNavigate(details);
589  }
590}
591
592void TabSpecificContentSettings::DidStartProvisionalLoadForFrame(
593    int64 frame_id,
594    int64 parent_frame_id,
595    bool is_main_frame,
596    const GURL& validated_url,
597    bool is_error_page,
598    bool is_iframe_srcdoc,
599    RenderViewHost* render_view_host) {
600  if (!is_main_frame)
601    return;
602
603  // If we're displaying a network error page do not reset the content
604  // settings delegate's cookies so the user has a chance to modify cookie
605  // settings.
606  if (!is_error_page)
607    ClearCookieSpecificContentSettings();
608  ClearGeolocationContentSettings();
609}
610
611void TabSpecificContentSettings::AppCacheAccessed(const GURL& manifest_url,
612                                                  bool blocked_by_policy) {
613  if (blocked_by_policy) {
614    blocked_local_shared_objects_.appcaches()->AddAppCache(manifest_url);
615    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
616  } else {
617    allowed_local_shared_objects_.appcaches()->AddAppCache(manifest_url);
618    OnContentAllowed(CONTENT_SETTINGS_TYPE_COOKIES);
619  }
620}
621
622void TabSpecificContentSettings::Observe(
623    int type,
624    const content::NotificationSource& source,
625    const content::NotificationDetails& details) {
626  DCHECK(type == chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED);
627
628  content::Details<const ContentSettingsDetails> settings_details(details);
629  const NavigationController& controller = web_contents()->GetController();
630  NavigationEntry* entry = controller.GetActiveEntry();
631  GURL entry_url;
632  if (entry)
633    entry_url = entry->GetURL();
634  if (settings_details.ptr()->update_all() ||
635      // The active NavigationEntry is the URL in the URL field of a tab.
636      // Currently this should be matched by the |primary_pattern|.
637      settings_details.ptr()->primary_pattern().Matches(entry_url)) {
638    Profile* profile =
639        Profile::FromBrowserContext(web_contents()->GetBrowserContext());
640    RendererContentSettingRules rules;
641    GetRendererContentSettingRules(profile->GetHostContentSettingsMap(),
642                                   &rules);
643    Send(new ChromeViewMsg_SetContentSettingRules(rules));
644  }
645}
646
647void TabSpecificContentSettings::AddSiteDataObserver(
648    SiteDataObserver* observer) {
649  observer_list_.AddObserver(observer);
650}
651
652void TabSpecificContentSettings::RemoveSiteDataObserver(
653    SiteDataObserver* observer) {
654  observer_list_.RemoveObserver(observer);
655}
656
657void TabSpecificContentSettings::NotifySiteDataObservers() {
658  FOR_EACH_OBSERVER(SiteDataObserver, observer_list_, OnSiteDataAccessed());
659}
660