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/ui/webui/collected_cookies_ui_delegate.h"
6
7#include "base/message_loop.h"
8#include "base/string_util.h"
9#include "base/values.h"
10#include "chrome/browser/cookies_tree_model.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
13#include "chrome/browser/ui/webui/constrained_html_ui.h"
14#include "chrome/browser/ui/webui/cookies_tree_model_util.h"
15#include "chrome/common/jstemplate_builder.h"
16#include "chrome/common/url_constants.h"
17#include "content/browser/tab_contents/tab_contents.h"
18#include "content/common/notification_service.h"
19#include "grit/browser_resources.h"
20#include "grit/generated_resources.h"
21#include "ui/base/l10n/l10n_util.h"
22#include "ui/base/resource/resource_bundle.h"
23#include "ui/gfx/size.h"
24
25namespace {
26
27// TODO(xiyuan): Localize this.
28const int kDialogWidth = 480;
29const int kDialogHeight = 470;
30
31CookieTreeOriginNode* GetOriginNode(CookiesTreeModel* model,
32                                    const std::string& node_path) {
33  CookieTreeNode* node = cookies_tree_model_util::GetTreeNodeFromPath(
34      model->GetRoot(), node_path);
35
36  while (node && node->GetDetailedInfo().node_type !=
37                 CookieTreeNode::DetailedInfo::TYPE_ORIGIN) {
38    node = node->parent();
39  }
40
41  return static_cast<CookieTreeOriginNode*>(node);
42}
43
44std::string GetInfobarLabel(ContentSetting setting,
45                            const string16& domain_name) {
46  switch (setting) {
47    case CONTENT_SETTING_BLOCK:
48      return l10n_util::GetStringFUTF8(
49          IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED, domain_name);
50
51    case CONTENT_SETTING_ALLOW:
52      return l10n_util::GetStringFUTF8(
53          IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED, domain_name);
54
55    case CONTENT_SETTING_SESSION_ONLY:
56      return l10n_util::GetStringFUTF8(
57          IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED, domain_name);
58
59    default:
60      NOTREACHED() << "Unknown ContentSetting, " << setting;
61      return std::string();
62  }
63}
64
65class CollectedCookiesSource : public ChromeURLDataManager::DataSource {
66 public:
67  explicit CollectedCookiesSource(bool block_third_party_cookies)
68      : DataSource(chrome::kChromeUICollectedCookiesHost,
69                   MessageLoop::current()),
70        block_third_party_cookies_(block_third_party_cookies) {
71  }
72
73  virtual void StartDataRequest(const std::string& path,
74                                bool is_incognito,
75                                int request_id);
76
77  virtual std::string GetMimeType(const std::string& path) const {
78    return "text/html";
79  }
80
81 private:
82  virtual ~CollectedCookiesSource() {}
83
84  bool block_third_party_cookies_;
85
86  DISALLOW_COPY_AND_ASSIGN(CollectedCookiesSource);
87};
88
89void CollectedCookiesSource::StartDataRequest(const std::string& path,
90                                              bool is_incognito,
91                                              int request_id) {
92  DictionaryValue localized_strings;
93  localized_strings.SetString("title",
94      l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE));
95
96  localized_strings.SetString("title",
97      l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE));
98  localized_strings.SetString("allowedCookies",
99      l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL));
100  localized_strings.SetString("blockButton",
101      l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON));
102
103  localized_strings.SetString("blockedCookies",
104      l10n_util::GetStringUTF16(block_third_party_cookies_ ?
105          IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED :
106          IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL));
107
108  localized_strings.SetString("allowButton",
109      l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_ALLOW_BUTTON));
110  localized_strings.SetString("allowThisSessionButton",
111      l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON));
112  localized_strings.SetString("closeButton",
113      l10n_util::GetStringUTF16(IDS_CLOSE));
114
115  SetFontAndTextDirection(&localized_strings);
116
117  static const base::StringPiece html(
118      ResourceBundle::GetSharedInstance().GetRawDataResource(
119          IDR_COLLECTED_COOKIES_HTML));
120  const std::string response = jstemplate_builder::GetI18nTemplateHtml(
121      html, &localized_strings);
122
123  scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
124  html_bytes->data.resize(response.size());
125  std::copy(response.begin(), response.end(), html_bytes->data.begin());
126
127  SendResponse(request_id, html_bytes);
128}
129
130}  // namespace
131
132// static
133void CollectedCookiesUIDelegate::Show(TabContents* tab_contents) {
134  CollectedCookiesUIDelegate* delegate =
135      new CollectedCookiesUIDelegate(tab_contents);
136  ConstrainedHtmlUI::CreateConstrainedHtmlDialog(tab_contents->profile(),
137                                                 delegate,
138                                                 tab_contents);
139}
140
141CollectedCookiesUIDelegate::CollectedCookiesUIDelegate(
142    TabContents* tab_contents)
143    : tab_contents_(tab_contents),
144      closed_(false) {
145  TabSpecificContentSettings* content_settings =
146      tab_contents->GetTabSpecificContentSettings();
147  HostContentSettingsMap* host_content_settings_map =
148      tab_contents_->profile()->GetHostContentSettingsMap();
149
150  registrar_.Add(this, NotificationType::COLLECTED_COOKIES_SHOWN,
151                 Source<TabSpecificContentSettings>(content_settings));
152
153  allowed_cookies_tree_model_.reset(
154      content_settings->GetAllowedCookiesTreeModel());
155  blocked_cookies_tree_model_.reset(
156      content_settings->GetBlockedCookiesTreeModel());
157
158  CollectedCookiesSource* source = new CollectedCookiesSource(
159      host_content_settings_map->BlockThirdPartyCookies());
160  tab_contents->profile()->GetChromeURLDataManager()->AddDataSource(source);
161}
162
163CollectedCookiesUIDelegate::~CollectedCookiesUIDelegate() {
164}
165
166bool CollectedCookiesUIDelegate::IsDialogModal() const {
167  return false;
168}
169
170std::wstring CollectedCookiesUIDelegate::GetDialogTitle() const {
171  return std::wstring();
172}
173
174GURL CollectedCookiesUIDelegate::GetDialogContentURL() const {
175  return GURL(chrome::kChromeUICollectedCookiesURL);
176}
177
178void CollectedCookiesUIDelegate::GetWebUIMessageHandlers(
179    std::vector<WebUIMessageHandler*>* handlers) const {
180  const WebUIMessageHandler* handler = this;
181  handlers->push_back(const_cast<WebUIMessageHandler*>(handler));
182}
183
184void CollectedCookiesUIDelegate::GetDialogSize(gfx::Size* size) const {
185  size->set_width(kDialogWidth);
186  size->set_height(kDialogHeight);
187}
188
189std::string CollectedCookiesUIDelegate::GetDialogArgs() const {
190  return std::string();
191}
192
193void CollectedCookiesUIDelegate::OnDialogClosed(
194    const std::string& json_retval) {
195  closed_ = true;
196}
197
198bool CollectedCookiesUIDelegate::ShouldShowDialogTitle() const {
199  return true;
200}
201
202void CollectedCookiesUIDelegate::RegisterMessages() {
203  web_ui_->RegisterMessageCallback("BindCookiesTreeModel",
204      NewCallback(this, &CollectedCookiesUIDelegate::BindCookiesTreeModel));
205  web_ui_->RegisterMessageCallback("Block",
206      NewCallback(this, &CollectedCookiesUIDelegate::Block));
207  web_ui_->RegisterMessageCallback("Allow",
208      NewCallback(this, &CollectedCookiesUIDelegate::Allow));
209  web_ui_->RegisterMessageCallback("AllowThisSession",
210      NewCallback(this, &CollectedCookiesUIDelegate::AllowThisSession));
211
212  allowed_cookies_adapter_.Init(web_ui_);
213  blocked_cookies_adapter_.Init(web_ui_);
214}
215
216void CollectedCookiesUIDelegate::CloseDialog() {
217  if (!closed_ && web_ui_)
218    web_ui_->CallJavascriptFunction("closeDialog");
219}
220
221void CollectedCookiesUIDelegate::SetInfobarLabel(const std::string& text) {
222  StringValue string(text);
223  web_ui_->CallJavascriptFunction("setInfobarLabel", string);
224}
225
226void CollectedCookiesUIDelegate::AddContentException(
227    CookieTreeOriginNode* origin_node, ContentSetting setting) {
228  if (origin_node->CanCreateContentException()) {
229    origin_node->CreateContentException(
230        tab_contents_->profile()->GetHostContentSettingsMap(), setting);
231
232    SetInfobarLabel(GetInfobarLabel(setting, origin_node->GetTitle()));
233  }
234}
235
236void CollectedCookiesUIDelegate::Observe(NotificationType type,
237                                         const NotificationSource& source,
238                                         const NotificationDetails& details) {
239  DCHECK_EQ(type.value, NotificationType::COLLECTED_COOKIES_SHOWN);
240  DCHECK_EQ(Source<TabSpecificContentSettings>(source).ptr(),
241            tab_contents_->GetTabSpecificContentSettings());
242  CloseDialog();
243}
244
245void CollectedCookiesUIDelegate::BindCookiesTreeModel(const ListValue* args) {
246  allowed_cookies_adapter_.Bind("allowed-cookies",
247      allowed_cookies_tree_model_.get());
248  blocked_cookies_adapter_.Bind("blocked-cookies",
249      blocked_cookies_tree_model_.get());
250}
251
252void CollectedCookiesUIDelegate::Block(const ListValue* args) {
253  std::string node_path;
254  if (!args->GetString(0, &node_path))
255    return;
256
257  CookieTreeOriginNode* origin_node = GetOriginNode(
258      allowed_cookies_tree_model_.get(), node_path);
259  if (!origin_node)
260    return;
261
262  AddContentException(origin_node, CONTENT_SETTING_BLOCK);
263}
264
265void CollectedCookiesUIDelegate::Allow(const ListValue* args) {
266  std::string node_path;
267  if (!args->GetString(0, &node_path))
268    return;
269
270  CookieTreeOriginNode* origin_node = GetOriginNode(
271      blocked_cookies_tree_model_.get(), node_path);
272  if (!origin_node)
273    return;
274
275  AddContentException(origin_node, CONTENT_SETTING_ALLOW);
276}
277
278void CollectedCookiesUIDelegate::AllowThisSession(const ListValue* args) {
279  std::string node_path;
280  if (!args->GetString(0, &node_path))
281    return;
282
283  CookieTreeOriginNode* origin_node = GetOriginNode(
284      blocked_cookies_tree_model_.get(), node_path);
285  if (!origin_node)
286    return;
287
288  AddContentException(origin_node, CONTENT_SETTING_SESSION_ONLY);
289}
290