OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/task_manager/task_manager.h" | 5 #include "chrome/browser/task_manager/task_manager.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/metrics/stats_table.h" | 9 #include "base/metrics/stats_table.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
11 #include "chrome/app/chrome_command_ids.h" | 11 #include "chrome/app/chrome_command_ids.h" |
12 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
13 #include "chrome/browser/memory_purger.h" | 13 #include "chrome/browser/memory_purger.h" |
14 #include "chrome/browser/prefs/pref_service.h" | 14 #include "chrome/browser/prefs/pref_service.h" |
15 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 15 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
16 #include "chrome/browser/ui/browser_list.h" | 16 #include "chrome/browser/ui/browser_list.h" |
17 #include "chrome/browser/ui/browser_window.h" | 17 #include "chrome/browser/ui/browser_window.h" |
18 #include "chrome/browser/ui/host_desktop.h" | 18 #include "chrome/browser/ui/host_desktop.h" |
19 #include "chrome/browser/ui/views/browser_dialogs.h" | 19 #include "chrome/browser/ui/views/browser_dialogs.h" |
20 #include "chrome/common/chrome_switches.h" | 20 #include "chrome/common/chrome_switches.h" |
21 #include "chrome/common/pref_names.h" | 21 #include "chrome/common/pref_names.h" |
22 #include "grit/chromium_strings.h" | 22 #include "grit/chromium_strings.h" |
23 #include "grit/generated_resources.h" | 23 #include "grit/generated_resources.h" |
24 #include "grit/theme_resources.h" | 24 #include "grit/theme_resources.h" |
25 #include "ui/base/accelerators/accelerator.h" | 25 #include "ui/base/accelerators/accelerator.h" |
26 #include "ui/base/l10n/l10n_util.h" | 26 #include "ui/base/l10n/l10n_util.h" |
| 27 #include "ui/base/models/simple_menu_model.h" |
27 #include "ui/base/models/table_model_observer.h" | 28 #include "ui/base/models/table_model_observer.h" |
28 #include "ui/views/background.h" | 29 #include "ui/views/background.h" |
29 #include "ui/views/context_menu_controller.h" | 30 #include "ui/views/context_menu_controller.h" |
30 #include "ui/views/controls/button/text_button.h" | 31 #include "ui/views/controls/button/text_button.h" |
31 #include "ui/views/controls/link.h" | 32 #include "ui/views/controls/link.h" |
32 #include "ui/views/controls/link_listener.h" | 33 #include "ui/views/controls/link_listener.h" |
33 #include "ui/views/controls/menu/menu.h" | 34 #include "ui/views/controls/menu/menu_model_adapter.h" |
| 35 #include "ui/views/controls/menu/menu_runner.h" |
34 #include "ui/views/controls/table/group_table_model.h" | 36 #include "ui/views/controls/table/group_table_model.h" |
35 #include "ui/views/controls/table/group_table_view.h" | 37 #include "ui/views/controls/table/group_table_view.h" |
36 #include "ui/views/controls/table/table_view_observer.h" | 38 #include "ui/views/controls/table/table_view_observer.h" |
37 #include "ui/views/layout/layout_constants.h" | 39 #include "ui/views/layout/layout_constants.h" |
38 #include "ui/views/widget/widget.h" | 40 #include "ui/views/widget/widget.h" |
39 #include "ui/views/window/dialog_delegate.h" | 41 #include "ui/views/window/dialog_delegate.h" |
40 | 42 |
41 #if defined(OS_WIN) | 43 #if defined(OS_WIN) |
42 #include "win8/util/win8_util.h" | 44 #include "win8/util/win8_util.h" |
43 #endif | 45 #endif |
(...skipping 14 matching lines...) Expand all Loading... |
58 | 60 |
59 class TaskManagerTableModel : public views::GroupTableModel, | 61 class TaskManagerTableModel : public views::GroupTableModel, |
60 public TaskManagerModelObserver { | 62 public TaskManagerModelObserver { |
61 public: | 63 public: |
62 explicit TaskManagerTableModel(TaskManagerModel* model) | 64 explicit TaskManagerTableModel(TaskManagerModel* model) |
63 : model_(model), | 65 : model_(model), |
64 observer_(NULL) { | 66 observer_(NULL) { |
65 model_->AddObserver(this); | 67 model_->AddObserver(this); |
66 } | 68 } |
67 | 69 |
68 ~TaskManagerTableModel() { | 70 virtual ~TaskManagerTableModel() { |
69 model_->RemoveObserver(this); | 71 model_->RemoveObserver(this); |
70 } | 72 } |
71 | 73 |
72 // GroupTableModel. | 74 // GroupTableModel. |
73 int RowCount() OVERRIDE; | 75 int RowCount() OVERRIDE; |
74 string16 GetText(int row, int column) OVERRIDE; | 76 string16 GetText(int row, int column) OVERRIDE; |
75 gfx::ImageSkia GetIcon(int row) OVERRIDE; | 77 gfx::ImageSkia GetIcon(int row) OVERRIDE; |
76 void GetGroupRangeForItem(int item, views::GroupRange* range) OVERRIDE; | 78 void GetGroupRangeForItem(int item, views::GroupRange* range) OVERRIDE; |
77 void SetObserver(ui::TableModelObserver* observer) OVERRIDE; | 79 void SetObserver(ui::TableModelObserver* observer) OVERRIDE; |
78 virtual int CompareValues(int row1, int row2, int column_id) OVERRIDE; | 80 virtual int CompareValues(int row1, int row2, int column_id) OVERRIDE; |
79 | 81 |
80 // TaskManagerModelObserver. | 82 // TaskManagerModelObserver. |
81 virtual void OnModelChanged(); | 83 virtual void OnModelChanged(); |
82 virtual void OnItemsChanged(int start, int length); | 84 virtual void OnItemsChanged(int start, int length); |
83 virtual void OnItemsAdded(int start, int length); | 85 virtual void OnItemsAdded(int start, int length); |
84 virtual void OnItemsRemoved(int start, int length); | 86 virtual void OnItemsRemoved(int start, int length); |
85 | 87 |
86 // Returns true if resource corresponding to |row| is a background resource. | 88 // Returns true if resource corresponding to |row| is a background resource. |
87 bool IsBackgroundResource(int row); | 89 bool IsBackgroundResource(int row); |
88 | 90 |
89 private: | 91 private: |
90 TaskManagerModel* model_; | 92 TaskManagerModel* model_; |
91 ui::TableModelObserver* observer_; | 93 ui::TableModelObserver* observer_; |
| 94 |
| 95 DISALLOW_COPY_AND_ASSIGN(TaskManagerTableModel); |
92 }; | 96 }; |
93 | 97 |
94 int TaskManagerTableModel::RowCount() { | 98 int TaskManagerTableModel::RowCount() { |
95 return model_->ResourceCount(); | 99 return model_->ResourceCount(); |
96 } | 100 } |
97 | 101 |
98 string16 TaskManagerTableModel::GetText(int row, int col_id) { | 102 string16 TaskManagerTableModel::GetText(int row, int col_id) { |
99 switch (col_id) { | 103 switch (col_id) { |
100 case IDS_TASK_MANAGER_TASK_COLUMN: // Process | 104 case IDS_TASK_MANAGER_TASK_COLUMN: // Process |
101 return model_->GetResourceTitle(row); | 105 return model_->GetResourceTitle(row); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 | 272 |
269 TaskManagerTableModel* model_; | 273 TaskManagerTableModel* model_; |
270 }; | 274 }; |
271 | 275 |
272 // The Task manager UI container. | 276 // The Task manager UI container. |
273 class TaskManagerView : public views::ButtonListener, | 277 class TaskManagerView : public views::ButtonListener, |
274 public views::DialogDelegateView, | 278 public views::DialogDelegateView, |
275 public views::TableViewObserver, | 279 public views::TableViewObserver, |
276 public views::LinkListener, | 280 public views::LinkListener, |
277 public views::ContextMenuController, | 281 public views::ContextMenuController, |
278 public views::Menu::Delegate { | 282 public ui::SimpleMenuModel::Delegate { |
279 public: | 283 public: |
280 TaskManagerView(bool highlight_background_resources, | 284 TaskManagerView(bool highlight_background_resources, |
281 chrome::HostDesktopType desktop_type); | 285 chrome::HostDesktopType desktop_type); |
282 virtual ~TaskManagerView(); | 286 virtual ~TaskManagerView(); |
283 | 287 |
284 // Shows the Task manager window, or re-activates an existing one. If | 288 // Shows the Task manager window, or re-activates an existing one. If |
285 // |highlight_background_resources| is true, highlights the background | 289 // |highlight_background_resources| is true, highlights the background |
286 // resources in the resource display. | 290 // resources in the resource display. |
287 static void Show(bool highlight_background_resources, | 291 static void Show(bool highlight_background_resources, |
288 chrome::HostDesktopType desktop_type); | 292 chrome::HostDesktopType desktop_type); |
(...skipping 26 matching lines...) Expand all Loading... |
315 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; | 319 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; |
316 | 320 |
317 // Called by the column picker to pick up any new stat counters that | 321 // Called by the column picker to pick up any new stat counters that |
318 // may have appeared since last time. | 322 // may have appeared since last time. |
319 void UpdateStatsCounters(); | 323 void UpdateStatsCounters(); |
320 | 324 |
321 // views::ContextMenuController: | 325 // views::ContextMenuController: |
322 virtual void ShowContextMenuForView(views::View* source, | 326 virtual void ShowContextMenuForView(views::View* source, |
323 const gfx::Point& point) OVERRIDE; | 327 const gfx::Point& point) OVERRIDE; |
324 | 328 |
325 // views::Menu::Delegate: | 329 // ui::SimpleMenuModel::Delegate: |
326 virtual bool IsItemChecked(int id) const OVERRIDE; | 330 virtual bool IsCommandIdChecked(int id) const OVERRIDE; |
| 331 virtual bool IsCommandIdEnabled(int id) const OVERRIDE; |
| 332 virtual bool GetAcceleratorForCommandId( |
| 333 int command_id, |
| 334 ui::Accelerator* accelerator) OVERRIDE; |
327 virtual void ExecuteCommand(int id) OVERRIDE; | 335 virtual void ExecuteCommand(int id) OVERRIDE; |
328 | 336 |
329 private: | 337 private: |
330 // Creates the child controls. | 338 // Creates the child controls. |
331 void Init(); | 339 void Init(); |
332 | 340 |
333 // Initializes the state of the always-on-top setting as the window is shown. | 341 // Initializes the state of the always-on-top setting as the window is shown. |
334 void InitAlwaysOnTopState(); | 342 void InitAlwaysOnTopState(); |
335 | 343 |
336 // Activates the tab associated with the focused row. | 344 // Activates the tab associated with the focused row. |
(...skipping 28 matching lines...) Expand all Loading... |
365 // The host desktop type this task manager belongs to. | 373 // The host desktop type this task manager belongs to. |
366 const chrome::HostDesktopType desktop_type_; | 374 const chrome::HostDesktopType desktop_type_; |
367 | 375 |
368 // We need to own the text of the menu, the Windows API does not copy it. | 376 // We need to own the text of the menu, the Windows API does not copy it. |
369 string16 always_on_top_menu_text_; | 377 string16 always_on_top_menu_text_; |
370 | 378 |
371 // An open Task manager window. There can only be one open at a time. This | 379 // An open Task manager window. There can only be one open at a time. This |
372 // is reset to NULL when the window is closed. | 380 // is reset to NULL when the window is closed. |
373 static TaskManagerView* instance_; | 381 static TaskManagerView* instance_; |
374 | 382 |
| 383 scoped_ptr<views::MenuRunner> menu_runner_; |
| 384 |
375 DISALLOW_COPY_AND_ASSIGN(TaskManagerView); | 385 DISALLOW_COPY_AND_ASSIGN(TaskManagerView); |
376 }; | 386 }; |
377 | 387 |
378 // static | 388 // static |
379 TaskManagerView* TaskManagerView::instance_ = NULL; | 389 TaskManagerView* TaskManagerView::instance_ = NULL; |
380 | 390 |
381 | 391 |
382 TaskManagerView::TaskManagerView(bool highlight_background_resources, | 392 TaskManagerView::TaskManagerView(bool highlight_background_resources, |
383 chrome::HostDesktopType desktop_type) | 393 chrome::HostDesktopType desktop_type) |
384 : purge_memory_button_(NULL), | 394 : purge_memory_button_(NULL), |
| 395 kill_button_(NULL), |
| 396 about_memory_link_(NULL), |
| 397 tab_table_(NULL), |
385 task_manager_(TaskManager::GetInstance()), | 398 task_manager_(TaskManager::GetInstance()), |
386 model_(TaskManager::GetInstance()->model()), | 399 model_(TaskManager::GetInstance()->model()), |
387 is_always_on_top_(false), | 400 is_always_on_top_(false), |
388 highlight_background_resources_(highlight_background_resources), | 401 highlight_background_resources_(highlight_background_resources), |
389 desktop_type_(desktop_type) { | 402 desktop_type_(desktop_type) { |
390 Init(); | 403 Init(); |
391 } | 404 } |
392 | 405 |
393 TaskManagerView::~TaskManagerView() { | 406 TaskManagerView::~TaskManagerView() { |
394 // Delete child views now, while our table model still exists. | 407 // Delete child views now, while our table model still exists. |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 } else { | 546 } else { |
534 parent->RemoveChildView(kill_button_); | 547 parent->RemoveChildView(kill_button_); |
535 if (purge_memory_button_) | 548 if (purge_memory_button_) |
536 parent->RemoveChildView(purge_memory_button_); | 549 parent->RemoveChildView(purge_memory_button_); |
537 parent->RemoveChildView(about_memory_link_); | 550 parent->RemoveChildView(about_memory_link_); |
538 } | 551 } |
539 } | 552 } |
540 } | 553 } |
541 | 554 |
542 void TaskManagerView::Layout() { | 555 void TaskManagerView::Layout() { |
543 // views::kPanelHorizMargin is too big. | |
544 const int kTableButtonSpacing = 12; | |
545 | |
546 gfx::Size size = kill_button_->GetPreferredSize(); | 556 gfx::Size size = kill_button_->GetPreferredSize(); |
547 int prefered_width = size.width(); | 557 int prefered_width = size.width(); |
548 int prefered_height = size.height(); | 558 int prefered_height = size.height(); |
549 | 559 |
550 tab_table_->SetBounds( | 560 tab_table_->SetBounds( |
551 x() + views::kPanelHorizMargin, | 561 x() + views::kPanelHorizMargin, |
552 y() + views::kPanelVertMargin, | 562 y() + views::kPanelVertMargin, |
553 width() - 2 * views::kPanelHorizMargin, | 563 width() - 2 * views::kPanelHorizMargin, |
554 height() - 2 * views::kPanelVertMargin - prefered_height); | 564 height() - 2 * views::kPanelVertMargin - prefered_height); |
555 | 565 |
(...skipping 29 matching lines...) Expand all Loading... |
585 link_prefered_height); | 595 link_prefered_height); |
586 } | 596 } |
587 | 597 |
588 gfx::Size TaskManagerView::GetPreferredSize() { | 598 gfx::Size TaskManagerView::GetPreferredSize() { |
589 return gfx::Size(kDefaultWidth, kDefaultHeight); | 599 return gfx::Size(kDefaultWidth, kDefaultHeight); |
590 } | 600 } |
591 | 601 |
592 // static | 602 // static |
593 void TaskManagerView::Show(bool highlight_background_resources, | 603 void TaskManagerView::Show(bool highlight_background_resources, |
594 chrome::HostDesktopType desktop_type) { | 604 chrome::HostDesktopType desktop_type) { |
| 605 #if defined(OS_WIN) |
595 // In Windows Metro it's not good to open this native window. | 606 // In Windows Metro it's not good to open this native window. |
596 DCHECK(!win8::IsSingleWindowMetroMode()); | 607 DCHECK(!win8::IsSingleWindowMetroMode()); |
| 608 #endif |
597 | 609 |
598 if (instance_) { | 610 if (instance_) { |
599 if (instance_->highlight_background_resources_ != | 611 if (instance_->highlight_background_resources_ != |
600 highlight_background_resources || | 612 highlight_background_resources || |
601 instance_->desktop_type_ != desktop_type) { | 613 instance_->desktop_type_ != desktop_type) { |
602 instance_->GetWidget()->Close(); | 614 instance_->GetWidget()->Close(); |
603 } else { | 615 } else { |
604 // If there's a Task manager window open already, just activate it. | 616 // If there's a Task manager window open already, just activate it. |
605 instance_->GetWidget()->Activate(); | 617 instance_->GetWidget()->Activate(); |
606 return; | 618 return; |
607 } | 619 } |
608 } | 620 } |
609 instance_ = new TaskManagerView(highlight_background_resources, | 621 instance_ = new TaskManagerView(highlight_background_resources, desktop_type); |
610 desktop_type); | |
611 views::Widget::CreateWindow(instance_); | 622 views::Widget::CreateWindow(instance_); |
612 instance_->InitAlwaysOnTopState(); | 623 instance_->InitAlwaysOnTopState(); |
613 instance_->model_->StartUpdating(); | 624 instance_->model_->StartUpdating(); |
614 instance_->GetWidget()->Show(); | 625 instance_->GetWidget()->Show(); |
615 | 626 |
616 // Set the initial focus to the list of tasks. | 627 // Set the initial focus to the list of tasks. |
617 views::FocusManager* focus_manager = instance_->GetFocusManager(); | 628 views::FocusManager* focus_manager = instance_->GetFocusManager(); |
618 if (focus_manager) | 629 if (focus_manager) |
619 focus_manager->SetFocusedView(instance_->tab_table_); | 630 focus_manager->SetFocusedView(instance_->tab_table_); |
620 } | 631 } |
621 | 632 |
622 // ButtonListener implementation. | 633 // ButtonListener implementation. |
623 void TaskManagerView::ButtonPressed( | 634 void TaskManagerView::ButtonPressed( |
624 views::Button* sender, const ui::Event& event) { | 635 views::Button* sender, |
| 636 const ui::Event& event) { |
625 if (purge_memory_button_ && (sender == purge_memory_button_)) { | 637 if (purge_memory_button_ && (sender == purge_memory_button_)) { |
626 MemoryPurger::PurgeAll(); | 638 MemoryPurger::PurgeAll(); |
627 } else { | 639 } else { |
628 DCHECK_EQ(kill_button_, sender); | 640 DCHECK_EQ(kill_button_, sender); |
629 for (views::TableSelectionIterator iter = tab_table_->SelectionBegin(); | 641 for (views::TableSelectionIterator iter = tab_table_->SelectionBegin(); |
630 iter != tab_table_->SelectionEnd(); ++iter) | 642 iter != tab_table_->SelectionEnd(); ++iter) |
631 task_manager_->KillProcess(*iter); | 643 task_manager_->KillProcess(*iter); |
632 } | 644 } |
633 } | 645 } |
634 | 646 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 } | 732 } |
721 | 733 |
722 void TaskManagerView::LinkClicked(views::Link* source, int event_flags) { | 734 void TaskManagerView::LinkClicked(views::Link* source, int event_flags) { |
723 DCHECK_EQ(about_memory_link_, source); | 735 DCHECK_EQ(about_memory_link_, source); |
724 task_manager_->OpenAboutMemory(desktop_type_); | 736 task_manager_->OpenAboutMemory(desktop_type_); |
725 } | 737 } |
726 | 738 |
727 void TaskManagerView::ShowContextMenuForView(views::View* source, | 739 void TaskManagerView::ShowContextMenuForView(views::View* source, |
728 const gfx::Point& point) { | 740 const gfx::Point& point) { |
729 UpdateStatsCounters(); | 741 UpdateStatsCounters(); |
730 scoped_ptr<views::Menu> menu(views::Menu::Create( | 742 ui::SimpleMenuModel menu_model(this); |
731 this, views::Menu::TOPLEFT, source->GetWidget()->GetNativeView())); | |
732 for (std::vector<ui::TableColumn>::iterator i(columns_.begin()); | 743 for (std::vector<ui::TableColumn>::iterator i(columns_.begin()); |
733 i != columns_.end(); ++i) { | 744 i != columns_.end(); ++i) { |
734 menu->AppendMenuItem(i->id, l10n_util::GetStringUTF16(i->id), | 745 menu_model.AddCheckItem(i->id, l10n_util::GetStringUTF16(i->id)); |
735 views::Menu::CHECKBOX); | |
736 } | 746 } |
737 menu->RunMenuAt(point.x(), point.y()); | 747 views::MenuModelAdapter menu_adapter(&menu_model); |
| 748 menu_runner_.reset(new views::MenuRunner(menu_adapter.CreateMenu())); |
| 749 if (menu_runner_->RunMenuAt(GetWidget(), NULL, gfx::Rect(point, gfx::Size()), |
| 750 views::MenuItemView::TOPLEFT, |
| 751 views::MenuRunner::CONTEXT_MENU) == |
| 752 views::MenuRunner::MENU_DELETED) |
| 753 return; |
738 } | 754 } |
739 | 755 |
740 bool TaskManagerView::IsItemChecked(int id) const { | 756 bool TaskManagerView::IsCommandIdChecked(int id) const { |
741 return tab_table_->IsColumnVisible(id); | 757 return tab_table_->IsColumnVisible(id); |
742 } | 758 } |
743 | 759 |
| 760 bool TaskManagerView::IsCommandIdEnabled(int id) const { |
| 761 return true; |
| 762 } |
| 763 |
| 764 bool TaskManagerView::GetAcceleratorForCommandId( |
| 765 int command_id, |
| 766 ui::Accelerator* accelerator) { |
| 767 return false; |
| 768 } |
| 769 |
744 void TaskManagerView::ExecuteCommand(int id) { | 770 void TaskManagerView::ExecuteCommand(int id) { |
745 tab_table_->SetColumnVisibility(id, !tab_table_->IsColumnVisible(id)); | 771 tab_table_->SetColumnVisibility(id, !tab_table_->IsColumnVisible(id)); |
746 } | 772 } |
747 | 773 |
748 void TaskManagerView::InitAlwaysOnTopState() { | 774 void TaskManagerView::InitAlwaysOnTopState() { |
749 is_always_on_top_ = false; | 775 is_always_on_top_ = false; |
750 if (GetSavedAlwaysOnTopState(&is_always_on_top_)) | 776 if (GetSavedAlwaysOnTopState(&is_always_on_top_)) |
751 GetWidget()->SetAlwaysOnTop(is_always_on_top_); | 777 GetWidget()->SetAlwaysOnTop(is_always_on_top_); |
752 AddAlwaysOnTopSystemMenuItem(); | 778 AddAlwaysOnTopSystemMenuItem(); |
753 } | 779 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
812 // Declared in browser_dialogs.h so others don't need to depend on our header. | 838 // Declared in browser_dialogs.h so others don't need to depend on our header. |
813 void ShowTaskManager(chrome::HostDesktopType desktop_type) { | 839 void ShowTaskManager(chrome::HostDesktopType desktop_type) { |
814 TaskManagerView::Show(false, desktop_type); | 840 TaskManagerView::Show(false, desktop_type); |
815 } | 841 } |
816 | 842 |
817 void ShowBackgroundPages(chrome::HostDesktopType desktop_type) { | 843 void ShowBackgroundPages(chrome::HostDesktopType desktop_type) { |
818 TaskManagerView::Show(true, desktop_type); | 844 TaskManagerView::Show(true, desktop_type); |
819 } | 845 } |
820 | 846 |
821 } // namespace chrome | 847 } // namespace chrome |
OLD | NEW |