OLD | NEW |
| (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/ash/launcher/browser_launcher_item_controller.
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/tab_helper.h" | |
13 #include "chrome/browser/favicon/favicon_tab_helper.h" | |
14 #include "chrome/browser/profiles/profile.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.h" | |
18 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
19 #include "chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.h" | |
20 #include "chrome/browser/web_applications/web_app.h" | |
21 #include "content/public/browser/web_contents.h" | |
22 #include "grit/ui_resources.h" | |
23 #include "ui/aura/client/aura_constants.h" | |
24 #include "ui/aura/window.h" | |
25 #include "ui/base/resource/resource_bundle.h" | |
26 | |
27 using extensions::Extension; | |
28 | |
29 BrowserLauncherItemController::BrowserLauncherItemController( | |
30 aura::Window* window, | |
31 TabStripModel* tab_model, | |
32 ChromeLauncherController* launcher_controller, | |
33 Type type, | |
34 const std::string& app_id) | |
35 : window_(window), | |
36 tab_model_(tab_model), | |
37 launcher_controller_(launcher_controller), | |
38 type_(type), | |
39 app_id_(app_id), | |
40 is_incognito_(tab_model->profile()->GetOriginalProfile() != | |
41 tab_model->profile() && !Profile::IsGuestSession()), | |
42 item_id_(-1) { | |
43 window_->AddObserver(this); | |
44 } | |
45 | |
46 BrowserLauncherItemController::~BrowserLauncherItemController() { | |
47 tab_model_->RemoveObserver(this); | |
48 window_->RemoveObserver(this); | |
49 if (item_id_ != -1) | |
50 launcher_controller_->LauncherItemClosed(item_id_); | |
51 } | |
52 | |
53 void BrowserLauncherItemController::Init() { | |
54 tab_model_->AddObserver(this); | |
55 ash::LauncherItemStatus app_status = | |
56 ash::wm::IsActiveWindow(window_) ? | |
57 ash::STATUS_ACTIVE : ash::STATUS_RUNNING; | |
58 if (type_ != TYPE_TABBED) { | |
59 item_id_ = launcher_controller_->CreateAppLauncherItem( | |
60 this, app_id_, app_status); | |
61 } else { | |
62 item_id_ = launcher_controller_->CreateTabbedLauncherItem( | |
63 this, | |
64 is_incognito_ ? ChromeLauncherController::STATE_INCOGNITO : | |
65 ChromeLauncherController::STATE_NOT_INCOGNITO, | |
66 app_status); | |
67 } | |
68 // In testing scenarios we can get tab strips with no active contents. | |
69 if (tab_model_->GetActiveTabContents()) | |
70 UpdateLauncher(tab_model_->GetActiveTabContents()); | |
71 } | |
72 | |
73 // static | |
74 BrowserLauncherItemController* BrowserLauncherItemController::Create( | |
75 Browser* browser) { | |
76 // Under testing this can be called before the controller is created. | |
77 if (!ChromeLauncherController::instance()) | |
78 return NULL; | |
79 | |
80 Type type; | |
81 std::string app_id; | |
82 if (browser->type() == Browser::TYPE_TABBED || | |
83 browser->type() == Browser::TYPE_POPUP) { | |
84 type = TYPE_TABBED; | |
85 } else if (browser->is_app()) { | |
86 if (browser->is_type_panel()) { | |
87 if (browser->app_type() == Browser::APP_TYPE_CHILD) | |
88 type = TYPE_EXTENSION_PANEL; | |
89 else | |
90 type = TYPE_APP_PANEL; | |
91 } else { | |
92 type = TYPE_TABBED; | |
93 } | |
94 app_id = web_app::GetExtensionIdFromApplicationName(browser->app_name()); | |
95 } else { | |
96 return NULL; | |
97 } | |
98 BrowserLauncherItemController* icon_updater = | |
99 new BrowserLauncherItemController( | |
100 browser->window()->GetNativeWindow(), browser->tab_strip_model(), | |
101 ChromeLauncherController::instance(), type, app_id); | |
102 icon_updater->Init(); | |
103 return icon_updater; | |
104 } | |
105 | |
106 void BrowserLauncherItemController::BrowserActivationStateChanged() { | |
107 if (tab_model_->GetActiveTabContents()) | |
108 UpdateAppState(tab_model_->GetActiveTabContents()); | |
109 UpdateItemStatus(); | |
110 } | |
111 | |
112 void BrowserLauncherItemController::ActiveTabChanged( | |
113 TabContents* old_contents, | |
114 TabContents* new_contents, | |
115 int index, | |
116 bool user_gesture) { | |
117 // Update immediately on a tab change. | |
118 if (old_contents) | |
119 UpdateAppState(old_contents); | |
120 UpdateAppState(new_contents); | |
121 UpdateLauncher(new_contents); | |
122 } | |
123 | |
124 void BrowserLauncherItemController::TabInsertedAt(TabContents* contents, | |
125 int index, | |
126 bool foreground) { | |
127 UpdateAppState(contents); | |
128 } | |
129 | |
130 void BrowserLauncherItemController::TabDetachedAt(TabContents* contents, | |
131 int index) { | |
132 launcher_controller_->UpdateAppState( | |
133 contents, ChromeLauncherController::APP_STATE_REMOVED); | |
134 } | |
135 | |
136 void BrowserLauncherItemController::TabChangedAt( | |
137 TabContents* tab, | |
138 int index, | |
139 TabStripModelObserver::TabChangeType change_type) { | |
140 UpdateAppState(tab); | |
141 if (index != tab_model_->active_index() || | |
142 !(change_type != TabStripModelObserver::LOADING_ONLY && | |
143 change_type != TabStripModelObserver::TITLE_NOT_LOADING)) { | |
144 return; | |
145 } | |
146 | |
147 if (tab->favicon_tab_helper()->FaviconIsValid() || | |
148 !tab->favicon_tab_helper()->ShouldDisplayFavicon()) { | |
149 // We have the favicon, update immediately. | |
150 UpdateLauncher(tab); | |
151 } else { | |
152 int item_index = launcher_model()->ItemIndexByID(item_id_); | |
153 if (item_index == -1) | |
154 return; | |
155 ash::LauncherItem item = launcher_model()->items()[item_index]; | |
156 item.image = SkBitmap(); | |
157 launcher_model()->Set(item_index, item); | |
158 } | |
159 } | |
160 | |
161 void BrowserLauncherItemController::TabReplacedAt( | |
162 TabStripModel* tab_strip_model, | |
163 TabContents* old_contents, | |
164 TabContents* new_contents, | |
165 int index) { | |
166 launcher_controller_->UpdateAppState( | |
167 old_contents, ChromeLauncherController::APP_STATE_REMOVED); | |
168 UpdateAppState(new_contents); | |
169 } | |
170 | |
171 void BrowserLauncherItemController::FaviconUpdated() { | |
172 UpdateLauncher(tab_model_->GetActiveTabContents()); | |
173 } | |
174 | |
175 void BrowserLauncherItemController::OnWindowPropertyChanged( | |
176 aura::Window* window, | |
177 const void* key, | |
178 intptr_t old) { | |
179 if (key == aura::client::kDrawAttentionKey) | |
180 UpdateItemStatus(); | |
181 } | |
182 | |
183 void BrowserLauncherItemController::UpdateItemStatus() { | |
184 ash::LauncherItemStatus status; | |
185 if (ash::wm::IsActiveWindow(window_)) { | |
186 // Clear attention state if active. | |
187 if (window_->GetProperty(aura::client::kDrawAttentionKey)) | |
188 window_->SetProperty(aura::client::kDrawAttentionKey, false); | |
189 status = ash::STATUS_ACTIVE; | |
190 } else if (window_->GetProperty(aura::client::kDrawAttentionKey)) { | |
191 status = ash::STATUS_ATTENTION; | |
192 } else { | |
193 status = ash::STATUS_RUNNING; | |
194 } | |
195 launcher_controller_->SetItemStatus(item_id_, status); | |
196 } | |
197 | |
198 void BrowserLauncherItemController::UpdateLauncher(TabContents* tab) { | |
199 if (type_ == TYPE_APP_PANEL) | |
200 return; // Maintained entirely by ChromeLauncherController. | |
201 | |
202 if (!tab) | |
203 return; // Assume the window is going to be closed if there are no tabs. | |
204 | |
205 int item_index = launcher_model()->ItemIndexByID(item_id_); | |
206 if (item_index == -1) | |
207 return; | |
208 | |
209 ash::LauncherItem item = launcher_model()->items()[item_index]; | |
210 if (type_ == TYPE_EXTENSION_PANEL) { | |
211 if (!favicon_loader_.get() || | |
212 favicon_loader_->web_contents() != tab->web_contents()) { | |
213 favicon_loader_.reset( | |
214 new LauncherFaviconLoader(this, tab->web_contents())); | |
215 } | |
216 // Update the icon for extension panels. | |
217 SkBitmap new_image = favicon_loader_->GetFavicon(); | |
218 if (new_image.empty() && tab->extension_tab_helper()->GetExtensionAppIcon()) | |
219 new_image = *tab->extension_tab_helper()->GetExtensionAppIcon(); | |
220 // Only update the icon if we have a new image, or none has been set yet. | |
221 // This avoids flickering to an empty image when a pinned app is opened. | |
222 if (!new_image.empty()) | |
223 item.image = new_image; | |
224 else if (item.image.empty()) | |
225 item.image = extensions::Extension::GetDefaultIcon(true); | |
226 } else { | |
227 DCHECK_EQ(TYPE_TABBED, type_); | |
228 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
229 if (tab->favicon_tab_helper()->ShouldDisplayFavicon()) { | |
230 item.image = tab->favicon_tab_helper()->GetFavicon().AsBitmap(); | |
231 if (item.image.empty()) { | |
232 item.image = *rb.GetBitmapNamed(IDR_DEFAULT_FAVICON); | |
233 } | |
234 } else { | |
235 item.image = *rb.GetBitmapNamed(IDR_DEFAULT_FAVICON); | |
236 } | |
237 } | |
238 launcher_model()->Set(item_index, item); | |
239 } | |
240 | |
241 void BrowserLauncherItemController::UpdateAppState(TabContents* tab) { | |
242 ChromeLauncherController::AppState app_state; | |
243 | |
244 if (tab_model_->GetIndexOfTabContents(tab) == TabStripModel::kNoTab) { | |
245 app_state = ChromeLauncherController::APP_STATE_REMOVED; | |
246 } else if (tab_model_->GetActiveTabContents() == tab) { | |
247 if (ash::wm::IsActiveWindow(window_)) | |
248 app_state = ChromeLauncherController::APP_STATE_WINDOW_ACTIVE; | |
249 else | |
250 app_state = ChromeLauncherController::APP_STATE_ACTIVE; | |
251 } else { | |
252 app_state = ChromeLauncherController::APP_STATE_INACTIVE; | |
253 } | |
254 launcher_controller_->UpdateAppState(tab, app_state); | |
255 } | |
256 | |
257 ash::LauncherModel* BrowserLauncherItemController::launcher_model() { | |
258 return launcher_controller_->model(); | |
259 } | |
OLD | NEW |