| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/views/options/cookies_view.h" | 5 #include "chrome/browser/cookies_table_model.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "app/gfx/canvas.h" | |
| 10 #include "app/gfx/color_utils.h" | |
| 11 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 8 #include "app/table_model_observer.h" |
| 12 #include "app/resource_bundle.h" | 9 #include "app/resource_bundle.h" |
| 13 #include "app/table_model.h" | |
| 14 #include "base/message_loop.h" | |
| 15 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 16 #include "base/time_format.h" | |
| 17 #include "chrome/browser/profile.h" | 11 #include "chrome/browser/profile.h" |
| 18 #include "grit/generated_resources.h" | 12 #include "grit/generated_resources.h" |
| 19 #include "grit/locale_settings.h" | |
| 20 #include "grit/theme_resources.h" | 13 #include "grit/theme_resources.h" |
| 21 #include "net/base/cookie_monster.h" | |
| 22 #include "net/url_request/url_request_context.h" | 14 #include "net/url_request/url_request_context.h" |
| 23 #include "views/border.h" | 15 #include "third_party/skia/include/core/SkBitmap.h" |
| 24 #include "views/grid_layout.h" | |
| 25 #include "views/controls/label.h" | |
| 26 #include "views/controls/button/native_button.h" | |
| 27 #include "views/controls/table/table_view.h" | |
| 28 #include "views/controls/textfield/textfield.h" | |
| 29 #include "views/standard_layout.h" | |
| 30 | |
| 31 // static | |
| 32 views::Window* CookiesView::instance_ = NULL; | |
| 33 static const int kCookieInfoViewBorderSize = 1; | |
| 34 static const int kCookieInfoViewInsetSize = 3; | |
| 35 static const int kSearchFilterDelayMs = 500; | |
| 36 | |
| 37 /////////////////////////////////////////////////////////////////////////////// | |
| 38 // CookiesTableModel | |
| 39 | |
| 40 class CookiesTableModel : public TableModel { | |
| 41 public: | |
| 42 explicit CookiesTableModel(Profile* profile); | |
| 43 virtual ~CookiesTableModel() {} | |
| 44 | |
| 45 // Returns information about the Cookie at the specified index. | |
| 46 std::string GetDomainAt(int index); | |
| 47 net::CookieMonster::CanonicalCookie& GetCookieAt(int index); | |
| 48 | |
| 49 // Remove the specified cookies from the Cookie Monster and update the view. | |
| 50 void RemoveCookies(int start_index, int remove_count); | |
| 51 void RemoveAllShownCookies(); | |
| 52 | |
| 53 // TableModel methods. | |
| 54 virtual int RowCount(); | |
| 55 virtual std::wstring GetText(int row, int column_id); | |
| 56 virtual SkBitmap GetIcon(int row); | |
| 57 virtual int CompareValues(int row1, int row2, int column_id); | |
| 58 virtual void SetObserver(TableModelObserver* observer); | |
| 59 | |
| 60 // Filter the cookies to only display matched results. | |
| 61 void UpdateSearchResults(const std::wstring& filter); | |
| 62 | |
| 63 private: | |
| 64 void LoadCookies(); | |
| 65 void DoFilter(); | |
| 66 | |
| 67 std::wstring filter_; | |
| 68 | |
| 69 // The profile from which this model sources cookies. | |
| 70 Profile* profile_; | |
| 71 | |
| 72 typedef net::CookieMonster::CookieList CookieList; | |
| 73 typedef std::vector<net::CookieMonster::CookieListPair*> CookiePtrList; | |
| 74 CookieList all_cookies_; | |
| 75 CookiePtrList shown_cookies_; | |
| 76 | |
| 77 TableModelObserver* observer_; | |
| 78 | |
| 79 DISALLOW_COPY_AND_ASSIGN(CookiesTableModel); | |
| 80 }; | |
| 81 | 16 |
| 82 /////////////////////////////////////////////////////////////////////////////// | 17 /////////////////////////////////////////////////////////////////////////////// |
| 83 // CookiesTableModel, public: | 18 // CookiesTableModel, public: |
| 84 | 19 |
| 85 CookiesTableModel::CookiesTableModel(Profile* profile) | 20 CookiesTableModel::CookiesTableModel(Profile* profile) |
| 86 : profile_(profile) { | 21 : profile_(profile) { |
| 87 LoadCookies(); | 22 LoadCookies(); |
| 88 } | 23 } |
| 89 | 24 |
| 90 std::string CookiesTableModel::GetDomainAt(int index) { | 25 std::string CookiesTableModel::GetDomainAt(int index) { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 shown_cookies_.push_back(&*iter); | 176 shown_cookies_.push_back(&*iter); |
| 242 } | 177 } |
| 243 } | 178 } |
| 244 } | 179 } |
| 245 | 180 |
| 246 void CookiesTableModel::UpdateSearchResults(const std::wstring& filter) { | 181 void CookiesTableModel::UpdateSearchResults(const std::wstring& filter) { |
| 247 filter_ = filter; | 182 filter_ = filter; |
| 248 DoFilter(); | 183 DoFilter(); |
| 249 observer_->OnModelChanged(); | 184 observer_->OnModelChanged(); |
| 250 } | 185 } |
| 251 | |
| 252 /////////////////////////////////////////////////////////////////////////////// | |
| 253 // CookiesTableView | |
| 254 // Overridden to handle Delete key presses | |
| 255 | |
| 256 class CookiesTableView : public views::TableView { | |
| 257 public: | |
| 258 CookiesTableView(CookiesTableModel* cookies_model, | |
| 259 std::vector<TableColumn> columns); | |
| 260 virtual ~CookiesTableView() {} | |
| 261 | |
| 262 // Removes the cookies associated with the selected rows in the TableView. | |
| 263 void RemoveSelectedCookies(); | |
| 264 | |
| 265 private: | |
| 266 // Our model, as a CookiesTableModel. | |
| 267 CookiesTableModel* cookies_model_; | |
| 268 | |
| 269 DISALLOW_COPY_AND_ASSIGN(CookiesTableView); | |
| 270 }; | |
| 271 | |
| 272 CookiesTableView::CookiesTableView( | |
| 273 CookiesTableModel* cookies_model, | |
| 274 std::vector<TableColumn> columns) | |
| 275 : views::TableView(cookies_model, columns, views::ICON_AND_TEXT, false, | |
| 276 true, true), | |
| 277 cookies_model_(cookies_model) { | |
| 278 } | |
| 279 | |
| 280 void CookiesTableView::RemoveSelectedCookies() { | |
| 281 // It's possible that we don't have anything selected. | |
| 282 if (SelectedRowCount() <= 0) | |
| 283 return; | |
| 284 | |
| 285 if (SelectedRowCount() == cookies_model_->RowCount()) { | |
| 286 cookies_model_->RemoveAllShownCookies(); | |
| 287 return; | |
| 288 } | |
| 289 | |
| 290 // Remove the selected cookies. This iterates over the rows backwards, which | |
| 291 // is required when calling RemoveCookies, see bug 2994. | |
| 292 int last_selected_view_row = -1; | |
| 293 int remove_count = 0; | |
| 294 for (views::TableView::iterator i = SelectionBegin(); | |
| 295 i != SelectionEnd(); ++i) { | |
| 296 int selected_model_row = *i; | |
| 297 ++remove_count; | |
| 298 if (last_selected_view_row == -1) { | |
| 299 // Store the view row since the view to model mapping changes when | |
| 300 // we delete. | |
| 301 last_selected_view_row = model_to_view(selected_model_row); | |
| 302 } | |
| 303 cookies_model_->RemoveCookies(selected_model_row, 1); | |
| 304 } | |
| 305 | |
| 306 // Select the next row after the last row deleted (unless removing last row). | |
| 307 DCHECK(RowCount() > 0 && last_selected_view_row != -1); | |
| 308 Select(view_to_model(std::min(RowCount() - 1, | |
| 309 last_selected_view_row - remove_count + 1))); | |
| 310 } | |
| 311 | |
| 312 /////////////////////////////////////////////////////////////////////////////// | |
| 313 // CookieInfoView | |
| 314 // | |
| 315 // Responsible for displaying a tabular grid of Cookie information. | |
| 316 class CookieInfoView : public views::View { | |
| 317 public: | |
| 318 CookieInfoView(); | |
| 319 virtual ~CookieInfoView(); | |
| 320 | |
| 321 // Update the display from the specified CookieNode. | |
| 322 void SetCookie(const std::string& domain, | |
| 323 const net::CookieMonster::CanonicalCookie& cookie_node); | |
| 324 | |
| 325 // Clears the cookie display to indicate that no or multiple cookies are | |
| 326 // selected. | |
| 327 void ClearCookieDisplay(); | |
| 328 | |
| 329 // Enables or disables the cookie proerty text fields. | |
| 330 void EnableCookieDisplay(bool enabled); | |
| 331 | |
| 332 protected: | |
| 333 // views::View overrides: | |
| 334 virtual void ViewHierarchyChanged(bool is_add, | |
| 335 views::View* parent, | |
| 336 views::View* child); | |
| 337 | |
| 338 private: | |
| 339 // Set up the view layout | |
| 340 void Init(); | |
| 341 | |
| 342 // Individual property labels | |
| 343 views::Label* name_label_; | |
| 344 views::Textfield* name_value_field_; | |
| 345 views::Label* content_label_; | |
| 346 views::Textfield* content_value_field_; | |
| 347 views::Label* domain_label_; | |
| 348 views::Textfield* domain_value_field_; | |
| 349 views::Label* path_label_; | |
| 350 views::Textfield* path_value_field_; | |
| 351 views::Label* send_for_label_; | |
| 352 views::Textfield* send_for_value_field_; | |
| 353 views::Label* created_label_; | |
| 354 views::Textfield* created_value_field_; | |
| 355 views::Label* expires_label_; | |
| 356 views::Textfield* expires_value_field_; | |
| 357 | |
| 358 DISALLOW_COPY_AND_ASSIGN(CookieInfoView); | |
| 359 }; | |
| 360 | |
| 361 /////////////////////////////////////////////////////////////////////////////// | |
| 362 // CookieInfoView, public: | |
| 363 | |
| 364 CookieInfoView::CookieInfoView() | |
| 365 : name_label_(NULL), | |
| 366 name_value_field_(NULL), | |
| 367 content_label_(NULL), | |
| 368 content_value_field_(NULL), | |
| 369 domain_label_(NULL), | |
| 370 domain_value_field_(NULL), | |
| 371 path_label_(NULL), | |
| 372 path_value_field_(NULL), | |
| 373 send_for_label_(NULL), | |
| 374 send_for_value_field_(NULL), | |
| 375 created_label_(NULL), | |
| 376 created_value_field_(NULL), | |
| 377 expires_label_(NULL), | |
| 378 expires_value_field_(NULL) { | |
| 379 } | |
| 380 | |
| 381 CookieInfoView::~CookieInfoView() { | |
| 382 } | |
| 383 | |
| 384 void CookieInfoView::SetCookie( | |
| 385 const std::string& domain, | |
| 386 const net::CookieMonster::CanonicalCookie& cookie) { | |
| 387 name_value_field_->SetText(UTF8ToWide(cookie.Name())); | |
| 388 content_value_field_->SetText(UTF8ToWide(cookie.Value())); | |
| 389 domain_value_field_->SetText(UTF8ToWide(domain)); | |
| 390 path_value_field_->SetText(UTF8ToWide(cookie.Path())); | |
| 391 created_value_field_->SetText( | |
| 392 base::TimeFormatFriendlyDateAndTime(cookie.CreationDate())); | |
| 393 | |
| 394 if (cookie.DoesExpire()) { | |
| 395 expires_value_field_->SetText( | |
| 396 base::TimeFormatFriendlyDateAndTime(cookie.ExpiryDate())); | |
| 397 } else { | |
| 398 // TODO(deanm) need a string that the average user can understand | |
| 399 // "When you quit or restart your browser" ? | |
| 400 expires_value_field_->SetText( | |
| 401 l10n_util::GetString(IDS_COOKIES_COOKIE_EXPIRES_SESSION)); | |
| 402 } | |
| 403 | |
| 404 std::wstring sendfor_text; | |
| 405 if (cookie.IsSecure()) { | |
| 406 sendfor_text = l10n_util::GetString(IDS_COOKIES_COOKIE_SENDFOR_SECURE); | |
| 407 } else { | |
| 408 sendfor_text = l10n_util::GetString(IDS_COOKIES_COOKIE_SENDFOR_ANY); | |
| 409 } | |
| 410 send_for_value_field_->SetText(sendfor_text); | |
| 411 EnableCookieDisplay(true); | |
| 412 } | |
| 413 | |
| 414 void CookieInfoView::EnableCookieDisplay(bool enabled) { | |
| 415 name_value_field_->SetEnabled(enabled); | |
| 416 content_value_field_->SetEnabled(enabled); | |
| 417 domain_value_field_->SetEnabled(enabled); | |
| 418 path_value_field_->SetEnabled(enabled); | |
| 419 send_for_value_field_->SetEnabled(enabled); | |
| 420 created_value_field_->SetEnabled(enabled); | |
| 421 expires_value_field_->SetEnabled(enabled); | |
| 422 } | |
| 423 | |
| 424 void CookieInfoView::ClearCookieDisplay() { | |
| 425 std::wstring no_cookie_string = | |
| 426 l10n_util::GetString(IDS_COOKIES_COOKIE_NONESELECTED); | |
| 427 name_value_field_->SetText(no_cookie_string); | |
| 428 content_value_field_->SetText(no_cookie_string); | |
| 429 domain_value_field_->SetText(no_cookie_string); | |
| 430 path_value_field_->SetText(no_cookie_string); | |
| 431 send_for_value_field_->SetText(no_cookie_string); | |
| 432 created_value_field_->SetText(no_cookie_string); | |
| 433 expires_value_field_->SetText(no_cookie_string); | |
| 434 EnableCookieDisplay(false); | |
| 435 } | |
| 436 | |
| 437 /////////////////////////////////////////////////////////////////////////////// | |
| 438 // CookieInfoView, views::View overrides: | |
| 439 | |
| 440 void CookieInfoView::ViewHierarchyChanged(bool is_add, | |
| 441 views::View* parent, | |
| 442 views::View* child) { | |
| 443 if (is_add && child == this) | |
| 444 Init(); | |
| 445 } | |
| 446 | |
| 447 /////////////////////////////////////////////////////////////////////////////// | |
| 448 // CookieInfoView, private: | |
| 449 | |
| 450 void CookieInfoView::Init() { | |
| 451 SkColor border_color = color_utils::GetSysSkColor(COLOR_3DSHADOW); | |
| 452 views::Border* border = views::Border::CreateSolidBorder( | |
| 453 kCookieInfoViewBorderSize, border_color); | |
| 454 set_border(border); | |
| 455 | |
| 456 name_label_ = new views::Label( | |
| 457 l10n_util::GetString(IDS_COOKIES_COOKIE_NAME_LABEL)); | |
| 458 name_value_field_ = new views::Textfield; | |
| 459 content_label_ = new views::Label( | |
| 460 l10n_util::GetString(IDS_COOKIES_COOKIE_CONTENT_LABEL)); | |
| 461 content_value_field_ = new views::Textfield; | |
| 462 domain_label_ = new views::Label( | |
| 463 l10n_util::GetString(IDS_COOKIES_COOKIE_DOMAIN_LABEL)); | |
| 464 domain_value_field_ = new views::Textfield; | |
| 465 path_label_ = new views::Label( | |
| 466 l10n_util::GetString(IDS_COOKIES_COOKIE_PATH_LABEL)); | |
| 467 path_value_field_ = new views::Textfield; | |
| 468 send_for_label_ = new views::Label( | |
| 469 l10n_util::GetString(IDS_COOKIES_COOKIE_SENDFOR_LABEL)); | |
| 470 send_for_value_field_ = new views::Textfield; | |
| 471 created_label_ = new views::Label( | |
| 472 l10n_util::GetString(IDS_COOKIES_COOKIE_CREATED_LABEL)); | |
| 473 created_value_field_ = new views::Textfield; | |
| 474 expires_label_ = new views::Label( | |
| 475 l10n_util::GetString(IDS_COOKIES_COOKIE_EXPIRES_LABEL)); | |
| 476 expires_value_field_ = new views::Textfield; | |
| 477 | |
| 478 using views::GridLayout; | |
| 479 using views::ColumnSet; | |
| 480 | |
| 481 GridLayout* layout = new GridLayout(this); | |
| 482 layout->SetInsets(kCookieInfoViewInsetSize, | |
| 483 kCookieInfoViewInsetSize, | |
| 484 kCookieInfoViewInsetSize, | |
| 485 kCookieInfoViewInsetSize); | |
| 486 SetLayoutManager(layout); | |
| 487 | |
| 488 int three_column_layout_id = 0; | |
| 489 ColumnSet* column_set = layout->AddColumnSet(three_column_layout_id); | |
| 490 column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0, | |
| 491 GridLayout::USE_PREF, 0, 0); | |
| 492 column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); | |
| 493 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, | |
| 494 GridLayout::USE_PREF, 0, 0); | |
| 495 | |
| 496 layout->StartRow(0, three_column_layout_id); | |
| 497 layout->AddView(name_label_); | |
| 498 layout->AddView(name_value_field_); | |
| 499 layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing); | |
| 500 layout->StartRow(0, three_column_layout_id); | |
| 501 layout->AddView(content_label_); | |
| 502 layout->AddView(content_value_field_); | |
| 503 layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing); | |
| 504 layout->StartRow(0, three_column_layout_id); | |
| 505 layout->AddView(domain_label_); | |
| 506 layout->AddView(domain_value_field_); | |
| 507 layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing); | |
| 508 layout->StartRow(0, three_column_layout_id); | |
| 509 layout->AddView(path_label_); | |
| 510 layout->AddView(path_value_field_); | |
| 511 layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing); | |
| 512 layout->StartRow(0, three_column_layout_id); | |
| 513 layout->AddView(send_for_label_); | |
| 514 layout->AddView(send_for_value_field_); | |
| 515 layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing); | |
| 516 layout->StartRow(0, three_column_layout_id); | |
| 517 layout->AddView(created_label_); | |
| 518 layout->AddView(created_value_field_); | |
| 519 layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing); | |
| 520 layout->StartRow(0, three_column_layout_id); | |
| 521 layout->AddView(expires_label_); | |
| 522 layout->AddView(expires_value_field_); | |
| 523 | |
| 524 // Color these borderless text areas the same as the containing dialog. | |
| 525 SkColor text_area_background = color_utils::GetSysSkColor(COLOR_3DFACE); | |
| 526 // Now that the Textfields are in the view hierarchy, we can initialize them. | |
| 527 name_value_field_->SetReadOnly(true); | |
| 528 name_value_field_->RemoveBorder(); | |
| 529 name_value_field_->SetBackgroundColor(text_area_background); | |
| 530 content_value_field_->SetReadOnly(true); | |
| 531 content_value_field_->RemoveBorder(); | |
| 532 content_value_field_->SetBackgroundColor(text_area_background); | |
| 533 domain_value_field_->SetReadOnly(true); | |
| 534 domain_value_field_->RemoveBorder(); | |
| 535 domain_value_field_->SetBackgroundColor(text_area_background); | |
| 536 path_value_field_->SetReadOnly(true); | |
| 537 path_value_field_->RemoveBorder(); | |
| 538 path_value_field_->SetBackgroundColor(text_area_background); | |
| 539 send_for_value_field_->SetReadOnly(true); | |
| 540 send_for_value_field_->RemoveBorder(); | |
| 541 send_for_value_field_->SetBackgroundColor(text_area_background); | |
| 542 created_value_field_->SetReadOnly(true); | |
| 543 created_value_field_->RemoveBorder(); | |
| 544 created_value_field_->SetBackgroundColor(text_area_background); | |
| 545 expires_value_field_->SetReadOnly(true); | |
| 546 expires_value_field_->RemoveBorder(); | |
| 547 expires_value_field_->SetBackgroundColor(text_area_background); | |
| 548 } | |
| 549 | |
| 550 /////////////////////////////////////////////////////////////////////////////// | |
| 551 // CookiesView, public: | |
| 552 | |
| 553 // static | |
| 554 void CookiesView::ShowCookiesWindow(Profile* profile) { | |
| 555 if (!instance_) { | |
| 556 CookiesView* cookies_view = new CookiesView(profile); | |
| 557 instance_ = views::Window::CreateChromeWindow( | |
| 558 NULL, gfx::Rect(), cookies_view); | |
| 559 } | |
| 560 if (!instance_->IsVisible()) { | |
| 561 instance_->Show(); | |
| 562 } else { | |
| 563 instance_->Activate(); | |
| 564 } | |
| 565 } | |
| 566 | |
| 567 CookiesView::~CookiesView() { | |
| 568 cookies_table_->SetModel(NULL); | |
| 569 } | |
| 570 | |
| 571 void CookiesView::UpdateSearchResults() { | |
| 572 cookies_table_model_->UpdateSearchResults(search_field_->text()); | |
| 573 remove_all_button_->SetEnabled(cookies_table_model_->RowCount() > 0); | |
| 574 } | |
| 575 | |
| 576 /////////////////////////////////////////////////////////////////////////////// | |
| 577 // CookiesView, views::Buttonlistener implementation: | |
| 578 | |
| 579 void CookiesView::ButtonPressed(views::Button* sender) { | |
| 580 if (sender == remove_button_) { | |
| 581 cookies_table_->RemoveSelectedCookies(); | |
| 582 } else if (sender == remove_all_button_) { | |
| 583 // Delete all the Cookies shown. | |
| 584 cookies_table_model_->RemoveAllShownCookies(); | |
| 585 UpdateForEmptyState(); | |
| 586 } else if (sender == clear_search_button_) { | |
| 587 ResetSearchQuery(); | |
| 588 } | |
| 589 } | |
| 590 | |
| 591 /////////////////////////////////////////////////////////////////////////////// | |
| 592 // CookiesView, views::TableViewObserver implementation: | |
| 593 void CookiesView::OnSelectionChanged() { | |
| 594 int selected_row_count = cookies_table_->SelectedRowCount(); | |
| 595 if (selected_row_count == 1) { | |
| 596 int selected_index = cookies_table_->FirstSelectedRow(); | |
| 597 if (selected_index >= 0 && | |
| 598 selected_index < cookies_table_model_->RowCount()) { | |
| 599 info_view_->SetCookie(cookies_table_model_->GetDomainAt(selected_index), | |
| 600 cookies_table_model_->GetCookieAt(selected_index)); | |
| 601 } | |
| 602 } else { | |
| 603 info_view_->ClearCookieDisplay(); | |
| 604 } | |
| 605 remove_button_->SetEnabled(selected_row_count != 0); | |
| 606 if (cookies_table_->RowCount() == 0) | |
| 607 UpdateForEmptyState(); | |
| 608 } | |
| 609 | |
| 610 void CookiesView::OnTableViewDelete(views::TableView* table_view) { | |
| 611 cookies_table_->RemoveSelectedCookies(); | |
| 612 } | |
| 613 | |
| 614 /////////////////////////////////////////////////////////////////////////////// | |
| 615 // CookiesView, views::Textfield::Controller implementation: | |
| 616 | |
| 617 void CookiesView::ContentsChanged(views::Textfield* sender, | |
| 618 const std::wstring& new_contents) { | |
| 619 clear_search_button_->SetEnabled(!search_field_->text().empty()); | |
| 620 search_update_factory_.RevokeAll(); | |
| 621 MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
| 622 search_update_factory_.NewRunnableMethod( | |
| 623 &CookiesView::UpdateSearchResults), kSearchFilterDelayMs); | |
| 624 } | |
| 625 | |
| 626 bool CookiesView::HandleKeystroke(views::Textfield* sender, | |
| 627 const views::Textfield::Keystroke& key) { | |
| 628 if (views::Textfield::IsKeystrokeEscape(key)) { | |
| 629 ResetSearchQuery(); | |
| 630 } else if (views::Textfield::IsKeystrokeEnter(key)) { | |
| 631 search_update_factory_.RevokeAll(); | |
| 632 UpdateSearchResults(); | |
| 633 } | |
| 634 return false; | |
| 635 } | |
| 636 | |
| 637 /////////////////////////////////////////////////////////////////////////////// | |
| 638 // CookiesView, views::DialogDelegate implementation: | |
| 639 | |
| 640 std::wstring CookiesView::GetWindowTitle() const { | |
| 641 return l10n_util::GetString(IDS_COOKIES_WINDOW_TITLE); | |
| 642 } | |
| 643 | |
| 644 void CookiesView::WindowClosing() { | |
| 645 instance_ = NULL; | |
| 646 } | |
| 647 | |
| 648 views::View* CookiesView::GetContentsView() { | |
| 649 return this; | |
| 650 } | |
| 651 | |
| 652 /////////////////////////////////////////////////////////////////////////////// | |
| 653 // CookiesView, views::View overrides: | |
| 654 | |
| 655 void CookiesView::Layout() { | |
| 656 // Lay out the Remove/Remove All buttons in the parent view. | |
| 657 gfx::Size ps = remove_button_->GetPreferredSize(); | |
| 658 gfx::Rect parent_bounds = GetParent()->GetLocalBounds(false); | |
| 659 int y_buttons = parent_bounds.bottom() - ps.height() - kButtonVEdgeMargin; | |
| 660 | |
| 661 remove_button_->SetBounds(kPanelHorizMargin, y_buttons, ps.width(), | |
| 662 ps.height()); | |
| 663 | |
| 664 ps = remove_all_button_->GetPreferredSize(); | |
| 665 int remove_all_x = remove_button_->x() + remove_button_->width() + | |
| 666 kRelatedControlHorizontalSpacing; | |
| 667 remove_all_button_->SetBounds(remove_all_x, y_buttons, ps.width(), | |
| 668 ps.height()); | |
| 669 | |
| 670 // Lay out this View | |
| 671 View::Layout(); | |
| 672 } | |
| 673 | |
| 674 gfx::Size CookiesView::GetPreferredSize() { | |
| 675 return gfx::Size(views::Window::GetLocalizedContentsSize( | |
| 676 IDS_COOKIES_DIALOG_WIDTH_CHARS, | |
| 677 IDS_COOKIES_DIALOG_HEIGHT_LINES)); | |
| 678 } | |
| 679 | |
| 680 void CookiesView::ViewHierarchyChanged(bool is_add, | |
| 681 views::View* parent, | |
| 682 views::View* child) { | |
| 683 if (is_add && child == this) | |
| 684 Init(); | |
| 685 } | |
| 686 | |
| 687 /////////////////////////////////////////////////////////////////////////////// | |
| 688 // CookiesView, private: | |
| 689 | |
| 690 CookiesView::CookiesView(Profile* profile) | |
| 691 : search_label_(NULL), | |
| 692 search_field_(NULL), | |
| 693 clear_search_button_(NULL), | |
| 694 description_label_(NULL), | |
| 695 cookies_table_(NULL), | |
| 696 info_view_(NULL), | |
| 697 remove_button_(NULL), | |
| 698 remove_all_button_(NULL), | |
| 699 profile_(profile), | |
| 700 ALLOW_THIS_IN_INITIALIZER_LIST(search_update_factory_(this)) { | |
| 701 } | |
| 702 | |
| 703 void CookiesView::Init() { | |
| 704 search_label_ = new views::Label( | |
| 705 l10n_util::GetString(IDS_COOKIES_SEARCH_LABEL)); | |
| 706 search_field_ = new views::Textfield; | |
| 707 search_field_->SetController(this); | |
| 708 clear_search_button_ = new views::NativeButton( | |
| 709 this, l10n_util::GetString(IDS_COOKIES_CLEAR_SEARCH_LABEL)); | |
| 710 clear_search_button_->SetEnabled(false); | |
| 711 description_label_ = new views::Label( | |
| 712 l10n_util::GetString(IDS_COOKIES_INFO_LABEL)); | |
| 713 description_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 714 | |
| 715 cookies_table_model_.reset(new CookiesTableModel(profile_)); | |
| 716 info_view_ = new CookieInfoView; | |
| 717 std::vector<TableColumn> columns; | |
| 718 columns.push_back(TableColumn(IDS_COOKIES_DOMAIN_COLUMN_HEADER, | |
| 719 TableColumn::LEFT, 200, 0.5f)); | |
| 720 columns.back().sortable = true; | |
| 721 columns.push_back(TableColumn(IDS_COOKIES_NAME_COLUMN_HEADER, | |
| 722 TableColumn::LEFT, 150, 0.5f)); | |
| 723 columns.back().sortable = true; | |
| 724 cookies_table_ = new CookiesTableView(cookies_table_model_.get(), columns); | |
| 725 cookies_table_->SetObserver(this); | |
| 726 // Make the table initially sorted by domain. | |
| 727 views::TableView::SortDescriptors sort; | |
| 728 sort.push_back( | |
| 729 views::TableView::SortDescriptor(IDS_COOKIES_DOMAIN_COLUMN_HEADER, | |
| 730 true)); | |
| 731 cookies_table_->SetSortDescriptors(sort); | |
| 732 remove_button_ = new views::NativeButton( | |
| 733 this, l10n_util::GetString(IDS_COOKIES_REMOVE_LABEL)); | |
| 734 remove_all_button_ = new views::NativeButton( | |
| 735 this, l10n_util::GetString(IDS_COOKIES_REMOVE_ALL_LABEL)); | |
| 736 | |
| 737 using views::GridLayout; | |
| 738 using views::ColumnSet; | |
| 739 | |
| 740 GridLayout* layout = CreatePanelGridLayout(this); | |
| 741 SetLayoutManager(layout); | |
| 742 | |
| 743 const int five_column_layout_id = 0; | |
| 744 ColumnSet* column_set = layout->AddColumnSet(five_column_layout_id); | |
| 745 column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0, | |
| 746 GridLayout::USE_PREF, 0, 0); | |
| 747 column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); | |
| 748 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, | |
| 749 GridLayout::USE_PREF, 0, 0); | |
| 750 column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); | |
| 751 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0, | |
| 752 GridLayout::USE_PREF, 0, 0); | |
| 753 | |
| 754 const int single_column_layout_id = 1; | |
| 755 column_set = layout->AddColumnSet(single_column_layout_id); | |
| 756 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, | |
| 757 GridLayout::USE_PREF, 0, 0); | |
| 758 | |
| 759 layout->StartRow(0, five_column_layout_id); | |
| 760 layout->AddView(search_label_); | |
| 761 layout->AddView(search_field_); | |
| 762 layout->AddView(clear_search_button_); | |
| 763 layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing); | |
| 764 layout->StartRow(0, single_column_layout_id); | |
| 765 layout->AddView(description_label_); | |
| 766 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); | |
| 767 layout->StartRow(1, single_column_layout_id); | |
| 768 layout->AddView(cookies_table_); | |
| 769 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); | |
| 770 layout->StartRow(0, single_column_layout_id); | |
| 771 layout->AddView(info_view_); | |
| 772 | |
| 773 // Add the Remove/Remove All buttons to the ClientView | |
| 774 View* parent = GetParent(); | |
| 775 parent->AddChildView(remove_button_); | |
| 776 parent->AddChildView(remove_all_button_); | |
| 777 | |
| 778 if (cookies_table_->RowCount() > 0) { | |
| 779 cookies_table_->Select(0); | |
| 780 } else { | |
| 781 UpdateForEmptyState(); | |
| 782 } | |
| 783 } | |
| 784 | |
| 785 void CookiesView::ResetSearchQuery() { | |
| 786 search_field_->SetText(EmptyWString()); | |
| 787 clear_search_button_->SetEnabled(false); | |
| 788 UpdateSearchResults(); | |
| 789 } | |
| 790 | |
| 791 void CookiesView::UpdateForEmptyState() { | |
| 792 info_view_->ClearCookieDisplay(); | |
| 793 remove_button_->SetEnabled(false); | |
| 794 remove_all_button_->SetEnabled(false); | |
| 795 } | |
| OLD | NEW |