Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(442)

Side by Side Diff: chrome/browser/ui/search/other_device_menu.cc

Issue 11009013: NTP5: Starting implementation of a native menu for showing other device sessions. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Respond to comments. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/search/other_device_menu.h"
6
7 #include "base/metrics/histogram.h"
8 #include "base/string16.h"
9 #include "chrome/browser/sync/glue/session_model_associator.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/browser_finder.h"
12 #include "chrome/browser/ui/browser_window.h"
13 #include "chrome/browser/ui/webui/ntp/foreign_session_handler.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/browser/web_ui.h"
16 #include "grit/generated_resources.h"
17 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/base/text/text_elider.h"
19 #include "ui/views/controls/menu/menu_model_adapter.h"
20 #include "ui/views/controls/menu/menu_runner.h"
21 #include "ui/views/widget/widget.h"
22 #include "webkit/glue/window_open_disposition.h"
23
24 // The max number of tabs that will be added to the menu.
25 static const size_t kMaxTabsToShow = 18;
26
27 // The max width of a menu. Menu text exceeding this will be elided.
28 static const int kMaxWidth = 375;
29
30 namespace {
31
32 // Enumerates the different menu item types.
33 enum ItemType {
34 // An item for restoring a single tab.
35 TAB,
36 // An item for restoring all tabs in this session.
37 OPEN_ALL,
38 // Number of enum entries, used for UMA histogram reporting macros.
39 ITEM_TYPE_ENUM_COUNT,
40 };
41
42 // Helper function that returns the largest tab timestamp for the window.
43 double getMaxTabTimestamp(const SessionWindow* window) {
dhollowa 2012/10/09 20:04:36 nit: Mixed case not camel-case on functions: GetMa
jeremycho 2012/10/09 20:31:05 Done.
44 double max_timestamp = 0;
45 for (size_t i = 0; i < window->tabs.size(); ++i) {
46 linked_ptr<DictionaryValue> tab_value =
47 linked_ptr<DictionaryValue>(new DictionaryValue());
48 if (browser_sync::ForeignSessionHandler::SessionTabToValue(
49 *window->tabs[i], tab_value.get())) {
50 double timestamp;
51 tab_value->GetDouble("timestamp", &timestamp);
52 if (timestamp > max_timestamp)
53 max_timestamp = timestamp;
54 }
55 }
56 return max_timestamp;
57 }
58
59 // Comparator function to sort windows by last-modified time. Windows in a
60 // session share the same timestamp, so we need to use tab timestamps instead.
61 // instead.
62 bool SortWindowsByRecency(const SessionWindow* w1, const SessionWindow* w2) {
63 return getMaxTabTimestamp(w1) > getMaxTabTimestamp(w2);
64 }
65
66 } // namespace
67
68 OtherDeviceMenu::OtherDeviceMenu(content::WebUI* web_ui,
69 const std::string& session_id,
70 const gfx::Point& location) :
71 web_ui_(web_ui), session_id_(session_id), location_(location),
72 ALLOW_THIS_IN_INITIALIZER_LIST(menu_model_(this)) {
73 AddDeviceTabs();
74
75 // Add a "Open all" menu item if there is more than one tab.
76 if (tab_data_.size() > 1) {
77 linked_ptr<DictionaryValue> open_all_tab_value =
78 linked_ptr<DictionaryValue>(new DictionaryValue());
79 // kInvalidId signifies that the entire session should be opened.
80 open_all_tab_value->SetInteger(
81 "sessionId",
82 browser_sync::ForeignSessionHandler::kInvalidId);
83 open_all_tab_value->SetInteger(
84 "windowId",
85 browser_sync::ForeignSessionHandler::kInvalidId);
86 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
87 menu_model_.AddItem(
88 tab_data_.size(),
89 l10n_util::GetStringUTF16(IDS_NEW_TAB_OTHER_SESSIONS_OPEN_ALL));
90 tab_data_.push_back(open_all_tab_value);
91 }
92 }
93
94 OtherDeviceMenu::~OtherDeviceMenu() {
95 }
96
97 void OtherDeviceMenu::ShowMenu() {
98 content::WebContents* web_contents = web_ui_->GetWebContents();
99 Browser* browser = browser::FindBrowserWithWebContents(web_contents);
100 if (!browser)
101 return;
102
103 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(
104 browser->window()->GetNativeWindow());
105 if (!widget)
106 return;
107
108 views::MenuModelAdapter menu_model_adapter(&menu_model_);
109 menu_runner_.reset(new views::MenuRunner(menu_model_adapter.CreateMenu()));
110
111 if (menu_runner_->RunMenuAt(widget, NULL, gfx::Rect(location_, gfx::Size()),
112 views::MenuItemView::TOPLEFT, 0) ==
113 views::MenuRunner::MENU_DELETED)
114 return;
115 }
116
117 bool OtherDeviceMenu::IsCommandIdChecked(int command_id) const {
118 return false;
119 }
120
121 bool OtherDeviceMenu::IsCommandIdEnabled(int command_id) const {
122 return true;
123 }
124
125 void OtherDeviceMenu::ExecuteCommand(int command_id) {
126 ExecuteCommand(command_id, 0);
127 }
128
129 // TODO(jeremycho): Figure out why mouse wheel clicks don't trigger this.
130 void OtherDeviceMenu::ExecuteCommand(int command_id, int event_flags) {
131 DCHECK_GT(tab_data_.size(), static_cast<size_t>(command_id)) <<
132 "Invalid command_id from other device menu.";
133
134 linked_ptr<DictionaryValue> tab_data = tab_data_[command_id];
135 // This is not a mistake - sessionId actually refers to the tab id.
136 // See http://crbug.com/154865.
137 int tab_id = browser_sync::ForeignSessionHandler::kInvalidId;
138 tab_data->GetInteger("sessionId", &tab_id);
139
140 int window_id = browser_sync::ForeignSessionHandler::kInvalidId;
141 tab_data->GetInteger("windowId", &window_id);
142
143 WindowOpenDisposition disposition =
144 chrome::DispositionFromEventFlags(event_flags);
145 browser_sync::ForeignSessionHandler::OpenForeignSession(
146 web_ui_, session_id_, window_id, tab_id, disposition);
147
148 ItemType itemType =
149 tab_id == browser_sync::ForeignSessionHandler::kInvalidId ?
150 OPEN_ALL : TAB;
dhollowa 2012/10/09 20:04:36 nit: indent
jeremycho 2012/10/09 20:31:05 Done.
151 UMA_HISTOGRAM_ENUMERATION("NewTabPage.OtherDeviceMenu",
152 itemType, ITEM_TYPE_ENUM_COUNT);
153 }
154
155 bool OtherDeviceMenu::GetAcceleratorForCommandId(
156 int command_id,
157 ui::Accelerator* accelerator) {
158 return false;
159 }
160
161 void OtherDeviceMenu::AddDeviceTabs() {
162 browser_sync::SessionModelAssociator* associator =
163 browser_sync::ForeignSessionHandler::GetModelAssociator(web_ui_);
164 std::vector<const SessionWindow*> windows;
165
166 // Populate the menu with the device's tabs, using separators between windows.
167 if (associator && associator->GetForeignSession(session_id_, &windows)) {
168 // Show windows by descending last-modified time.
169 std::sort(windows.begin(), windows.end(), SortWindowsByRecency);
170 bool last_window_has_tabs = false;
171 for (std::vector<const SessionWindow*>::const_iterator it =
172 windows.begin(); it != windows.end(); ++it) {
173 if (last_window_has_tabs)
174 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
175 last_window_has_tabs = false;
176
177 const SessionWindow* window = *it;
178 for (size_t i = 0; i < window->tabs.size(); ++i) {
179 linked_ptr<DictionaryValue> tab_value =
180 linked_ptr<DictionaryValue>(new DictionaryValue());
181 if (browser_sync::ForeignSessionHandler::SessionTabToValue(
182 *window->tabs[i], tab_value.get())) {
183 last_window_has_tabs = true;
184 tab_value->SetInteger("windowId", window->window_id.id());
185 string16 title;
186 tab_value->GetString("title", &title);
187 title = ui::ElideText(
188 title, gfx::Font(), kMaxWidth, ui::ELIDE_AT_END);
189 menu_model_.AddItem(tab_data_.size(), title);
190 // TODO(jeremycho): Use tab_value.GetString("url", &url) to
191 // request favicons. http://crbug.com/153410.
192 tab_data_.push_back(tab_value);
193 if (tab_data_.size() >= kMaxTabsToShow)
194 return;
195 }
196 }
197 }
198 }
199 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/search/other_device_menu.h ('k') | chrome/browser/ui/webui/ntp/foreign_session_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698