| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/views/location_bar_view.h" | 5 #include "chrome/browser/views/location_bar_view.h" |
| 6 | 6 |
| 7 #if defined(OS_LINUX) | 7 #if defined(OS_LINUX) |
| 8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| 11 #include "build/build_config.h" | 11 #include "build/build_config.h" |
| 12 | 12 |
| 13 #include "app/gfx/canvas.h" | 13 #include "app/gfx/canvas.h" |
| 14 #include "app/gfx/color_utils.h" | 14 #include "app/gfx/color_utils.h" |
| 15 #include "app/gfx/favicon_size.h" | |
| 16 #include "app/l10n_util.h" | 15 #include "app/l10n_util.h" |
| 17 #include "app/resource_bundle.h" | 16 #include "app/resource_bundle.h" |
| 18 #include "base/file_util.h" | 17 #include "base/file_util.h" |
| 19 #include "base/keyboard_codes.h" | 18 #include "base/keyboard_codes.h" |
| 20 #include "base/path_service.h" | 19 #include "base/path_service.h" |
| 21 #include "base/string_util.h" | 20 #include "base/string_util.h" |
| 22 #include "chrome/app/chrome_dll_resource.h" | 21 #include "chrome/app/chrome_dll_resource.h" |
| 23 #include "chrome/browser/alternate_nav_url_fetcher.h" | 22 #include "chrome/browser/alternate_nav_url_fetcher.h" |
| 24 #include "chrome/browser/browser.h" | 23 #include "chrome/browser/browser.h" |
| 25 #include "chrome/browser/browser_list.h" | 24 #include "chrome/browser/browser_list.h" |
| 26 #include "chrome/browser/browser_process.h" | |
| 27 #include "chrome/browser/command_updater.h" | 25 #include "chrome/browser/command_updater.h" |
| 28 #include "chrome/browser/extensions/extension_browser_event_router.h" | 26 #include "chrome/browser/extensions/extension_browser_event_router.h" |
| 29 #include "chrome/browser/extensions/extension_tabs_module.h" | 27 #include "chrome/browser/extensions/extension_tabs_module.h" |
| 30 #include "chrome/browser/extensions/extensions_service.h" | 28 #include "chrome/browser/extensions/extensions_service.h" |
| 31 #include "chrome/browser/page_info_window.h" | 29 #include "chrome/browser/page_info_window.h" |
| 32 #include "chrome/browser/profile.h" | 30 #include "chrome/browser/profile.h" |
| 33 #include "chrome/browser/search_engines/template_url.h" | 31 #include "chrome/browser/search_engines/template_url.h" |
| 34 #include "chrome/browser/search_engines/template_url_model.h" | 32 #include "chrome/browser/search_engines/template_url_model.h" |
| 35 #include "chrome/browser/tab_contents/navigation_entry.h" | 33 #include "chrome/browser/tab_contents/navigation_entry.h" |
| 36 #include "chrome/browser/view_ids.h" | 34 #include "chrome/browser/view_ids.h" |
| 37 #include "chrome/browser/views/info_bubble.h" | 35 #include "chrome/browser/views/info_bubble.h" |
| 38 #include "chrome/common/extensions/extension.h" | 36 #include "chrome/common/extensions/extension.h" |
| 39 #include "chrome/common/page_action.h" | 37 #include "chrome/common/page_action.h" |
| 40 #include "grit/generated_resources.h" | 38 #include "grit/generated_resources.h" |
| 41 #include "grit/theme_resources.h" | 39 #include "grit/theme_resources.h" |
| 42 #include "skia/ext/image_operations.h" | |
| 43 #include "views/focus/focus_manager.h" | 40 #include "views/focus/focus_manager.h" |
| 44 #include "views/widget/root_view.h" | 41 #include "views/widget/root_view.h" |
| 45 #include "views/widget/widget.h" | 42 #include "views/widget/widget.h" |
| 46 #include "webkit/glue/image_decoder.h" | |
| 47 | 43 |
| 48 #if defined(OS_WIN) | 44 #if defined(OS_WIN) |
| 49 #include "app/win_util.h" | 45 #include "app/win_util.h" |
| 50 #include "chrome/browser/views/first_run_bubble.h" | 46 #include "chrome/browser/views/first_run_bubble.h" |
| 51 #endif | 47 #endif |
| 52 | 48 |
| 53 using views::View; | 49 using views::View; |
| 54 | 50 |
| 55 // static | 51 // static |
| 56 const int LocationBarView::kVertMargin = 2; | 52 const int LocationBarView::kVertMargin = 2; |
| (...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 void LocationBarView::DeletePageActionViews() { | 646 void LocationBarView::DeletePageActionViews() { |
| 651 if (!page_action_image_views_.empty()) { | 647 if (!page_action_image_views_.empty()) { |
| 652 for (size_t i = 0; i < page_action_image_views_.size(); ++i) | 648 for (size_t i = 0; i < page_action_image_views_.size(); ++i) |
| 653 RemoveChildView(page_action_image_views_[i]); | 649 RemoveChildView(page_action_image_views_[i]); |
| 654 STLDeleteContainerPointers(page_action_image_views_.begin(), | 650 STLDeleteContainerPointers(page_action_image_views_.begin(), |
| 655 page_action_image_views_.end()); | 651 page_action_image_views_.end()); |
| 656 page_action_image_views_.clear(); | 652 page_action_image_views_.clear(); |
| 657 } | 653 } |
| 658 } | 654 } |
| 659 | 655 |
| 660 std::vector<PageAction*> LocationBarView::GetPageActions() { | |
| 661 std::vector<PageAction*> result; | |
| 662 if (!profile_->GetExtensionsService()) | |
| 663 return result; | |
| 664 | |
| 665 // Query the extension system to see how many page actions we have. | |
| 666 // TODO(finnur): Sort the page icons in some meaningful way. | |
| 667 const ExtensionList* extensions = | |
| 668 profile_->GetExtensionsService()->extensions(); | |
| 669 for (ExtensionList::const_iterator iter = extensions->begin(); | |
| 670 iter != extensions->end(); ++iter) { | |
| 671 const PageActionMap& page_actions = (*iter)->page_actions(); | |
| 672 for (PageActionMap::const_iterator i(page_actions.begin()); | |
| 673 i != page_actions.end(); ++i) { | |
| 674 result.push_back(i->second); | |
| 675 } | |
| 676 } | |
| 677 | |
| 678 return result; | |
| 679 } | |
| 680 | |
| 681 void LocationBarView::RefreshPageActionViews() { | 656 void LocationBarView::RefreshPageActionViews() { |
| 682 std::vector<PageAction*> page_actions = GetPageActions(); | 657 std::vector<PageAction*> page_actions; |
| 658 if (profile_->GetExtensionsService()) |
| 659 page_actions = profile_->GetExtensionsService()->GetPageActions(); |
| 683 | 660 |
| 684 // On startup we sometimes haven't loaded any extensions. This makes sure | 661 // On startup we sometimes haven't loaded any extensions. This makes sure |
| 685 // we catch up when the extensions (and any page actions) load. | 662 // we catch up when the extensions (and any page actions) load. |
| 686 if (page_actions.size() != page_action_image_views_.size()) { | 663 if (page_actions.size() != page_action_image_views_.size()) { |
| 687 DeletePageActionViews(); // Delete the old views (if any). | 664 DeletePageActionViews(); // Delete the old views (if any). |
| 688 | 665 |
| 689 page_action_image_views_.resize(page_actions.size()); | 666 page_action_image_views_.resize(page_actions.size()); |
| 690 | 667 |
| 691 for (size_t i = 0; i < page_actions.size(); ++i) { | 668 for (size_t i = 0; i < page_actions.size(); ++i) { |
| 692 page_action_image_views_[i] = | 669 page_action_image_views_[i] = |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1201 void LocationBarView::SecurityImageView::ShowInfoBubble() { | 1178 void LocationBarView::SecurityImageView::ShowInfoBubble() { |
| 1202 std::wstring text; | 1179 std::wstring text; |
| 1203 model_->GetIconHoverText(&text); | 1180 model_->GetIconHoverText(&text); |
| 1204 ShowInfoBubbleImpl(text, GetColor( | 1181 ShowInfoBubbleImpl(text, GetColor( |
| 1205 model_->GetSecurityLevel() == ToolbarModel::SECURE, | 1182 model_->GetSecurityLevel() == ToolbarModel::SECURE, |
| 1206 SECURITY_INFO_BUBBLE_TEXT)); | 1183 SECURITY_INFO_BUBBLE_TEXT)); |
| 1207 } | 1184 } |
| 1208 | 1185 |
| 1209 // PageActionImageView---------------------------------------------------------- | 1186 // PageActionImageView---------------------------------------------------------- |
| 1210 | 1187 |
| 1211 // The views need to load their icons asynchronously but might be deleted before | |
| 1212 // the images have loaded. This class stays alive while the request is in | |
| 1213 // progress (manages its own lifetime) and keeps track of whether the view still | |
| 1214 // cares about the icon loading. | |
| 1215 class LocationBarView::PageActionImageView::ImageLoadingTracker | |
| 1216 : public base::RefCountedThreadSafe<ImageLoadingTracker> { | |
| 1217 public: | |
| 1218 explicit ImageLoadingTracker(PageActionImageView* view, int image_count) | |
| 1219 : view_(view), image_count_(image_count) { | |
| 1220 AddRef(); // We hold on to a reference to ourself to make sure we don't | |
| 1221 // get deleted until we get a response from image loading (see | |
| 1222 // ImageLoadingDone). | |
| 1223 } | |
| 1224 ~ImageLoadingTracker() {} | |
| 1225 | |
| 1226 void StopTrackingImageLoad() { | |
| 1227 view_ = NULL; | |
| 1228 } | |
| 1229 | |
| 1230 void OnImageLoaded(SkBitmap* image, int index) { | |
| 1231 if (image == NULL) { | |
| 1232 NOTREACHED() << "Image failed to decode."; | |
| 1233 image = new SkBitmap(); | |
| 1234 } | |
| 1235 if (view_) | |
| 1236 view_->OnImageLoaded(image, index); | |
| 1237 delete image; | |
| 1238 if (--image_count_ == 0) | |
| 1239 Release(); // We are no longer needed. | |
| 1240 } | |
| 1241 | |
| 1242 private: | |
| 1243 | |
| 1244 // The view that is waiting for the image to load. | |
| 1245 PageActionImageView* view_; | |
| 1246 | |
| 1247 // The number of images this ImageTracker should keep track of. | |
| 1248 int image_count_; | |
| 1249 }; | |
| 1250 | |
| 1251 // The LoadImageTask is for asynchronously loading the image on the file thread. | |
| 1252 // If the image is successfully loaded and decoded it will report back on the | |
| 1253 // |callback_loop| to let the caller know the image is done loading. | |
| 1254 class LocationBarView::PageActionImageView::LoadImageTask : public Task { | |
| 1255 public: | |
| 1256 // Constructor for the LoadImageTask class. |tracker| is the object that | |
| 1257 // we use to communicate back to the entity that wants the image after we | |
| 1258 // decode it. |path| is the path to load the image from. |index| is an | |
| 1259 // identifier for the image that we pass back to the caller. | |
| 1260 LoadImageTask(ImageLoadingTracker* tracker, | |
| 1261 const FilePath& path, | |
| 1262 int index) | |
| 1263 : callback_loop_(MessageLoop::current()), | |
| 1264 tracker_(tracker), | |
| 1265 path_(path), | |
| 1266 index_(index) {} | |
| 1267 | |
| 1268 void ReportBack(SkBitmap* image) { | |
| 1269 DCHECK(image); | |
| 1270 callback_loop_->PostTask(FROM_HERE, NewRunnableMethod(tracker_, | |
| 1271 &PageActionImageView::ImageLoadingTracker::OnImageLoaded, | |
| 1272 image, | |
| 1273 index_)); | |
| 1274 } | |
| 1275 | |
| 1276 virtual void Run() { | |
| 1277 // Read the file from disk. | |
| 1278 std::string file_contents; | |
| 1279 if (!file_util::PathExists(path_) || | |
| 1280 !file_util::ReadFileToString(path_, &file_contents)) { | |
| 1281 ReportBack(NULL); | |
| 1282 return; | |
| 1283 } | |
| 1284 | |
| 1285 // Decode the image using WebKit's image decoder. | |
| 1286 const unsigned char* data = | |
| 1287 reinterpret_cast<const unsigned char*>(file_contents.data()); | |
| 1288 webkit_glue::ImageDecoder decoder(gfx::Size(kFavIconSize, kFavIconSize)); | |
| 1289 scoped_ptr<SkBitmap> decoded(new SkBitmap()); | |
| 1290 *decoded = decoder.Decode(data, file_contents.length()); | |
| 1291 if (decoded->empty()) { | |
| 1292 ReportBack(NULL); | |
| 1293 return; // Unable to decode. | |
| 1294 } | |
| 1295 | |
| 1296 if (decoded->width() != kFavIconSize || decoded->height() != kFavIconSize) { | |
| 1297 // The bitmap is not the correct size, re-sample. | |
| 1298 int new_width = decoded->width(); | |
| 1299 int new_height = decoded->height(); | |
| 1300 // Calculate what dimensions to use within the constraints (16x16 max). | |
| 1301 calc_favicon_target_size(&new_width, &new_height); | |
| 1302 *decoded = skia::ImageOperations::Resize( | |
| 1303 *decoded, skia::ImageOperations::RESIZE_LANCZOS3, | |
| 1304 new_width, new_height); | |
| 1305 } | |
| 1306 | |
| 1307 ReportBack(decoded.release()); | |
| 1308 } | |
| 1309 | |
| 1310 private: | |
| 1311 // The message loop that we need to call back on to report that we are done. | |
| 1312 MessageLoop* callback_loop_; | |
| 1313 | |
| 1314 // The object that is waiting for us to respond back. | |
| 1315 ImageLoadingTracker* tracker_; | |
| 1316 | |
| 1317 // The path to the image to load asynchronously. | |
| 1318 FilePath path_; | |
| 1319 | |
| 1320 // The index of the icon being loaded. | |
| 1321 int index_; | |
| 1322 }; | |
| 1323 | |
| 1324 LocationBarView::PageActionImageView::PageActionImageView( | 1188 LocationBarView::PageActionImageView::PageActionImageView( |
| 1325 LocationBarView* owner, | 1189 LocationBarView* owner, |
| 1326 Profile* profile, | 1190 Profile* profile, |
| 1327 const PageAction* page_action) | 1191 const PageAction* page_action) |
| 1328 : LocationBarImageView(), | 1192 : LocationBarImageView(), |
| 1329 owner_(owner), | 1193 owner_(owner), |
| 1330 profile_(profile), | 1194 profile_(profile), |
| 1331 page_action_(page_action), | 1195 page_action_(page_action), |
| 1332 current_tab_id_(-1), | 1196 current_tab_id_(-1), |
| 1333 tooltip_(page_action_->name()) { | 1197 tooltip_(page_action_->name()) { |
| 1334 Extension* extension = profile->GetExtensionsService()->GetExtensionById( | 1198 Extension* extension = profile->GetExtensionsService()->GetExtensionById( |
| 1335 page_action->extension_id()); | 1199 page_action->extension_id()); |
| 1336 DCHECK(extension); | 1200 DCHECK(extension); |
| 1337 | 1201 |
| 1338 // Load the images this view needs asynchronously on the file thread. We'll | 1202 // Load the images this view needs asynchronously on the file thread. We'll |
| 1339 // get a call back into OnImageLoaded if the image loads successfully. If not, | 1203 // get a call back into OnImageLoaded if the image loads successfully. If not, |
| 1340 // the ImageView will have no image and will not appear in the Omnibox. | 1204 // the ImageView will have no image and will not appear in the Omnibox. |
| 1341 DCHECK(!page_action->icon_paths().empty()); | 1205 DCHECK(!page_action->icon_paths().empty()); |
| 1342 const std::vector<std::string>& icon_paths = page_action->icon_paths(); | 1206 const std::vector<std::string>& icon_paths = page_action->icon_paths(); |
| 1343 page_action_icons_.resize(icon_paths.size()); | 1207 page_action_icons_.resize(icon_paths.size()); |
| 1344 int index = 0; | |
| 1345 MessageLoop* file_loop = g_browser_process->file_thread()->message_loop(); | |
| 1346 tracker_ = new ImageLoadingTracker(this, icon_paths.size()); | 1208 tracker_ = new ImageLoadingTracker(this, icon_paths.size()); |
| 1347 for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); | 1209 for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); |
| 1348 iter != icon_paths.end(); ++iter) { | 1210 iter != icon_paths.end(); ++iter) { |
| 1349 FilePath path = extension->GetResourcePath(*iter); | 1211 FilePath path = extension->GetResourcePath(*iter); |
| 1350 file_loop->PostTask(FROM_HERE, new LoadImageTask(tracker_, path, index++)); | 1212 tracker_->PostLoadImageTask(path); |
| 1351 } | 1213 } |
| 1352 } | 1214 } |
| 1353 | 1215 |
| 1354 LocationBarView::PageActionImageView::~PageActionImageView() { | 1216 LocationBarView::PageActionImageView::~PageActionImageView() { |
| 1355 if (tracker_) | 1217 if (tracker_) |
| 1356 tracker_->StopTrackingImageLoad(); | 1218 tracker_->StopTrackingImageLoad(); |
| 1357 } | 1219 } |
| 1358 | 1220 |
| 1359 bool LocationBarView::PageActionImageView::OnMousePressed( | 1221 bool LocationBarView::PageActionImageView::OnMousePressed( |
| 1360 const views::MouseEvent& event) { | 1222 const views::MouseEvent& event) { |
| 1361 // Our PageAction icon was clicked on, notify proper authorities. | 1223 // Our PageAction icon was clicked on, notify proper authorities. |
| 1362 ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( | 1224 ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( |
| 1363 profile_, page_action_->extension_id(), page_action_->id(), | 1225 profile_, page_action_->extension_id(), page_action_->id(), |
| 1364 current_tab_id_, current_url_.spec()); | 1226 current_tab_id_, current_url_.spec()); |
| 1365 return true; | 1227 return true; |
| 1366 } | 1228 } |
| 1367 | 1229 |
| 1368 void LocationBarView::PageActionImageView::ShowInfoBubble() { | 1230 void LocationBarView::PageActionImageView::ShowInfoBubble() { |
| 1369 ShowInfoBubbleImpl(ASCIIToWide(tooltip_), GetColor(false, TEXT)); | 1231 ShowInfoBubbleImpl(ASCIIToWide(tooltip_), GetColor(false, TEXT)); |
| 1370 } | 1232 } |
| 1371 | 1233 |
| 1234 void LocationBarView::PageActionImageView::OnImageLoaded(SkBitmap* image, |
| 1235 size_t index) { |
| 1236 DCHECK(index < page_action_icons_.size()); |
| 1237 if (index == page_action_icons_.size() - 1) |
| 1238 tracker_ = NULL; // The tracker object will delete itself when we return. |
| 1239 page_action_icons_[index] = *image; |
| 1240 owner_->UpdatePageActions(); |
| 1241 } |
| 1242 |
| 1372 void LocationBarView::PageActionImageView::UpdateVisibility( | 1243 void LocationBarView::PageActionImageView::UpdateVisibility( |
| 1373 TabContents* contents, GURL url) { | 1244 TabContents* contents, GURL url) { |
| 1374 // Save this off so we can pass it back to the extension when the action gets | 1245 // Save this off so we can pass it back to the extension when the action gets |
| 1375 // executed. See PageActionImageView::OnMousePressed. | 1246 // executed. See PageActionImageView::OnMousePressed. |
| 1376 current_tab_id_ = ExtensionTabUtil::GetTabId(contents); | 1247 current_tab_id_ = ExtensionTabUtil::GetTabId(contents); |
| 1377 current_url_ = url; | 1248 current_url_ = url; |
| 1378 | 1249 |
| 1379 const PageActionState* state = contents->GetPageActionState(page_action_); | 1250 const PageActionState* state = contents->GetPageActionState(page_action_); |
| 1380 bool visible = state != NULL; | 1251 bool visible = state != NULL; |
| 1381 if (visible) { | 1252 if (visible) { |
| 1382 // Set the tooltip. | 1253 // Set the tooltip. |
| 1383 if (state->title().empty()) | 1254 if (state->title().empty()) |
| 1384 tooltip_ = page_action_->name(); | 1255 tooltip_ = page_action_->name(); |
| 1385 else | 1256 else |
| 1386 tooltip_ = state->title(); | 1257 tooltip_ = state->title(); |
| 1387 // Set the image. | 1258 // Set the image. |
| 1388 int index = state->icon_index(); | 1259 int index = state->icon_index(); |
| 1389 // The image index (if not within bounds) will be set to the first image. | 1260 // The image index (if not within bounds) will be set to the first image. |
| 1390 if (index < 0 || index >= static_cast<int>(page_action_icons_.size())) | 1261 if (index < 0 || index >= static_cast<int>(page_action_icons_.size())) |
| 1391 index = 0; | 1262 index = 0; |
| 1392 ImageView::SetImage(page_action_icons_[index]); | 1263 ImageView::SetImage(page_action_icons_[index]); |
| 1393 } | 1264 } |
| 1394 SetVisible(visible); | 1265 SetVisible(visible); |
| 1395 } | 1266 } |
| 1396 | 1267 |
| 1397 void LocationBarView::PageActionImageView::OnImageLoaded(SkBitmap* image, | |
| 1398 size_t index) { | |
| 1399 DCHECK(index < page_action_icons_.size()); | |
| 1400 if (index == page_action_icons_.size() - 1) | |
| 1401 tracker_ = NULL; // The tracker object will delete itself when we return. | |
| 1402 page_action_icons_[index] = *image; | |
| 1403 owner_->UpdatePageActions(); | |
| 1404 } | |
| 1405 | |
| 1406 //////////////////////////////////////////////////////////////////////////////// | 1268 //////////////////////////////////////////////////////////////////////////////// |
| 1407 // LocationBarView, LocationBar implementation: | 1269 // LocationBarView, LocationBar implementation: |
| 1408 | 1270 |
| 1409 void LocationBarView::ShowFirstRunBubble(bool use_OEM_bubble) { | 1271 void LocationBarView::ShowFirstRunBubble(bool use_OEM_bubble) { |
| 1410 // We wait 30 milliseconds to open. It allows less flicker. | 1272 // We wait 30 milliseconds to open. It allows less flicker. |
| 1411 Task* task = first_run_bubble_.NewRunnableMethod( | 1273 Task* task = first_run_bubble_.NewRunnableMethod( |
| 1412 &LocationBarView::ShowFirstRunBubbleInternal, use_OEM_bubble); | 1274 &LocationBarView::ShowFirstRunBubbleInternal, use_OEM_bubble); |
| 1413 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 30); | 1275 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 30); |
| 1414 } | 1276 } |
| 1415 | 1277 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1452 } | 1314 } |
| 1453 | 1315 |
| 1454 int LocationBarView::PageActionVisibleCount() { | 1316 int LocationBarView::PageActionVisibleCount() { |
| 1455 int result = 0; | 1317 int result = 0; |
| 1456 for (size_t i = 0; i < page_action_image_views_.size(); i++) { | 1318 for (size_t i = 0; i < page_action_image_views_.size(); i++) { |
| 1457 if (page_action_image_views_[i]->IsVisible()) | 1319 if (page_action_image_views_[i]->IsVisible()) |
| 1458 ++result; | 1320 ++result; |
| 1459 } | 1321 } |
| 1460 return result; | 1322 return result; |
| 1461 } | 1323 } |
| OLD | NEW |