PageRenderTime 49ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/chrome/browser/views/task_manager_view.cc

https://github.com/akesling/chromium
C++ | 630 lines | 456 code | 103 blank | 71 comment | 47 complexity | 4bf0193e9afba4a690da2f75f65ec22a MD5 | raw file
  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
  3. // found in the LICENSE file.
  4. #include "chrome/browser/task_manager.h"
  5. #include "app/l10n_util.h"
  6. #include "app/table_model_observer.h"
  7. #include "base/stats_table.h"
  8. #include "chrome/app/chrome_dll_resource.h"
  9. #include "chrome/browser/browser_list.h"
  10. #include "chrome/browser/browser_process.h"
  11. #include "chrome/browser/browser_window.h"
  12. #include "chrome/browser/views/browser_dialogs.h"
  13. #include "chrome/common/pref_names.h"
  14. #include "chrome/common/pref_service.h"
  15. #include "grit/chromium_strings.h"
  16. #include "grit/generated_resources.h"
  17. #include "grit/theme_resources.h"
  18. #include "views/accelerator.h"
  19. #include "views/background.h"
  20. #include "views/controls/button/native_button.h"
  21. #include "views/controls/link.h"
  22. #include "views/controls/menu/menu.h"
  23. #include "views/controls/table/group_table_view.h"
  24. #include "views/controls/table/table_view_observer.h"
  25. #include "views/standard_layout.h"
  26. #include "views/widget/widget.h"
  27. #include "views/window/dialog_delegate.h"
  28. #include "views/window/window.h"
  29. // The task manager window default size.
  30. static const int kDefaultWidth = 460;
  31. static const int kDefaultHeight = 270;
  32. // An id for the most important column, made sufficiently large so as not to
  33. // collide with anything else.
  34. static const int64 kNuthMagicNumber = 1737350766;
  35. static const int kBitMask = 0x7FFFFFFF;
  36. static const int kGoatsTeleportedColumn =
  37. (94024 * kNuthMagicNumber) & kBitMask;
  38. namespace {
  39. ////////////////////////////////////////////////////////////////////////////////
  40. // TaskManagerTableModel class
  41. ////////////////////////////////////////////////////////////////////////////////
  42. class TaskManagerTableModel : public views::GroupTableModel,
  43. public TaskManagerModelObserver {
  44. public:
  45. explicit TaskManagerTableModel(TaskManagerModel* model)
  46. : model_(model),
  47. observer_(NULL) {
  48. model->SetObserver(this);
  49. }
  50. ~TaskManagerTableModel() {}
  51. // GroupTableModel.
  52. int RowCount();
  53. std::wstring GetText(int row, int column);
  54. SkBitmap GetIcon(int row);
  55. void GetGroupRangeForItem(int item, views::GroupRange* range);
  56. void SetObserver(TableModelObserver* observer);
  57. virtual int CompareValues(int row1, int row2, int column_id);
  58. // TaskManagerModelObserver.
  59. virtual void OnModelChanged();
  60. virtual void OnItemsChanged(int start, int length);
  61. virtual void OnItemsAdded(int start, int length);
  62. virtual void OnItemsRemoved(int start, int length);
  63. private:
  64. const TaskManagerModel* model_;
  65. TableModelObserver* observer_;
  66. };
  67. int TaskManagerTableModel::RowCount() {
  68. return model_->ResourceCount();
  69. }
  70. std::wstring TaskManagerTableModel::GetText(int row, int col_id) {
  71. switch (col_id) {
  72. case IDS_TASK_MANAGER_PAGE_COLUMN: // Process
  73. return model_->GetResourceTitle(row);
  74. case IDS_TASK_MANAGER_NET_COLUMN: // Net
  75. return model_->GetResourceNetworkUsage(row);
  76. case IDS_TASK_MANAGER_CPU_COLUMN: // CPU
  77. if (!model_->IsResourceFirstInGroup(row))
  78. return std::wstring();
  79. return model_->GetResourceCPUUsage(row);
  80. case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: // Memory
  81. if (!model_->IsResourceFirstInGroup(row))
  82. return std::wstring();
  83. return model_->GetResourcePrivateMemory(row);
  84. case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: // Memory
  85. if (!model_->IsResourceFirstInGroup(row))
  86. return std::wstring();
  87. return model_->GetResourceSharedMemory(row);
  88. case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN: // Memory
  89. if (!model_->IsResourceFirstInGroup(row))
  90. return std::wstring();
  91. return model_->GetResourcePhysicalMemory(row);
  92. case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
  93. if (!model_->IsResourceFirstInGroup(row))
  94. return std::wstring();
  95. return model_->GetResourceProcessId(row);
  96. case kGoatsTeleportedColumn: // Goats Teleported!
  97. return model_->GetResourceGoatsTeleported(row);
  98. default:
  99. return model_->GetResourceStatsValue(row, col_id);
  100. }
  101. }
  102. SkBitmap TaskManagerTableModel::GetIcon(int row) {
  103. return model_->GetResourceIcon(row);
  104. }
  105. void TaskManagerTableModel::GetGroupRangeForItem(int item,
  106. views::GroupRange* range) {
  107. std::pair<int, int> range_pair = model_->GetGroupRangeForResource(item);
  108. range->start = range_pair.first;
  109. range->length = range_pair.second;
  110. }
  111. void TaskManagerTableModel::SetObserver(TableModelObserver* observer) {
  112. observer_ = observer;
  113. }
  114. int TaskManagerTableModel::CompareValues(int row1, int row2, int column_id) {
  115. return model_->CompareValues(row1, row2, column_id);
  116. }
  117. void TaskManagerTableModel::OnModelChanged() {
  118. if (observer_)
  119. observer_->OnModelChanged();
  120. }
  121. void TaskManagerTableModel::OnItemsChanged(int start, int length) {
  122. if (observer_)
  123. observer_->OnItemsChanged(start, length);
  124. }
  125. void TaskManagerTableModel::OnItemsAdded(int start, int length) {
  126. if (observer_)
  127. observer_->OnItemsAdded(start, length);
  128. }
  129. void TaskManagerTableModel::OnItemsRemoved(int start, int length) {
  130. if (observer_)
  131. observer_->OnItemsRemoved(start, length);
  132. }
  133. // The Task manager UI container.
  134. class TaskManagerView : public views::View,
  135. public views::ButtonListener,
  136. public views::DialogDelegate,
  137. public views::TableViewObserver,
  138. public views::LinkController,
  139. public views::ContextMenuController,
  140. public views::Menu::Delegate {
  141. public:
  142. TaskManagerView();
  143. virtual ~TaskManagerView();
  144. // Shows the Task manager window, or re-activates an existing one.
  145. static void Show();
  146. // views::View
  147. virtual void Layout();
  148. virtual gfx::Size GetPreferredSize();
  149. virtual void ViewHierarchyChanged(bool is_add, views::View* parent,
  150. views::View* child);
  151. // ButtonListener implementation.
  152. virtual void ButtonPressed(views::Button* sender);
  153. // views::DialogDelegate
  154. virtual bool CanResize() const;
  155. virtual bool CanMaximize() const;
  156. virtual bool ExecuteWindowsCommand(int command_id);
  157. virtual std::wstring GetWindowTitle() const;
  158. virtual std::wstring GetWindowName() const;
  159. virtual int GetDialogButtons() const;
  160. virtual void WindowClosing();
  161. virtual void DeleteDelegate();
  162. virtual views::View* GetContentsView();
  163. // views::TableViewObserver implementation.
  164. virtual void OnSelectionChanged();
  165. virtual void OnDoubleClick();
  166. virtual void OnKeyDown(unsigned short virtual_keycode);
  167. // views::LinkController implementation.
  168. virtual void LinkActivated(views::Link* source, int event_flags);
  169. // Called by the column picker to pick up any new stat counters that
  170. // may have appeared since last time.
  171. void UpdateStatsCounters();
  172. // Menu::Delegate
  173. virtual void ShowContextMenu(views::View* source,
  174. int x,
  175. int y,
  176. bool is_mouse_gesture);
  177. virtual bool IsItemChecked(int id) const;
  178. virtual void ExecuteCommand(int id);
  179. private:
  180. // Creates the child controls.
  181. void Init();
  182. // Initializes the state of the always-on-top setting as the window is shown.
  183. void InitAlwaysOnTopState();
  184. // Activates the tab associated with the focused row.
  185. void ActivateFocusedTab();
  186. // Adds an always on top item to the window's system menu.
  187. void AddAlwaysOnTopSystemMenuItem();
  188. // Restores saved always on top state from a previous session.
  189. bool GetSavedAlwaysOnTopState(bool* always_on_top) const;
  190. views::NativeButton* kill_button_;
  191. views::Link* about_memory_link_;
  192. views::GroupTableView* tab_table_;
  193. TaskManager* task_manager_;
  194. TaskManagerModel* model_;
  195. // all possible columns, not necessarily visible
  196. std::vector<TableColumn> columns_;
  197. scoped_ptr<TaskManagerTableModel> table_model_;
  198. // True when the Task Manager window should be shown on top of other windows.
  199. bool is_always_on_top_;
  200. // We need to own the text of the menu, the Windows API does not copy it.
  201. std::wstring always_on_top_menu_text_;
  202. // An open Task manager window. There can only be one open at a time. This
  203. // is reset to NULL when the window is closed.
  204. static TaskManagerView* instance_;
  205. DISALLOW_COPY_AND_ASSIGN(TaskManagerView);
  206. };
  207. // static
  208. TaskManagerView* TaskManagerView::instance_ = NULL;
  209. TaskManagerView::TaskManagerView()
  210. : task_manager_(TaskManager::GetInstance()),
  211. model_(TaskManager::GetInstance()->model()),
  212. is_always_on_top_(false) {
  213. Init();
  214. }
  215. TaskManagerView::~TaskManagerView() {
  216. // Delete child views now, while our table model still exists.
  217. RemoveAllChildViews(true);
  218. }
  219. void TaskManagerView::Init() {
  220. table_model_.reset(new TaskManagerTableModel(model_));
  221. columns_.push_back(TableColumn(IDS_TASK_MANAGER_PAGE_COLUMN,
  222. TableColumn::LEFT, -1, 1));
  223. columns_.back().sortable = true;
  224. columns_.push_back(TableColumn(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN,
  225. TableColumn::RIGHT, -1, 0));
  226. columns_.back().sortable = true;
  227. columns_.push_back(TableColumn(IDS_TASK_MANAGER_SHARED_MEM_COLUMN,
  228. TableColumn::RIGHT, -1, 0));
  229. columns_.back().sortable = true;
  230. columns_.push_back(TableColumn(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN,
  231. TableColumn::RIGHT, -1, 0));
  232. columns_.back().sortable = true;
  233. columns_.push_back(TableColumn(IDS_TASK_MANAGER_CPU_COLUMN,
  234. TableColumn::RIGHT, -1, 0));
  235. columns_.back().sortable = true;
  236. columns_.push_back(TableColumn(IDS_TASK_MANAGER_NET_COLUMN,
  237. TableColumn::RIGHT, -1, 0));
  238. columns_.back().sortable = true;
  239. columns_.push_back(TableColumn(IDS_TASK_MANAGER_PROCESS_ID_COLUMN,
  240. TableColumn::RIGHT, -1, 0));
  241. columns_.back().sortable = true;
  242. tab_table_ = new views::GroupTableView(table_model_.get(), columns_,
  243. views::ICON_AND_TEXT, false, true,
  244. true);
  245. // Hide some columns by default
  246. tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PROCESS_ID_COLUMN, false);
  247. tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_SHARED_MEM_COLUMN, false);
  248. tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, false);
  249. UpdateStatsCounters();
  250. TableColumn col(kGoatsTeleportedColumn, L"Goats Teleported",
  251. TableColumn::RIGHT, -1, 0);
  252. col.sortable = true;
  253. columns_.push_back(col);
  254. tab_table_->AddColumn(col);
  255. tab_table_->SetObserver(this);
  256. SetContextMenuController(this);
  257. kill_button_ = new views::NativeButton(
  258. this, l10n_util::GetString(IDS_TASK_MANAGER_KILL));
  259. kill_button_->AddAccelerator(views::Accelerator('E', false, false, false));
  260. kill_button_->SetAccessibleKeyboardShortcut(L"E");
  261. about_memory_link_ = new views::Link(
  262. l10n_util::GetString(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK));
  263. about_memory_link_->SetController(this);
  264. // Makes sure our state is consistent.
  265. OnSelectionChanged();
  266. }
  267. void TaskManagerView::UpdateStatsCounters() {
  268. StatsTable* stats = StatsTable::current();
  269. if (stats != NULL) {
  270. int max = stats->GetMaxCounters();
  271. // skip the first row (it's header data)
  272. for (int i = 1; i < max; i++) {
  273. const char* row = stats->GetRowName(i);
  274. if (row != NULL && row[0] != '\0' && !tab_table_->HasColumn(i)) {
  275. // TODO(erikkay): Use l10n to get display names for stats. Right
  276. // now we're just displaying the internal counter name. Perhaps
  277. // stat names not in the string table would be filtered out.
  278. // TODO(erikkay): Width is hard-coded right now, so many column
  279. // names are clipped.
  280. TableColumn col(i, ASCIIToWide(row), TableColumn::RIGHT, 90, 0);
  281. col.sortable = true;
  282. columns_.push_back(col);
  283. tab_table_->AddColumn(col);
  284. }
  285. }
  286. }
  287. }
  288. void TaskManagerView::ViewHierarchyChanged(bool is_add,
  289. views::View* parent,
  290. views::View* child) {
  291. // Since we want the Kill button and the Memory Details link to show up in
  292. // the same visual row as the close button, which is provided by the
  293. // framework, we must add the buttons to the non-client view, which is the
  294. // parent of this view. Similarly, when we're removed from the view
  295. // hierarchy, we must take care to clean up those items as well.
  296. if (child == this) {
  297. if (is_add) {
  298. parent->AddChildView(about_memory_link_);
  299. parent->AddChildView(kill_button_);
  300. AddChildView(tab_table_);
  301. } else {
  302. parent->RemoveChildView(kill_button_);
  303. parent->RemoveChildView(about_memory_link_);
  304. }
  305. }
  306. }
  307. void TaskManagerView::Layout() {
  308. // kPanelHorizMargin is too big.
  309. const int kTableButtonSpacing = 12;
  310. gfx::Size size = kill_button_->GetPreferredSize();
  311. int prefered_width = size.width();
  312. int prefered_height = size.height();
  313. tab_table_->SetBounds(x() + kPanelHorizMargin,
  314. y() + kPanelVertMargin,
  315. width() - 2 * kPanelHorizMargin,
  316. height() - 2 * kPanelVertMargin - prefered_height);
  317. // y-coordinate of button top left.
  318. gfx::Rect parent_bounds = GetParent()->GetLocalBounds(false);
  319. int y_buttons = parent_bounds.bottom() - prefered_height - kButtonVEdgeMargin;
  320. kill_button_->SetBounds(x() + width() - prefered_width - kPanelHorizMargin,
  321. y_buttons,
  322. prefered_width,
  323. prefered_height);
  324. size = about_memory_link_->GetPreferredSize();
  325. int link_prefered_width = size.width();
  326. int link_prefered_height = size.height();
  327. // center between the two buttons horizontally, and line up with
  328. // bottom of buttons vertically.
  329. int link_y_offset = std::max(0, prefered_height - link_prefered_height) / 2;
  330. about_memory_link_->SetBounds(
  331. x() + kPanelHorizMargin,
  332. y_buttons + prefered_height - link_prefered_height - link_y_offset,
  333. link_prefered_width,
  334. link_prefered_height);
  335. }
  336. gfx::Size TaskManagerView::GetPreferredSize() {
  337. return gfx::Size(kDefaultWidth, kDefaultHeight);
  338. }
  339. // static
  340. void TaskManagerView::Show() {
  341. if (instance_) {
  342. // If there's a Task manager window open already, just activate it.
  343. instance_->window()->Activate();
  344. } else {
  345. instance_ = new TaskManagerView;
  346. views::Window::CreateChromeWindow(NULL, gfx::Rect(), instance_);
  347. instance_->InitAlwaysOnTopState();
  348. instance_->model_->StartUpdating();
  349. instance_->window()->Show();
  350. }
  351. }
  352. // ButtonListener implementation.
  353. void TaskManagerView::ButtonPressed(views::Button* sender) {
  354. DCHECK(sender == kill_button_);
  355. for (views::TableSelectionIterator iter = tab_table_->SelectionBegin();
  356. iter != tab_table_->SelectionEnd(); ++iter) {
  357. task_manager_->KillProcess(*iter);
  358. }
  359. }
  360. // DialogDelegate implementation.
  361. bool TaskManagerView::CanResize() const {
  362. return true;
  363. }
  364. bool TaskManagerView::CanMaximize() const {
  365. return true;
  366. }
  367. bool TaskManagerView::ExecuteWindowsCommand(int command_id) {
  368. if (command_id == IDC_ALWAYS_ON_TOP) {
  369. is_always_on_top_ = !is_always_on_top_;
  370. // Change the menu check state.
  371. HMENU system_menu = GetSystemMenu(GetWindow()->GetNativeWindow(), FALSE);
  372. MENUITEMINFO menu_info;
  373. memset(&menu_info, 0, sizeof(MENUITEMINFO));
  374. menu_info.cbSize = sizeof(MENUITEMINFO);
  375. BOOL r = GetMenuItemInfo(system_menu, IDC_ALWAYS_ON_TOP,
  376. FALSE, &menu_info);
  377. DCHECK(r);
  378. menu_info.fMask = MIIM_STATE;
  379. if (is_always_on_top_)
  380. menu_info.fState = MFS_CHECKED;
  381. r = SetMenuItemInfo(system_menu, IDC_ALWAYS_ON_TOP, FALSE, &menu_info);
  382. // Now change the actual window's behavior.
  383. window()->SetIsAlwaysOnTop(is_always_on_top_);
  384. // Save the state.
  385. if (g_browser_process->local_state()) {
  386. DictionaryValue* window_preferences =
  387. g_browser_process->local_state()->GetMutableDictionary(
  388. GetWindowName().c_str());
  389. window_preferences->SetBoolean(L"always_on_top", is_always_on_top_);
  390. }
  391. return true;
  392. }
  393. return false;
  394. }
  395. std::wstring TaskManagerView::GetWindowTitle() const {
  396. return l10n_util::GetString(IDS_TASK_MANAGER_TITLE);
  397. }
  398. std::wstring TaskManagerView::GetWindowName() const {
  399. return prefs::kTaskManagerWindowPlacement;
  400. }
  401. int TaskManagerView::GetDialogButtons() const {
  402. return MessageBoxFlags::DIALOGBUTTON_NONE;
  403. }
  404. void TaskManagerView::WindowClosing() {
  405. // Now that the window is closed, we can allow a new one to be opened.
  406. instance_ = NULL;
  407. task_manager_->OnWindowClosed();
  408. }
  409. void TaskManagerView::DeleteDelegate() {
  410. ReleaseWindow();
  411. }
  412. views::View* TaskManagerView::GetContentsView() {
  413. return this;
  414. }
  415. // views::TableViewObserver implementation.
  416. void TaskManagerView::OnSelectionChanged() {
  417. bool selection_contains_browser_process = false;
  418. for (views::TableSelectionIterator iter = tab_table_->SelectionBegin();
  419. iter != tab_table_->SelectionEnd(); ++iter) {
  420. if (task_manager_->IsBrowserProcess(*iter)) {
  421. selection_contains_browser_process = true;
  422. break;
  423. }
  424. }
  425. kill_button_->SetEnabled(!selection_contains_browser_process &&
  426. tab_table_->SelectedRowCount() > 0);
  427. }
  428. void TaskManagerView::OnDoubleClick() {
  429. ActivateFocusedTab();
  430. }
  431. void TaskManagerView::OnKeyDown(unsigned short virtual_keycode) {
  432. if (virtual_keycode == VK_RETURN)
  433. ActivateFocusedTab();
  434. }
  435. // views::LinkController implementation
  436. void TaskManagerView::LinkActivated(views::Link* source, int event_flags) {
  437. DCHECK(source == about_memory_link_);
  438. Browser* browser = BrowserList::GetLastActive();
  439. DCHECK(browser);
  440. browser->OpenURL(GURL("about:memory"), GURL(), NEW_FOREGROUND_TAB,
  441. PageTransition::LINK);
  442. // In case the browser window is minimzed, show it. If this is an application
  443. // or popup, we can only have one tab, hence we need to process this in a
  444. // tabbed browser window. Currently, |browser| is pointing to the application,
  445. // popup window. Therefore, we have to retrieve the last active tab again,
  446. // since a new window has been used.
  447. if (browser->type() & Browser::TYPE_APP_POPUP) {
  448. browser = BrowserList::GetLastActive();
  449. DCHECK(browser);
  450. }
  451. browser->window()->Show();
  452. }
  453. void TaskManagerView::ShowContextMenu(views::View* source, int x, int y,
  454. bool is_mouse_gesture) {
  455. UpdateStatsCounters();
  456. scoped_ptr<views::Menu> menu(views::Menu::Create(
  457. this, views::Menu::TOPLEFT, source->GetWidget()->GetNativeView()));
  458. for (std::vector<TableColumn>::iterator i =
  459. columns_.begin(); i != columns_.end(); ++i) {
  460. menu->AppendMenuItem(i->id, i->title, views::Menu::CHECKBOX);
  461. }
  462. menu->RunMenuAt(x, y);
  463. }
  464. bool TaskManagerView::IsItemChecked(int id) const {
  465. return tab_table_->IsColumnVisible(id);
  466. }
  467. void TaskManagerView::ExecuteCommand(int id) {
  468. tab_table_->SetColumnVisibility(id, !tab_table_->IsColumnVisible(id));
  469. }
  470. void TaskManagerView::InitAlwaysOnTopState() {
  471. is_always_on_top_ = false;
  472. if (GetSavedAlwaysOnTopState(&is_always_on_top_))
  473. window()->SetIsAlwaysOnTop(is_always_on_top_);
  474. AddAlwaysOnTopSystemMenuItem();
  475. }
  476. void TaskManagerView::ActivateFocusedTab() {
  477. int row_count = tab_table_->RowCount();
  478. for (int i = 0; i < row_count; ++i) {
  479. if (tab_table_->ItemHasTheFocus(i)) {
  480. task_manager_->ActivateProcess(i);
  481. break;
  482. }
  483. }
  484. }
  485. void TaskManagerView::AddAlwaysOnTopSystemMenuItem() {
  486. // The Win32 API requires that we own the text.
  487. always_on_top_menu_text_ = l10n_util::GetString(IDS_ALWAYS_ON_TOP);
  488. // Let's insert a menu to the window.
  489. HMENU system_menu = ::GetSystemMenu(GetWindow()->GetNativeWindow(), FALSE);
  490. int index = ::GetMenuItemCount(system_menu) - 1;
  491. if (index < 0) {
  492. // Paranoia check.
  493. NOTREACHED();
  494. index = 0;
  495. }
  496. // First we add the separator.
  497. MENUITEMINFO menu_info;
  498. memset(&menu_info, 0, sizeof(MENUITEMINFO));
  499. menu_info.cbSize = sizeof(MENUITEMINFO);
  500. menu_info.fMask = MIIM_FTYPE;
  501. menu_info.fType = MFT_SEPARATOR;
  502. ::InsertMenuItem(system_menu, index, TRUE, &menu_info);
  503. // Then the actual menu.
  504. menu_info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_STATE;
  505. menu_info.fType = MFT_STRING;
  506. menu_info.fState = MFS_ENABLED;
  507. if (is_always_on_top_)
  508. menu_info.fState |= MFS_CHECKED;
  509. menu_info.wID = IDC_ALWAYS_ON_TOP;
  510. menu_info.dwTypeData = const_cast<wchar_t*>(always_on_top_menu_text_.c_str());
  511. ::InsertMenuItem(system_menu, index, TRUE, &menu_info);
  512. }
  513. bool TaskManagerView::GetSavedAlwaysOnTopState(bool* always_on_top) const {
  514. if (!g_browser_process->local_state())
  515. return false;
  516. const DictionaryValue* dictionary =
  517. g_browser_process->local_state()->GetDictionary(GetWindowName().c_str());
  518. return dictionary &&
  519. dictionary->GetBoolean(L"always_on_top", always_on_top) && always_on_top;
  520. }
  521. } // namespace
  522. namespace browser {
  523. // Declared in browser_dialogs.h so others don't need to depend on our header.
  524. void ShowTaskManager() {
  525. TaskManagerView::Show();
  526. }
  527. } // namespace browser