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/views/cookie_info_view.h"
6
7#include <algorithm>
8
9#include "base/i18n/time_formatting.h"
10#include "base/message_loop.h"
11#include "base/string16.h"
12#include "base/string_util.h"
13#include "base/utf_string_conversions.h"
14#include "chrome/browser/cookies_tree_model.h"
15#include "grit/generated_resources.h"
16#include "grit/locale_settings.h"
17#include "ui/base/l10n/l10n_util.h"
18#include "ui/gfx/canvas.h"
19#include "ui/gfx/color_utils.h"
20#include "views/border.h"
21#include "views/controls/label.h"
22#include "views/controls/button/native_button.h"
23#include "views/controls/tree/tree_view.h"
24#include "views/controls/textfield/textfield.h"
25#include "views/layout/grid_layout.h"
26#include "views/layout/layout_constants.h"
27
28static const int kCookieInfoViewBorderSize = 1;
29static const int kCookieInfoViewInsetSize = 3;
30
31///////////////////////////////////////////////////////////////////////////////
32// CookieInfoView, public:
33
34CookieInfoView::CookieInfoView(bool editable_expiration_date)
35    : name_label_(NULL),
36      name_value_field_(NULL),
37      content_label_(NULL),
38      content_value_field_(NULL),
39      domain_label_(NULL),
40      domain_value_field_(NULL),
41      path_label_(NULL),
42      path_value_field_(NULL),
43      send_for_label_(NULL),
44      send_for_value_field_(NULL),
45      created_label_(NULL),
46      created_value_field_(NULL),
47      expires_label_(NULL),
48      expires_value_field_(NULL),
49      expires_value_combobox_(NULL),
50      expire_view_(NULL),
51      editable_expiration_date_(editable_expiration_date),
52      delegate_(NULL) {
53}
54
55CookieInfoView::~CookieInfoView() {
56}
57
58void CookieInfoView::SetCookie(
59    const std::string& domain,
60    const net::CookieMonster::CanonicalCookie& cookie) {
61  name_value_field_->SetText(UTF8ToWide(cookie.Name()));
62  content_value_field_->SetText(UTF8ToWide(cookie.Value()));
63  domain_value_field_->SetText(UTF8ToWide(domain));
64  path_value_field_->SetText(UTF8ToWide(cookie.Path()));
65  created_value_field_->SetText(
66      base::TimeFormatFriendlyDateAndTime(cookie.CreationDate()));
67
68  std::wstring expire_text = cookie.DoesExpire() ?
69      base::TimeFormatFriendlyDateAndTime(cookie.ExpiryDate()) :
70      UTF16ToWide(
71          l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_EXPIRES_SESSION));
72
73  if (editable_expiration_date_) {
74    expire_combo_values_.clear();
75    if (cookie.DoesExpire())
76      expire_combo_values_.push_back(expire_text);
77    expire_combo_values_.push_back(UTF16ToWide(
78        l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_EXPIRES_SESSION)));
79    expires_value_combobox_->ModelChanged();
80    expires_value_combobox_->SetSelectedItem(0);
81    expires_value_combobox_->SetEnabled(true);
82    expires_value_combobox_->set_listener(this);
83  } else {
84    expires_value_field_->SetText(expire_text);
85  }
86
87  send_for_value_field_->SetText(cookie.IsSecure() ?
88      UTF16ToWide(
89          l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_SENDFOR_SECURE)) :
90      UTF16ToWide(
91          l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_SENDFOR_ANY)));
92  EnableCookieDisplay(true);
93  Layout();
94}
95
96void CookieInfoView::SetCookieString(const GURL& url,
97                                     const std::string& cookie_line) {
98  net::CookieMonster::ParsedCookie pc(cookie_line);
99  net::CookieMonster::CanonicalCookie cookie(url, pc);
100  SetCookie(pc.HasDomain() ? pc.Domain() : url.host(), cookie);
101}
102
103
104void CookieInfoView::ClearCookieDisplay() {
105  std::wstring no_cookie_string =
106      UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_NONESELECTED));
107  name_value_field_->SetText(no_cookie_string);
108  content_value_field_->SetText(no_cookie_string);
109  domain_value_field_->SetText(no_cookie_string);
110  path_value_field_->SetText(no_cookie_string);
111  send_for_value_field_->SetText(no_cookie_string);
112  created_value_field_->SetText(no_cookie_string);
113  if (expires_value_field_)
114    expires_value_field_->SetText(no_cookie_string);
115  EnableCookieDisplay(false);
116}
117
118void CookieInfoView::EnableCookieDisplay(bool enabled) {
119  name_value_field_->SetEnabled(enabled);
120  content_value_field_->SetEnabled(enabled);
121  domain_value_field_->SetEnabled(enabled);
122  path_value_field_->SetEnabled(enabled);
123  send_for_value_field_->SetEnabled(enabled);
124  created_value_field_->SetEnabled(enabled);
125  if (expires_value_field_)
126    expires_value_field_->SetEnabled(enabled);
127}
128
129///////////////////////////////////////////////////////////////////////////////
130// CookieInfoView, views::View overrides.
131
132void CookieInfoView::ViewHierarchyChanged(bool is_add,
133                                          views::View* parent,
134                                          views::View* child) {
135  if (is_add && child == this)
136    Init();
137}
138
139///////////////////////////////////////////////////////////////////////////////
140// CookieInfoView, views::Combobox::Listener overrides.
141
142void CookieInfoView::ItemChanged(views::Combobox* combo_box,
143                                 int prev_index,
144                                 int new_index) {
145  DCHECK(combo_box == expires_value_combobox_);
146  if (delegate_)
147    delegate_->ModifyExpireDate(new_index != 0);
148}
149
150///////////////////////////////////////////////////////////////////////////////
151// CookieInfoView, ComboboxModel overrides.
152int CookieInfoView::GetItemCount() {
153  return static_cast<int>(expire_combo_values_.size());
154}
155
156string16 CookieInfoView::GetItemAt(int index) {
157  return WideToUTF16Hack(expire_combo_values_[index]);
158}
159
160void CookieInfoView::AddLabelRow(int layout_id, views::GridLayout* layout,
161                                 views::View* label, views::View* value) {
162  layout->StartRow(0, layout_id);
163  layout->AddView(label);
164  layout->AddView(value, 2, 1, views::GridLayout::FILL,
165                  views::GridLayout::CENTER);
166  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
167}
168
169void CookieInfoView::AddControlRow(int layout_id, views::GridLayout* layout,
170                                 views::View* label, views::View* control) {
171  layout->StartRow(0, layout_id);
172  layout->AddView(label);
173  layout->AddView(control, 1, 1);
174  layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
175}
176
177///////////////////////////////////////////////////////////////////////////////
178// CookieInfoView, private:
179
180void CookieInfoView::Init() {
181  // Ensure we don't run this more than once and leak memory.
182  DCHECK(!name_label_);
183
184  SkColor border_color = color_utils::GetSysSkColor(COLOR_3DSHADOW);
185  views::Border* border = views::Border::CreateSolidBorder(
186      kCookieInfoViewBorderSize, border_color);
187  set_border(border);
188
189  name_label_ = new views::Label(
190      UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_NAME_LABEL)));
191  name_value_field_ = new views::Textfield;
192  content_label_ = new views::Label(
193      UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_CONTENT_LABEL)));
194  content_value_field_ = new views::Textfield;
195  domain_label_ = new views::Label(
196      UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_DOMAIN_LABEL)));
197  domain_value_field_ = new views::Textfield;
198  path_label_ = new views::Label(
199      UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_PATH_LABEL)));
200  path_value_field_ = new views::Textfield;
201  send_for_label_ = new views::Label(
202      UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_SENDFOR_LABEL)));
203  send_for_value_field_ = new views::Textfield;
204  created_label_ = new views::Label(
205      UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_CREATED_LABEL)));
206  created_value_field_ = new views::Textfield;
207  expires_label_ = new views::Label(
208      UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_EXPIRES_LABEL)));
209  if (editable_expiration_date_)
210    expires_value_combobox_ = new views::Combobox(this);
211  else
212    expires_value_field_ = new views::Textfield;
213
214  using views::GridLayout;
215  using views::ColumnSet;
216
217  GridLayout* layout = new GridLayout(this);
218  layout->SetInsets(kCookieInfoViewInsetSize,
219                    kCookieInfoViewInsetSize,
220                    kCookieInfoViewInsetSize,
221                    kCookieInfoViewInsetSize);
222  SetLayoutManager(layout);
223
224  int three_column_layout_id = 0;
225  ColumnSet* column_set = layout->AddColumnSet(three_column_layout_id);
226  column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
227                        GridLayout::USE_PREF, 0, 0);
228  column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
229  column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
230                        GridLayout::USE_PREF, 0, 0);
231  column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
232                        GridLayout::USE_PREF, 0, 0);
233
234  AddLabelRow(three_column_layout_id, layout, name_label_, name_value_field_);
235  AddLabelRow(three_column_layout_id, layout, content_label_,
236              content_value_field_);
237  AddLabelRow(three_column_layout_id, layout, domain_label_,
238              domain_value_field_);
239  AddLabelRow(three_column_layout_id, layout, path_label_, path_value_field_);
240  AddLabelRow(three_column_layout_id, layout, send_for_label_,
241              send_for_value_field_);
242  AddLabelRow(three_column_layout_id, layout, created_label_,
243              created_value_field_);
244
245  if (editable_expiration_date_) {
246    AddControlRow(three_column_layout_id, layout, expires_label_,
247                  expires_value_combobox_);
248  } else {
249    AddLabelRow(three_column_layout_id, layout, expires_label_,
250                expires_value_field_);
251  }
252
253  // Color these borderless text areas the same as the containing dialog.
254  SkColor text_area_background = color_utils::GetSysSkColor(COLOR_3DFACE);
255  // Now that the Textfields are in the view hierarchy, we can initialize them.
256  name_value_field_->SetReadOnly(true);
257  name_value_field_->RemoveBorder();
258  name_value_field_->SetBackgroundColor(text_area_background);
259  content_value_field_->SetReadOnly(true);
260  content_value_field_->RemoveBorder();
261  content_value_field_->SetBackgroundColor(text_area_background);
262  domain_value_field_->SetReadOnly(true);
263  domain_value_field_->RemoveBorder();
264  domain_value_field_->SetBackgroundColor(text_area_background);
265  path_value_field_->SetReadOnly(true);
266  path_value_field_->RemoveBorder();
267  path_value_field_->SetBackgroundColor(text_area_background);
268  send_for_value_field_->SetReadOnly(true);
269  send_for_value_field_->RemoveBorder();
270  send_for_value_field_->SetBackgroundColor(text_area_background);
271  created_value_field_->SetReadOnly(true);
272  created_value_field_->RemoveBorder();
273  created_value_field_->SetBackgroundColor(text_area_background);
274  if (expires_value_field_) {
275    expires_value_field_->SetReadOnly(true);
276    expires_value_field_->RemoveBorder();
277    expires_value_field_->SetBackgroundColor(text_area_background);
278  }
279}
280