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