1// Copyright (c) 2011 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/tab_contents/tab_specific_content_settings.h"
6
7#include "base/utf_string_conversions.h"
8#include "chrome/browser/browsing_data_appcache_helper.h"
9#include "chrome/browser/browsing_data_database_helper.h"
10#include "chrome/browser/browsing_data_indexed_db_helper.h"
11#include "chrome/browser/browsing_data_local_storage_helper.h"
12#include "chrome/browser/cookies_tree_model.h"
13#include "net/base/cookie_monster.h"
14
15bool TabSpecificContentSettings::LocalSharedObjectsContainer::empty() const {
16  return cookies_->GetAllCookies().empty() &&
17      appcaches_->empty() &&
18      databases_->empty() &&
19      indexed_dbs_->empty() &&
20      local_storages_->empty() &&
21      session_storages_->empty();
22}
23
24bool TabSpecificContentSettings::IsContentBlocked(
25    ContentSettingsType content_type) const {
26  DCHECK(content_type != CONTENT_SETTINGS_TYPE_GEOLOCATION)
27      << "Geolocation settings handled by ContentSettingGeolocationImageModel";
28  DCHECK(content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS)
29      << "Notifications settings handled by "
30      << "ContentSettingsNotificationsImageModel";
31
32  if (content_type == CONTENT_SETTINGS_TYPE_IMAGES ||
33      content_type == CONTENT_SETTINGS_TYPE_JAVASCRIPT ||
34      content_type == CONTENT_SETTINGS_TYPE_PLUGINS ||
35      content_type == CONTENT_SETTINGS_TYPE_COOKIES ||
36      content_type == CONTENT_SETTINGS_TYPE_POPUPS)
37    return content_blocked_[content_type];
38
39  NOTREACHED();
40  return false;
41}
42
43bool TabSpecificContentSettings::IsBlockageIndicated(
44    ContentSettingsType content_type) const {
45  return content_blockage_indicated_to_user_[content_type];
46}
47
48void TabSpecificContentSettings::SetBlockageHasBeenIndicated(
49    ContentSettingsType content_type) {
50  content_blockage_indicated_to_user_[content_type] = true;
51}
52
53bool TabSpecificContentSettings::IsContentAccessed(
54    ContentSettingsType content_type) const {
55  // This method currently only returns meaningful values for cookies.
56  if (content_type != CONTENT_SETTINGS_TYPE_COOKIES)
57    return false;
58
59  return content_accessed_[content_type];
60}
61
62const std::set<std::string>&
63    TabSpecificContentSettings::BlockedResourcesForType(
64        ContentSettingsType content_type) const {
65  if (blocked_resources_[content_type].get()) {
66    return *blocked_resources_[content_type];
67  } else {
68    static std::set<std::string> empty_set;
69    return empty_set;
70  }
71}
72
73void TabSpecificContentSettings::AddBlockedResource(
74    ContentSettingsType content_type,
75    const std::string& resource_identifier) {
76  if (!blocked_resources_[content_type].get())
77    blocked_resources_[content_type].reset(new std::set<std::string>());
78  blocked_resources_[content_type]->insert(resource_identifier);
79}
80
81void TabSpecificContentSettings::OnContentBlocked(
82    ContentSettingsType type,
83    const std::string& resource_identifier) {
84  DCHECK(type != CONTENT_SETTINGS_TYPE_GEOLOCATION)
85      << "Geolocation settings handled by OnGeolocationPermissionSet";
86  content_accessed_[type] = true;
87  if (!resource_identifier.empty())
88    AddBlockedResource(type, resource_identifier);
89  if (!content_blocked_[type]) {
90    content_blocked_[type] = true;
91    if (delegate_)
92      delegate_->OnContentSettingsAccessed(true);
93  }
94}
95
96void TabSpecificContentSettings::OnContentAccessed(ContentSettingsType type) {
97  DCHECK(type != CONTENT_SETTINGS_TYPE_GEOLOCATION)
98      << "Geolocation settings handled by OnGeolocationPermissionSet";
99  if (!content_accessed_[type]) {
100    content_accessed_[type] = true;
101    if (delegate_)
102      delegate_->OnContentSettingsAccessed(false);
103  }
104}
105
106void TabSpecificContentSettings::OnCookiesRead(
107    const GURL& url,
108    const net::CookieList& cookie_list,
109    bool blocked_by_policy) {
110  if (cookie_list.empty())
111    return;
112  LocalSharedObjectsContainer& container = blocked_by_policy ?
113      blocked_local_shared_objects_ : allowed_local_shared_objects_;
114  typedef net::CookieList::const_iterator cookie_iterator;
115  for (cookie_iterator cookie = cookie_list.begin();
116       cookie != cookie_list.end(); ++cookie) {
117    container.cookies()->SetCookieWithDetails(url,
118                                              cookie->Name(),
119                                              cookie->Value(),
120                                              cookie->Domain(),
121                                              cookie->Path(),
122                                              cookie->ExpiryDate(),
123                                              cookie->IsSecure(),
124                                              cookie->IsHttpOnly());
125  }
126  if (blocked_by_policy)
127    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
128  else
129    OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
130}
131
132void TabSpecificContentSettings::OnCookieChanged(
133    const GURL& url,
134    const std::string& cookie_line,
135    const net::CookieOptions& options,
136    bool blocked_by_policy) {
137  if (blocked_by_policy) {
138    blocked_local_shared_objects_.cookies()->SetCookieWithOptions(
139        url, cookie_line, options);
140    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
141  } else {
142    allowed_local_shared_objects_.cookies()->SetCookieWithOptions(
143        url, cookie_line, options);
144    OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
145  }
146}
147
148void TabSpecificContentSettings::OnIndexedDBAccessed(
149    const GURL& url,
150    const string16& description,
151    bool blocked_by_policy) {
152  if (blocked_by_policy) {
153    blocked_local_shared_objects_.indexed_dbs()->AddIndexedDB(
154        url, description);
155    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
156  }else {
157    allowed_local_shared_objects_.indexed_dbs()->AddIndexedDB(
158        url, description);
159    OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
160  }
161}
162
163void TabSpecificContentSettings::OnLocalStorageAccessed(
164    const GURL& url,
165    DOMStorageType storage_type,
166    bool blocked_by_policy) {
167  LocalSharedObjectsContainer& container = blocked_by_policy ?
168      blocked_local_shared_objects_ : allowed_local_shared_objects_;
169  CannedBrowsingDataLocalStorageHelper* helper =
170      storage_type == DOM_STORAGE_LOCAL ?
171          container.local_storages() : container.session_storages();
172  helper->AddLocalStorage(url);
173
174  if (blocked_by_policy)
175    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
176  else
177    OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
178}
179
180void TabSpecificContentSettings::OnWebDatabaseAccessed(
181    const GURL& url,
182    const string16& name,
183    const string16& display_name,
184    unsigned long estimated_size,
185    bool blocked_by_policy) {
186  if (blocked_by_policy) {
187    blocked_local_shared_objects_.databases()->AddDatabase(
188        url, UTF16ToUTF8(name), UTF16ToUTF8(display_name));
189    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
190  } else {
191    allowed_local_shared_objects_.databases()->AddDatabase(
192        url, UTF16ToUTF8(name), UTF16ToUTF8(display_name));
193    OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
194  }
195}
196
197void TabSpecificContentSettings::OnAppCacheAccessed(
198    const GURL& manifest_url, bool blocked_by_policy) {
199  if (blocked_by_policy) {
200    blocked_local_shared_objects_.appcaches()->AddAppCache(manifest_url);
201    OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES, std::string());
202  } else {
203    allowed_local_shared_objects_.appcaches()->AddAppCache(manifest_url);
204    OnContentAccessed(CONTENT_SETTINGS_TYPE_COOKIES);
205  }
206}
207
208void TabSpecificContentSettings::OnGeolocationPermissionSet(
209    const GURL& requesting_origin,
210    bool allowed) {
211  geolocation_settings_state_.OnGeolocationPermissionSet(requesting_origin,
212                                                         allowed);
213  if (delegate_)
214    delegate_->OnContentSettingsAccessed(!allowed);
215}
216
217TabSpecificContentSettings::TabSpecificContentSettings(
218    Delegate* delegate, Profile* profile)
219    : allowed_local_shared_objects_(profile),
220      blocked_local_shared_objects_(profile),
221      geolocation_settings_state_(profile),
222      load_plugins_link_enabled_(true),
223      delegate_(NULL) {
224  ClearBlockedContentSettingsExceptForCookies();
225  ClearCookieSpecificContentSettings();
226  delegate_ = delegate;
227}
228
229void TabSpecificContentSettings::ClearBlockedContentSettingsExceptForCookies() {
230  for (size_t i = 0; i < arraysize(content_blocked_); ++i) {
231    if (i == CONTENT_SETTINGS_TYPE_COOKIES)
232      continue;
233    blocked_resources_[i].reset();
234    content_blocked_[i] = false;
235    content_accessed_[i] = false;
236    content_blockage_indicated_to_user_[i] = false;
237  }
238  load_plugins_link_enabled_ = true;
239  if (delegate_)
240    delegate_->OnContentSettingsAccessed(false);
241}
242
243void TabSpecificContentSettings::ClearCookieSpecificContentSettings() {
244  blocked_local_shared_objects_.Reset();
245  allowed_local_shared_objects_.Reset();
246  content_blocked_[CONTENT_SETTINGS_TYPE_COOKIES] = false;
247  content_accessed_[CONTENT_SETTINGS_TYPE_COOKIES] = false;
248  content_blockage_indicated_to_user_[CONTENT_SETTINGS_TYPE_COOKIES] = false;
249  if (delegate_)
250    delegate_->OnContentSettingsAccessed(false);
251}
252
253void TabSpecificContentSettings::SetPopupsBlocked(bool blocked) {
254  content_blocked_[CONTENT_SETTINGS_TYPE_POPUPS] = blocked;
255  content_blockage_indicated_to_user_[CONTENT_SETTINGS_TYPE_POPUPS] = false;
256  if (delegate_)
257    delegate_->OnContentSettingsAccessed(blocked);
258}
259
260void TabSpecificContentSettings::GeolocationDidNavigate(
261      const NavigationController::LoadCommittedDetails& details) {
262  geolocation_settings_state_.DidNavigate(details);
263}
264
265void TabSpecificContentSettings::ClearGeolocationContentSettings() {
266  geolocation_settings_state_.ClearStateMap();
267}
268
269CookiesTreeModel* TabSpecificContentSettings::GetAllowedCookiesTreeModel() {
270  return allowed_local_shared_objects_.GetCookiesTreeModel();
271}
272
273CookiesTreeModel* TabSpecificContentSettings::GetBlockedCookiesTreeModel() {
274  return blocked_local_shared_objects_.GetCookiesTreeModel();
275}
276
277TabSpecificContentSettings::LocalSharedObjectsContainer::
278    LocalSharedObjectsContainer(Profile* profile)
279    : cookies_(new net::CookieMonster(NULL, NULL)),
280      appcaches_(new CannedBrowsingDataAppCacheHelper(profile)),
281      databases_(new CannedBrowsingDataDatabaseHelper(profile)),
282      indexed_dbs_(new CannedBrowsingDataIndexedDBHelper(profile)),
283      local_storages_(new CannedBrowsingDataLocalStorageHelper(profile)),
284      session_storages_(new CannedBrowsingDataLocalStorageHelper(profile)) {
285  cookies_->SetCookieableSchemes(
286      net::CookieMonster::kDefaultCookieableSchemes,
287      net::CookieMonster::kDefaultCookieableSchemesCount);
288  cookies_->SetKeepExpiredCookies();
289}
290
291TabSpecificContentSettings::LocalSharedObjectsContainer::
292    ~LocalSharedObjectsContainer() {
293}
294
295void TabSpecificContentSettings::LocalSharedObjectsContainer::Reset() {
296  cookies_ = new net::CookieMonster(NULL, NULL);
297  cookies_->SetCookieableSchemes(
298      net::CookieMonster::kDefaultCookieableSchemes,
299      net::CookieMonster::kDefaultCookieableSchemesCount);
300  cookies_->SetKeepExpiredCookies();
301  appcaches_->Reset();
302  databases_->Reset();
303  indexed_dbs_->Reset();
304  local_storages_->Reset();
305  session_storages_->Reset();
306}
307
308CookiesTreeModel*
309TabSpecificContentSettings::LocalSharedObjectsContainer::GetCookiesTreeModel() {
310  return new CookiesTreeModel(cookies_,
311                              databases_->Clone(),
312                              local_storages_->Clone(),
313                              session_storages_->Clone(),
314                              appcaches_->Clone(),
315                              indexed_dbs_->Clone(),
316                              true);
317}
318