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

Side by Side Diff: chrome/browser/ui/views/aura/launcher/launcher_updater.cc

Issue 9570044: Rename chrome/browser/ui/views/{aura => ash}/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 years, 9 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/views/aura/launcher/launcher_updater.h"
6
7 #include "ash/launcher/launcher.h"
8 #include "ash/launcher/launcher_model.h"
9 #include "ash/shell.h"
10 #include "ash/wm/window_util.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_tab_helper.h"
13 #include "chrome/browser/favicon/favicon_tab_helper.h"
14 #include "chrome/browser/tabs/tab_strip_model.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_window.h"
17 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
18 #include "chrome/browser/ui/views/aura/launcher/chrome_launcher_delegate.h"
19 #include "chrome/browser/web_applications/web_app.h"
20 #include "content/public/browser/web_contents.h"
21 #include "grit/ui_resources.h"
22 #include "ui/aura/window.h"
23 #include "ui/base/resource/resource_bundle.h"
24
25 LauncherUpdater::AppTabDetails::AppTabDetails() : id(0) {
26 }
27
28 LauncherUpdater::AppTabDetails::~AppTabDetails() {
29 }
30
31 LauncherUpdater::LauncherUpdater(aura::Window* window,
32 TabStripModel* tab_model,
33 ChromeLauncherDelegate* delegate,
34 Type type,
35 const std::string& app_id)
36 : window_(window),
37 tab_model_(tab_model),
38 launcher_delegate_(delegate),
39 type_(type),
40 app_id_(app_id),
41 item_id_(-1) {
42 }
43
44 LauncherUpdater::~LauncherUpdater() {
45 tab_model_->RemoveObserver(this);
46 if (item_id_ != -1)
47 launcher_delegate_->LauncherItemClosed(item_id_);
48 for (AppTabMap::iterator i = app_map_.begin(); i != app_map_.end(); ++i)
49 launcher_delegate_->LauncherItemClosed(i->second.id);
50 }
51
52 void LauncherUpdater::Init() {
53 tab_model_->AddObserver(this);
54 if (type_ == TYPE_APP) {
55 // App type never changes, create the launcher item immediately.
56 item_id_ = launcher_delegate_->CreateAppLauncherItem(
57 this, app_id_, ChromeLauncherDelegate::APP_TYPE_WINDOW);
58 } else {
59 // Determine if we have any tabs that should get launcher items.
60 std::vector<TabContentsWrapper*> app_tabs;
61 for (int i = 0; i < tab_model_->count(); ++i) {
62 TabContentsWrapper* tab = tab_model_->GetTabContentsAt(i);
63 if (!launcher_delegate_->GetAppID(tab).empty())
64 app_tabs.push_back(tab);
65 }
66
67 if (static_cast<int>(app_tabs.size()) != tab_model_->count())
68 CreateTabbedItem();
69
70 // Create items for the app tabs.
71 for (size_t i = 0; i < app_tabs.size(); ++i)
72 AddAppItem(app_tabs[i]);
73 }
74 UpdateLauncher(tab_model_->GetActiveTabContents());
75 }
76
77 // static
78 LauncherUpdater* LauncherUpdater::Create(Browser* browser) {
79 Type type;
80 std::string app_id;
81 if (browser->type() == Browser::TYPE_TABBED) {
82 type = TYPE_TABBED;
83 } else if (browser->is_app()) {
84 type = TYPE_APP;
85 app_id = web_app::GetExtensionIdFromApplicationName(browser->app_name());
86 } else {
87 return NULL;
88 }
89 LauncherUpdater* icon_updater = new LauncherUpdater(
90 browser->window()->GetNativeHandle(), browser->tabstrip_model(),
91 ChromeLauncherDelegate::instance(), type, app_id);
92 icon_updater->Init();
93 return icon_updater;
94 }
95
96 TabContentsWrapper* LauncherUpdater::GetTab(ash::LauncherID id) {
97 for (AppTabMap::const_iterator i = app_map_.begin(); i != app_map_.end();
98 ++i) {
99 if (i->second.id == id)
100 return i->first;
101 }
102 return NULL;
103 }
104
105 void LauncherUpdater::ActiveTabChanged(TabContentsWrapper* old_contents,
106 TabContentsWrapper* new_contents,
107 int index,
108 bool user_gesture) {
109 // Update immediately on a tab change.
110 UpdateLauncher(new_contents);
111 }
112
113 void LauncherUpdater::TabChangedAt(
114 TabContentsWrapper* tab,
115 int index,
116 TabStripModelObserver::TabChangeType change_type) {
117 if (type_ == TYPE_TABBED &&
118 (change_type == TabStripModelObserver::LOADING_ONLY ||
119 change_type == TabStripModelObserver::ALL)) {
120 UpdateAppTabState(tab, UPDATE_TAB_CHANGED);
121 }
122
123 if (index != tab_model_->active_index() ||
124 !(change_type != TabStripModelObserver::LOADING_ONLY &&
125 change_type != TabStripModelObserver::TITLE_NOT_LOADING)) {
126 return;
127 }
128
129 if (tab->favicon_tab_helper()->FaviconIsValid()) {
130 // We have the favicon, update immediately.
131 UpdateLauncher(tab);
132 } else {
133 // Let the model know we're waiting. We delay updating as otherwise the user
134 // sees flicker as we fetch the favicon.
135 int item_index = launcher_model()->ItemIndexByID(item_id_);
136 if (item_index == -1)
137 return;
138 launcher_model()->SetPendingUpdate(item_index);
139 }
140 }
141
142 void LauncherUpdater::TabInsertedAt(TabContentsWrapper* contents,
143 int index,
144 bool foreground) {
145 if (type_ == TYPE_APP)
146 return;
147
148 UpdateAppTabState(contents, UPDATE_TAB_INSERTED);
149 }
150
151 void LauncherUpdater::TabReplacedAt(TabStripModel* tab_strip_model,
152 TabContentsWrapper* old_contents,
153 TabContentsWrapper* new_contents,
154 int index) {
155 AppTabMap::iterator i = app_map_.find(old_contents);
156 if (i != app_map_.end()) {
157 AppTabDetails details = i->second;
158 app_map_.erase(i);
159 i = app_map_.end();
160 app_map_[new_contents] = details;
161 UpdateAppTabState(new_contents, UPDATE_TAB_CHANGED);
162 }
163 }
164
165 void LauncherUpdater::TabDetachedAt(TabContentsWrapper* contents, int index) {
166 if (type_ == TYPE_APP)
167 return;
168
169 UpdateAppTabState(contents, UPDATE_TAB_REMOVED);
170 if (tab_model_->count() <= 3) {
171 // We can't rely on the active tab at this point as the model hasn't fully
172 // adjusted itself. We can rely on the count though.
173 int item_index = launcher_model()->ItemIndexByID(item_id_);
174 if (item_index == -1)
175 return;
176
177 if (launcher_model()->items()[item_index].type == ash::TYPE_TABBED) {
178 ash::LauncherItem new_item(launcher_model()->items()[item_index]);
179 new_item.num_tabs = tab_model_->count();
180 launcher_model()->Set(item_index, new_item);
181 }
182 }
183 }
184
185 void LauncherUpdater::UpdateLauncher(TabContentsWrapper* tab) {
186 if (type_ == TYPE_APP)
187 return; // TYPE_APP is entirely maintained by ChromeLauncherDelegate.
188
189 if (!tab)
190 return; // Assume the window is going to be closed if there are no tabs.
191
192 int item_index = launcher_model()->ItemIndexByID(item_id_);
193 if (item_index == -1)
194 return;
195
196 ash::LauncherItem item;
197 if (launcher_model()->items()[item_index].type == ash::TYPE_APP) {
198 // Use the app icon if we can.
199 if (tab->extension_tab_helper()->GetExtensionAppIcon())
200 item.image = *tab->extension_tab_helper()->GetExtensionAppIcon();
201 else
202 item.image = tab->favicon_tab_helper()->GetFavicon();
203 } else {
204 item.num_tabs = tab_model_->count();
205 if (tab->favicon_tab_helper()->ShouldDisplayFavicon()) {
206 item.image = tab->favicon_tab_helper()->GetFavicon();
207 if (item.image.empty()) {
208 item.image = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
209 IDR_DEFAULT_FAVICON);
210 }
211 }
212 }
213 launcher_model()->Set(item_index, item);
214 }
215
216 void LauncherUpdater::UpdateAppTabState(TabContentsWrapper* tab,
217 UpdateType update_type) {
218 bool showing_app_item = app_map_.find(tab) != app_map_.end();
219 std::string app_id = update_type == UPDATE_TAB_REMOVED ?
220 std::string() : launcher_delegate_->GetAppID(tab);
221 bool show_app = !app_id.empty();
222 if (showing_app_item == show_app) {
223 if (!show_app) {
224 if (item_id_ == -1 && update_type == UPDATE_TAB_INSERTED) {
225 // A new non-app tab was added and we have no app tabs. Add one now.
226 CreateTabbedItem();
227 } else if (item_id_ != -1 && update_type == UPDATE_TAB_REMOVED &&
228 tab_model_->count() == (static_cast<int>(app_map_.size()))) {
229 launcher_delegate_->LauncherItemClosed(item_id_);
230 item_id_ = -1;
231 }
232 return;
233 }
234
235 if (app_id != app_map_[tab].app_id) {
236 // The extension changed.
237 app_map_[tab].app_id = app_id;
238 launcher_delegate_->AppIDChanged(app_map_[tab].id, app_id);
239 }
240 return;
241 }
242
243 if (showing_app_item) {
244 // Going from showing to not showing.
245 ash::LauncherID launcher_id(app_map_[tab].id);
246 app_map_.erase(tab);
247 int model_index = launcher_model()->ItemIndexByID(launcher_id);
248 DCHECK_NE(-1, model_index);
249 if (item_id_ == -1 &&
250 (update_type != UPDATE_TAB_REMOVED ||
251 (tab_model_->count() != 1 &&
252 tab_model_->count() == (static_cast<int>(app_map_.size()) + 1)))) {
253 if (!launcher_delegate_->IsPinned(launcher_id)) {
254 // Swap the item for a tabbed item.
255 item_id_ = launcher_id;
256 launcher_delegate_->ConvertAppToTabbed(item_id_);
257 } else {
258 // If the app is pinned we have to leave it and create a new tabbed
259 // item.
260 launcher_delegate_->LauncherItemClosed(launcher_id);
261 CreateTabbedItem();
262 }
263 ash::LauncherItem item(ash::TYPE_TABBED);
264 item.num_tabs = tab_model_->count();
265 launcher_model()->Set(launcher_model()->ItemIndexByID(item_id_), item);
266 } else {
267 // We have a tabbed item, so we can remove the the app item.
268 launcher_delegate_->LauncherItemClosed(launcher_id);
269 }
270 } else {
271 // Going from not showing to showing.
272 if (item_id_ != -1 &&
273 static_cast<int>(app_map_.size()) + 1 == tab_model_->count()) {
274 if (launcher_delegate_->HasClosedAppItem(
275 launcher_delegate_->GetAppID(tab),
276 ChromeLauncherDelegate::APP_TYPE_TAB)) {
277 // There's a closed item we can use. Close the tabbed item and add an
278 // app item, which will end up using the closed item.
279 launcher_delegate_->LauncherItemClosed(item_id_);
280 AddAppItem(tab);
281 } else {
282 // All the tabs are app tabs, replace the tabbed item with the app.
283 launcher_delegate_->ConvertTabbedToApp(
284 item_id_,
285 launcher_delegate_->GetAppID(tab),
286 ChromeLauncherDelegate::APP_TYPE_TAB);
287 RegisterAppItem(item_id_, tab);
288 }
289 item_id_ = -1;
290 } else {
291 AddAppItem(tab);
292 }
293 }
294 }
295
296 void LauncherUpdater::AddAppItem(TabContentsWrapper* tab) {
297 ash::LauncherID id = launcher_delegate_->CreateAppLauncherItem(
298 this,
299 launcher_delegate_->GetAppID(tab),
300 ChromeLauncherDelegate::APP_TYPE_TAB);
301 RegisterAppItem(id, tab);
302 }
303
304 void LauncherUpdater::RegisterAppItem(ash::LauncherID id,
305 TabContentsWrapper* tab) {
306 AppTabDetails details;
307 details.id = id;
308 details.app_id = launcher_delegate_->GetAppID(tab);
309 app_map_[tab] = details;
310 }
311
312 void LauncherUpdater::CreateTabbedItem() {
313 DCHECK_EQ(-1, item_id_);
314 item_id_ = launcher_delegate_->CreateTabbedLauncherItem(this);
315 }
316
317 bool LauncherUpdater::ContainsID(ash::LauncherID id, TabContentsWrapper** tab) {
318 if (item_id_ == id)
319 return true;
320 for (AppTabMap::const_iterator i = app_map_.begin(); i != app_map_.end();
321 ++i) {
322 if (i->second.id == id) {
323 *tab = i->first;
324 return true;
325 }
326 }
327 return false;
328 }
329
330 ash::LauncherModel* LauncherUpdater::launcher_model() {
331 return launcher_delegate_->model();
332 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698