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

Side by Side Diff: chrome/browser/ui/search/other_device_menu_controller.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: Fix dumb typo. Created 8 years, 1 month 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_controller.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 "webkit/glue/window_open_disposition.h"
20
21 namespace {
22
23 // The max number of tabs that will be added to the menu.
24 const size_t kMaxTabsToShow = 18;
25
26 // The max width of a menu. Menu text exceeding this will be elided.
27 const int kMaxWidth = 375;
28
29 // Enumerates the different menu item types.
30 enum ItemType {
31 // An item for restoring a single tab.
32 TAB,
33 // An item for restoring all tabs in this session.
34 OPEN_ALL,
35 // Number of enum entries, used for UMA histogram reporting macros.
36 ITEM_TYPE_ENUM_COUNT,
37 };
38
39 // Helper function that returns the largest tab timestamp for the window.
40 double GetMostRecentTabTimestamp(const SessionWindow* window) {
41 double max_timestamp = 0;
42 for (size_t i = 0, num_tabs = window->tabs.size(); i < num_tabs; ++i) {
43 linked_ptr<DictionaryValue> tab_value =
44 linked_ptr<DictionaryValue>(new DictionaryValue());
45 if (browser_sync::ForeignSessionHandler::SessionTabToValue(
46 *window->tabs[i], tab_value.get())) {
47 double timestamp;
48 tab_value->GetDouble("timestamp", &timestamp);
49 if (timestamp > max_timestamp)
50 max_timestamp = timestamp;
51 }
52 }
53 return max_timestamp;
54 }
55
56 // Comparator function to sort windows by last-modified time. Windows in a
57 // session share the same timestamp, so we need to use tab timestamps instead.
58 // instead.
59 bool SortWindowsByRecency(const SessionWindow* w1, const SessionWindow* w2) {
60 return GetMostRecentTabTimestamp(w1) > GetMostRecentTabTimestamp(w2);
61 }
62
63 } // namespace
64
65 OtherDeviceMenuController::OtherDeviceMenuController(
66 content::WebUI* web_ui,
67 const std::string& session_id,
68 const gfx::Point& location)
69 : web_ui_(web_ui),
70 session_id_(session_id),
71 location_(location),
72 ALLOW_THIS_IN_INITIALIZER_LIST(menu_model_(this)) {
73
74 // Initialize the model.
75 AddDeviceTabs();
76
77 // Add a "Open all" menu item if there is more than one tab.
78 if (!tab_data_.empty()) {
79 linked_ptr<DictionaryValue> open_all_tab_value =
80 linked_ptr<DictionaryValue>(new DictionaryValue());
81 // kInvalidId signifies that the entire session should be opened.
82 open_all_tab_value->SetInteger(
83 "sessionId",
84 browser_sync::ForeignSessionHandler::kInvalidId);
85 open_all_tab_value->SetInteger(
86 "windowId",
87 browser_sync::ForeignSessionHandler::kInvalidId);
88 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
89 menu_model_.AddItem(
90 tab_data_.size(),
91 l10n_util::GetStringUTF16(IDS_NEW_TAB_OTHER_SESSIONS_OPEN_ALL));
92 tab_data_.push_back(open_all_tab_value);
93 }
94
95 // Create the view.
96 view_.reset(OtherDeviceMenu::Create(&menu_model_));
97 }
98
99 OtherDeviceMenuController::~OtherDeviceMenuController() {
100 }
101
102 void OtherDeviceMenuController::ShowMenu() {
103 content::WebContents* web_contents = web_ui_->GetWebContents();
104 Browser* browser = browser::FindBrowserWithWebContents(web_contents);
105 if (!browser)
106 return;
107
108 view_->ShowMenu(browser->window()->GetNativeWindow(), location_);
109 }
110
111 bool OtherDeviceMenuController::IsCommandIdChecked(int command_id) const {
112 return false;
113 }
114
115 bool OtherDeviceMenuController::IsCommandIdEnabled(int command_id) const {
116 return true;
117 }
118
119 void OtherDeviceMenuController::ExecuteCommand(int command_id) {
120 ExecuteCommand(command_id, 0);
121 }
122
123 // TODO(jeremycho): Figure out why mouse wheel clicks don't trigger this.
124 void OtherDeviceMenuController::ExecuteCommand(int command_id,
125 int event_flags) {
126 DCHECK_GT(tab_data_.size(), static_cast<size_t>(command_id)) <<
127 "Invalid command_id from other device menu.";
128
129 linked_ptr<DictionaryValue> tab_data = tab_data_[command_id];
130 // This is not a mistake - sessionId actually refers to the tab id.
131 // See http://crbug.com/154865.
132 int tab_id = browser_sync::ForeignSessionHandler::kInvalidId;
133 tab_data->GetInteger("sessionId", &tab_id);
134
135 int window_id = browser_sync::ForeignSessionHandler::kInvalidId;
136 tab_data->GetInteger("windowId", &window_id);
137
138 WindowOpenDisposition disposition =
139 chrome::DispositionFromEventFlags(event_flags);
140 browser_sync::ForeignSessionHandler::OpenForeignSession(
141 web_ui_, session_id_, window_id, tab_id, disposition);
142
143 ItemType itemType = tab_id ==
144 browser_sync::ForeignSessionHandler::kInvalidId ? OPEN_ALL : TAB;
145 UMA_HISTOGRAM_ENUMERATION("NewTabPage.OtherDeviceMenu",
146 itemType, ITEM_TYPE_ENUM_COUNT);
147 }
148
149 bool OtherDeviceMenuController::GetAcceleratorForCommandId(
150 int command_id,
151 ui::Accelerator* accelerator) {
152 return false;
153 }
154
155 void OtherDeviceMenuController::AddDeviceTabs() {
156 browser_sync::SessionModelAssociator* associator =
157 browser_sync::ForeignSessionHandler::GetModelAssociator(web_ui_);
158 std::vector<const SessionWindow*> windows;
159
160 // Populate the menu with the device's tabs, using separators between windows.
161 if (associator && associator->GetForeignSession(session_id_, &windows)) {
162 // Show windows by descending last-modified time.
163 std::sort(windows.begin(), windows.end(), SortWindowsByRecency);
164 bool last_window_has_tabs = false;
165 for (std::vector<const SessionWindow*>::const_iterator it =
166 windows.begin(); it != windows.end(); ++it) {
167 if (last_window_has_tabs)
168 menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
169 last_window_has_tabs = false;
170
171 const SessionWindow* window = *it;
172 for (size_t i = 0, num_tabs = window->tabs.size(); i < num_tabs; ++i) {
173 linked_ptr<DictionaryValue> tab_value =
174 linked_ptr<DictionaryValue>(new DictionaryValue());
175 if (!browser_sync::ForeignSessionHandler::SessionTabToValue(
176 *window->tabs[i], tab_value.get())) {
177 continue;
178 }
179 last_window_has_tabs = true;
180 tab_value->SetInteger("windowId", window->window_id.id());
181 string16 title;
182 tab_value->GetString("title", &title);
183 title = ui::ElideText(
184 title, gfx::Font(), kMaxWidth, ui::ELIDE_AT_END);
185 menu_model_.AddItem(tab_data_.size(), title);
186 // TODO(jeremycho): Use tab_value.GetString("url", &url) to request
187 // favicons. http://crbug.com/153410.
188 tab_data_.push_back(tab_value);
189 if (tab_data_.size() >= kMaxTabsToShow)
190 return;
191 }
192 }
193 }
194 }
195
196 // OtherDevice menu ----------------------------------------------------------
197
198 OtherDeviceMenu::~OtherDeviceMenu() {}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698