cookies_view_handler.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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/ui/webui/options/cookies_view_handler.h"
6
7#include <string>
8
9#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/utf_string_conversions.h"
12#include "base/values.h"
13#include "chrome/common/extensions/extension.h"
14#include "chrome/common/extensions/extension_set.h"
15#include "chrome/browser/browsing_data/browsing_data_appcache_helper.h"
16#include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
17#include "chrome/browser/browsing_data/browsing_data_database_helper.h"
18#include "chrome/browser/browsing_data/browsing_data_file_system_helper.h"
19#include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h"
20#include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h"
21#include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h"
22#include "chrome/browser/browsing_data/browsing_data_quota_helper.h"
23#include "chrome/browser/browsing_data/browsing_data_server_bound_cert_helper.h"
24#include "chrome/browser/extensions/extension_service.h"
25#include "chrome/browser/extensions/extension_system.h"
26#include "chrome/browser/profiles/profile.h"
27#include "chrome/browser/ui/webui/cookies_tree_model_util.h"
28#include "content/public/browser/browser_context.h"
29#include "content/public/browser/render_process_host.h"
30#include "content/public/browser/site_instance.h"
31#include "content/public/browser/storage_partition.h"
32#include "content/public/browser/web_ui.h"
33#include "grit/generated_resources.h"
34#include "ui/base/l10n/l10n_util.h"
35
36namespace fileapi {
37class FileSystemContext;
38}
39
40namespace options {
41
42CookiesViewHandler::CookiesViewHandler()
43  : batch_update_(false),
44    app_context_(false),
45    model_util_(new CookiesTreeModelUtil) {
46}
47
48CookiesViewHandler::~CookiesViewHandler() {
49}
50
51void CookiesViewHandler::GetLocalizedValues(
52    DictionaryValue* localized_strings) {
53  DCHECK(localized_strings);
54
55  static OptionsStringResource resources[] = {
56    { "label_cookie_name", IDS_COOKIES_COOKIE_NAME_LABEL },
57    { "label_cookie_content", IDS_COOKIES_COOKIE_CONTENT_LABEL },
58    { "label_cookie_domain", IDS_COOKIES_COOKIE_DOMAIN_LABEL },
59    { "label_cookie_path", IDS_COOKIES_COOKIE_PATH_LABEL },
60    { "label_cookie_send_for", IDS_COOKIES_COOKIE_SENDFOR_LABEL },
61    { "label_cookie_accessible_to_script",
62      IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_LABEL },
63    { "label_cookie_created", IDS_COOKIES_COOKIE_CREATED_LABEL },
64    { "label_cookie_expires", IDS_COOKIES_COOKIE_EXPIRES_LABEL },
65    { "label_webdb_desc", IDS_COOKIES_WEB_DATABASE_DESCRIPTION_LABEL },
66    { "label_local_storage_size",
67      IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL },
68    { "label_local_storage_last_modified",
69      IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL },
70    { "label_local_storage_origin", IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL },
71    { "label_indexed_db_size", IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL },
72    { "label_indexed_db_last_modified",
73      IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL },
74    { "label_indexed_db_origin", IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL },
75    { "label_app_cache_manifest",
76      IDS_COOKIES_APPLICATION_CACHE_MANIFEST_LABEL },
77    { "label_cookie_last_accessed", IDS_COOKIES_LAST_ACCESSED_LABEL },
78    { "cookie_domain", IDS_COOKIES_DOMAIN_COLUMN_HEADER },
79    { "cookie_local_data", IDS_COOKIES_DATA_COLUMN_HEADER },
80    { "cookie_singular", IDS_COOKIES_SINGLE_COOKIE },
81    { "cookie_plural", IDS_COOKIES_PLURAL_COOKIES },
82    { "cookie_database_storage", IDS_COOKIES_DATABASE_STORAGE },
83    { "cookie_indexed_db", IDS_COOKIES_INDEXED_DB },
84    { "cookie_local_storage", IDS_COOKIES_LOCAL_STORAGE },
85    { "cookie_app_cache", IDS_COOKIES_APPLICATION_CACHE },
86    { "cookie_flash_lso", IDS_COOKIES_FLASH_LSO },
87    { "search_cookies", IDS_COOKIES_SEARCH_COOKIES },
88    { "remove_cookie", IDS_COOKIES_REMOVE_LABEL },
89    { "remove_all_cookie", IDS_COOKIES_REMOVE_ALL_LABEL },
90    { "cookie_file_system", IDS_COOKIES_FILE_SYSTEM },
91    { "label_file_system_origin", IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL },
92    { "label_file_system_temporary_usage",
93      IDS_COOKIES_FILE_SYSTEM_TEMPORARY_USAGE_LABEL },
94    { "label_file_system_persistent_usage",
95      IDS_COOKIES_FILE_SYSTEM_PERSISTENT_USAGE_LABEL },
96    { "cookie_server_bound_cert", IDS_COOKIES_SERVER_BOUND_CERT },
97    { "label_server_bound_cert_server_id",
98      IDS_COOKIES_SERVER_BOUND_CERT_ORIGIN_LABEL },
99    { "label_server_bound_cert_type",
100      IDS_COOKIES_SERVER_BOUND_CERT_TYPE_LABEL },
101    { "label_server_bound_cert_created",
102      IDS_COOKIES_SERVER_BOUND_CERT_CREATED_LABEL },
103    { "label_server_bound_cert_expires",
104      IDS_COOKIES_SERVER_BOUND_CERT_EXPIRES_LABEL },
105    { "label_protected_by_apps",
106      IDS_GEOLOCATION_SET_BY_HOVER },  // TODO(bauerb): Use a better string
107  };
108
109  RegisterStrings(localized_strings, resources, arraysize(resources));
110  RegisterTitle(localized_strings, "cookiesViewPage",
111                IDS_COOKIES_WEBSITE_PERMISSIONS_WINDOW_TITLE);
112  RegisterTitle(localized_strings, "appCookiesViewPage",
113                IDS_APP_COOKIES_WEBSITE_PERMISSIONS_WINDOW_TITLE);
114}
115
116void CookiesViewHandler::RegisterMessages() {
117  web_ui()->RegisterMessageCallback("updateCookieSearchResults",
118      base::Bind(&CookiesViewHandler::UpdateSearchResults,
119                 base::Unretained(this)));
120  web_ui()->RegisterMessageCallback("removeAllCookies",
121      base::Bind(&CookiesViewHandler::RemoveAll,
122                 base::Unretained(this)));
123  web_ui()->RegisterMessageCallback("removeCookie",
124      base::Bind(&CookiesViewHandler::Remove,
125                 base::Unretained(this)));
126  web_ui()->RegisterMessageCallback("loadCookie",
127      base::Bind(&CookiesViewHandler::LoadChildren,
128                 base::Unretained(this)));
129  web_ui()->RegisterMessageCallback("setViewContext",
130      base::Bind(&CookiesViewHandler::SetViewContext,
131                 base::Unretained(this)));
132  web_ui()->RegisterMessageCallback("reloadCookies",
133      base::Bind(&CookiesViewHandler::ReloadCookies,
134                 base::Unretained(this)));
135}
136
137void CookiesViewHandler::TreeNodesAdded(ui::TreeModel* model,
138                                        ui::TreeModelNode* parent,
139                                        int start,
140                                        int count) {
141  // Skip if there is a batch update in progress.
142  if (batch_update_)
143    return;
144
145  CookiesTreeModel* tree_model = static_cast<CookiesTreeModel*>(model);
146  CookieTreeNode* parent_node = tree_model->AsNode(parent);
147
148  ListValue* children = new ListValue;
149  model_util_->GetChildNodeList(parent_node, start, count,
150                                            children);
151
152  ListValue args;
153  args.Append(parent == tree_model->GetRoot() ?
154      Value::CreateNullValue() :
155      Value::CreateStringValue(
156          model_util_->GetTreeNodeId(parent_node)));
157  args.Append(Value::CreateIntegerValue(start));
158  args.Append(children);
159  web_ui()->CallJavascriptFunction(
160      GetCallback("onTreeItemAdded", tree_model), args);
161}
162
163void CookiesViewHandler::TreeNodesRemoved(ui::TreeModel* model,
164                                          ui::TreeModelNode* parent,
165                                          int start,
166                                          int count) {
167  // Skip if there is a batch update in progress.
168  if (batch_update_)
169    return;
170
171  CookiesTreeModel* tree_model = static_cast<CookiesTreeModel*>(model);
172
173  ListValue args;
174  args.Append(parent == tree_model->GetRoot() ?
175      Value::CreateNullValue() :
176      Value::CreateStringValue(model_util_->GetTreeNodeId(
177          tree_model->AsNode(parent))));
178  args.Append(Value::CreateIntegerValue(start));
179  args.Append(Value::CreateIntegerValue(count));
180  web_ui()->CallJavascriptFunction(
181      GetCallback("onTreeItemRemoved", tree_model), args);
182}
183
184void CookiesViewHandler::TreeModelBeginBatch(CookiesTreeModel* model) {
185  DCHECK(!batch_update_);  // There should be no nested batch begin.
186  batch_update_ = true;
187}
188
189void CookiesViewHandler::TreeModelEndBatch(CookiesTreeModel* model) {
190  DCHECK(batch_update_);
191  batch_update_ = false;
192
193  SendChildren(model->GetRoot());
194}
195
196void CookiesViewHandler::EnsureCookiesTreeModelCreated() {
197  if (!app_context_ && !cookies_tree_model_.get()) {
198    Profile* profile = Profile::FromWebUI(web_ui());
199    ContainerMap apps_map;
200    content::StoragePartition* storage_partition =
201        content::BrowserContext::GetDefaultStoragePartition(profile);
202    content::IndexedDBContext* indexed_db_context =
203        storage_partition->GetIndexedDBContext();
204    fileapi::FileSystemContext* file_system_context =
205        storage_partition->GetFileSystemContext();
206    apps_map[std::string()] = new LocalDataContainer(
207        "Site Data", std::string(),
208        new BrowsingDataCookieHelper(profile->GetRequestContext()),
209        new BrowsingDataDatabaseHelper(profile),
210        new BrowsingDataLocalStorageHelper(profile),
211        NULL,
212        new BrowsingDataAppCacheHelper(profile),
213        BrowsingDataIndexedDBHelper::Create(indexed_db_context),
214        BrowsingDataFileSystemHelper::Create(file_system_context),
215        BrowsingDataQuotaHelper::Create(profile),
216        BrowsingDataServerBoundCertHelper::Create(profile),
217        BrowsingDataFlashLSOHelper::Create(profile));
218    cookies_tree_model_.reset(
219        new CookiesTreeModel(apps_map,
220                             profile->GetExtensionSpecialStoragePolicy(),
221                             false));
222    cookies_tree_model_->AddCookiesTreeObserver(this);
223  }
224
225  if (app_context_ && !app_cookies_tree_model_.get()) {
226    Profile* profile = Profile::FromWebUI(web_ui());
227    ContainerMap apps_map;
228    const ExtensionService* service = profile->GetExtensionService();
229    if (!service)
230      return;
231
232    ExtensionProcessManager* process_manager =
233        extensions::ExtensionSystem::Get(profile)->process_manager();
234    if (!process_manager)
235      return;
236
237    const ExtensionSet* extensions = service->extensions();
238    for (ExtensionSet::const_iterator it = extensions->begin();
239         it != extensions->end(); ++it) {
240      if ((*it)->is_storage_isolated()) {
241        content::StoragePartition* storage_partition =
242            content::BrowserContext::GetStoragePartitionForSite(profile,
243                                                                (*it)->url());
244        net::URLRequestContextGetter* context_getter =
245            storage_partition->GetURLRequestContext();
246        // TODO(nasko): When new types of storage are isolated, add the
247        // appropriate browsing data helper objects to the constructor.
248        // For now, just cookies are isolated, so other parameters are NULL.
249        apps_map[(*it)->id()] = new LocalDataContainer(
250            (*it)->name(), (*it)->id(),
251            new BrowsingDataCookieHelper(context_getter),
252            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
253      }
254    }
255    app_cookies_tree_model_.reset(
256        new CookiesTreeModel(apps_map,
257                             profile->GetExtensionSpecialStoragePolicy(),
258                             false));
259    app_cookies_tree_model_->AddCookiesTreeObserver(this);
260  }
261}
262
263void CookiesViewHandler::UpdateSearchResults(const ListValue* args) {
264  string16 query;
265  if (!args->GetString(0, &query))
266    return;
267
268  EnsureCookiesTreeModelCreated();
269
270  GetTreeModel()->UpdateSearchResults(query);
271}
272
273void CookiesViewHandler::RemoveAll(const ListValue* args) {
274  EnsureCookiesTreeModelCreated();
275  GetTreeModel()->DeleteAllStoredObjects();
276}
277
278void CookiesViewHandler::Remove(const ListValue* args) {
279  std::string node_path;
280  if (!args->GetString(0, &node_path))
281    return;
282
283  EnsureCookiesTreeModelCreated();
284
285  const CookieTreeNode* node = model_util_->GetTreeNodeFromPath(
286      GetTreeModel()->GetRoot(), node_path);
287  if (node)
288    GetTreeModel()->DeleteCookieNode(const_cast<CookieTreeNode*>(node));
289}
290
291void CookiesViewHandler::LoadChildren(const ListValue* args) {
292  std::string node_path;
293  if (!args->GetString(0, &node_path))
294    return;
295
296  EnsureCookiesTreeModelCreated();
297
298  const CookieTreeNode* node = model_util_->GetTreeNodeFromPath(
299      GetTreeModel()->GetRoot(), node_path);
300  if (node)
301    SendChildren(node);
302}
303
304void CookiesViewHandler::SendChildren(const CookieTreeNode* parent) {
305  ListValue* children = new ListValue;
306  model_util_->GetChildNodeList(parent, 0, parent->child_count(),
307      children);
308
309  ListValue args;
310  args.Append(parent == GetTreeModel()->GetRoot() ?
311      Value::CreateNullValue() :
312      Value::CreateStringValue(model_util_->GetTreeNodeId(parent)));
313  args.Append(children);
314
315  web_ui()->CallJavascriptFunction(
316      GetCallback("loadChildren", GetTreeModel()), args);
317}
318
319void CookiesViewHandler::SetViewContext(const base::ListValue* args) {
320  bool app_context = false;
321  if (args->GetBoolean(0, &app_context))
322    app_context_ = app_context;
323}
324
325void CookiesViewHandler::ReloadCookies(const base::ListValue* args) {
326  cookies_tree_model_.reset();
327  app_cookies_tree_model_.reset();
328
329  EnsureCookiesTreeModelCreated();
330}
331
332CookiesTreeModel* CookiesViewHandler::GetTreeModel() {
333  CookiesTreeModel* model = app_context_ ?
334      app_cookies_tree_model_.get() : cookies_tree_model_.get();
335  DCHECK(model);
336  return model;
337}
338
339std::string CookiesViewHandler::GetCallback(
340     std::string method, CookiesTreeModel* model) {
341  std::string callback("CookiesView");
342
343  if (model == app_cookies_tree_model_)
344    callback.append("App");
345  return callback.append(".").append(method);
346}
347
348}  // namespace options
349