| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/extensions/extension_web_ui.h" | 5 #include "chrome/browser/extensions/extension_web_ui.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/browser/bookmarks/bookmark_manager_extension_api.h" | 13 #include "chrome/browser/bookmarks/bookmark_manager_extension_api.h" |
| 14 #include "chrome/browser/extensions/extension_service.h" | 14 #include "chrome/browser/extensions/extension_service.h" |
| 15 #include "chrome/browser/extensions/extension_tab_util.h" | 15 #include "chrome/browser/extensions/extension_tab_util.h" |
| 16 #include "chrome/browser/extensions/image_loading_tracker.h" | 16 #include "chrome/browser/extensions/image_utils.h" |
| 17 #include "chrome/browser/prefs/pref_service.h" | 17 #include "chrome/browser/prefs/pref_service.h" |
| 18 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 18 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| 19 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
| 20 #include "chrome/browser/ui/browser.h" | 20 #include "chrome/browser/ui/browser.h" |
| 21 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 21 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 22 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" | 22 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" |
| 23 #include "chrome/common/chrome_switches.h" | 23 #include "chrome/common/chrome_switches.h" |
| 24 #include "chrome/common/extensions/extension.h" | 24 #include "chrome/common/extensions/extension.h" |
| 25 #include "chrome/common/extensions/extension_constants.h" | 25 #include "chrome/common/extensions/extension_constants.h" |
| 26 #include "chrome/common/extensions/extension_icon_set.h" | 26 #include "chrome/common/extensions/extension_icon_set.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 if (!url.SchemeIs(chrome::kChromeUIScheme) || url.host() != page) | 71 if (!url.SchemeIs(chrome::kChromeUIScheme) || url.host() != page) |
| 72 return; | 72 return; |
| 73 | 73 |
| 74 // Don't use Reload() since |url| isn't the same as the internal URL that | 74 // Don't use Reload() since |url| isn't the same as the internal URL that |
| 75 // NavigationController has. | 75 // NavigationController has. |
| 76 web_contents->GetController().LoadURL( | 76 web_contents->GetController().LoadURL( |
| 77 url, content::Referrer(url, WebKit::WebReferrerPolicyDefault), | 77 url, content::Referrer(url, WebKit::WebReferrerPolicyDefault), |
| 78 content::PAGE_TRANSITION_RELOAD, std::string()); | 78 content::PAGE_TRANSITION_RELOAD, std::string()); |
| 79 } | 79 } |
| 80 | 80 |
| 81 // Helper class that is used to track the loading of the favicon of an | 81 // Forwards the result of the request. If no favicon was available then |
| 82 // extension. | 82 // |image| will be empty. Once the result has been forwarded the instance is |
| 83 class ExtensionWebUIImageLoadingTracker : public ImageLoadingTracker::Observer { | 83 // deleted. |
| 84 public: | 84 void ForwardFaviconResult(FaviconService::GetFaviconRequest* request, |
| 85 ExtensionWebUIImageLoadingTracker(Profile* profile, | 85 const gfx::Image& image) { |
| 86 FaviconService::GetFaviconRequest* request, | 86 std::vector<history::FaviconBitmapResult> favicon_bitmap_results; |
| 87 const GURL& page_url) | 87 const std::vector<gfx::ImageSkiaRep>& image_reps = |
| 88 : ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)), | 88 image.AsImageSkia().image_reps(); |
| 89 request_(request), | 89 for (size_t i = 0; i < image_reps.size(); ++i) { |
| 90 extension_(NULL) { | 90 const gfx::ImageSkiaRep& image_rep = image_reps[i]; |
| 91 // Even when the extensions service is enabled by default, it's still | 91 scoped_refptr<base::RefCountedBytes> bitmap_data( |
| 92 // disabled in incognito mode. | 92 new base::RefCountedBytes()); |
| 93 ExtensionService* service = profile->GetExtensionService(); | 93 if (gfx::PNGCodec::EncodeBGRASkBitmap(image_rep.sk_bitmap(), |
| 94 if (service) | 94 false, |
| 95 extension_ = service->extensions()->GetByID(page_url.host()); | 95 &bitmap_data->data())) { |
| 96 } | 96 history::FaviconBitmapResult bitmap_result; |
| 97 bitmap_result.bitmap_data = bitmap_data; |
| 98 bitmap_result.pixel_size = gfx::Size(image_rep.pixel_width(), |
| 99 image_rep.pixel_height()); |
| 100 // Leave |bitmap_result|'s icon URL as the default of GURL(). |
| 101 bitmap_result.icon_type = history::FAVICON; |
| 97 | 102 |
| 98 void Init() { | 103 favicon_bitmap_results.push_back(bitmap_result); |
| 99 if (extension_) { | |
| 100 // Fetch resources for all supported scale factors for which there are | |
| 101 // resources. Load image reps for all supported scale factors immediately | |
| 102 // instead of in an as needed fashion to be consistent with how favicons | |
| 103 // are requested for chrome:// and page URLs. | |
| 104 const std::vector<ui::ScaleFactor>& scale_factors = | |
| 105 ui::GetSupportedScaleFactors(); | |
| 106 std::vector<ImageLoadingTracker::ImageRepresentation> info_list; | |
| 107 for (size_t i = 0; i < scale_factors.size(); ++i) { | |
| 108 float scale = ui::GetScaleFactorScale(scale_factors[i]); | |
| 109 int pixel_size = static_cast<int>(gfx::kFaviconSize * scale); | |
| 110 ExtensionResource icon_resource = | |
| 111 extension_->GetIconResource(pixel_size, | |
| 112 ExtensionIconSet::MATCH_BIGGER); | |
| 113 | |
| 114 info_list.push_back( | |
| 115 ImageLoadingTracker::ImageRepresentation( | |
| 116 icon_resource, | |
| 117 ImageLoadingTracker::ImageRepresentation::ALWAYS_RESIZE, | |
| 118 gfx::Size(pixel_size, pixel_size), | |
| 119 scale_factors[i])); | |
| 120 } | |
| 121 | |
| 122 tracker_.LoadImages(extension_, info_list, | |
| 123 ImageLoadingTracker::DONT_CACHE); | |
| 124 } else { | 104 } else { |
| 125 ForwardResult(gfx::Image()); | 105 NOTREACHED() << "Could not encode extension favicon"; |
| 126 } | 106 } |
| 127 } | 107 } |
| 128 | 108 |
| 129 virtual void OnImageLoaded(const gfx::Image& image, | 109 // Populate IconURLSizesMap such that all the icon URLs in |
| 130 const std::string& extension_id, | 110 // |favicon_bitmap_results| are present in |icon_url_sizes|. |
| 131 int index) OVERRIDE { | 111 // Populate the favicon sizes with the relevant pixel sizes in the |
| 132 ForwardResult(image); | 112 // extension's icon set. |
| 113 history::IconURLSizesMap icon_url_sizes; |
| 114 for (size_t i = 0; i < favicon_bitmap_results.size(); ++i) { |
| 115 const history::FaviconBitmapResult& bitmap_result = |
| 116 favicon_bitmap_results[i]; |
| 117 const GURL& icon_url = bitmap_result.icon_url; |
| 118 icon_url_sizes[icon_url].push_back(bitmap_result.pixel_size); |
| 133 } | 119 } |
| 134 | 120 |
| 135 private: | 121 request->ForwardResultAsync(request->handle(), favicon_bitmap_results, |
| 136 ~ExtensionWebUIImageLoadingTracker() {} | 122 icon_url_sizes); |
| 137 | 123 } |
| 138 // Forwards the result of the request. If no favicon was available then | |
| 139 // |image| will be empty. Once the result has been forwarded the instance is | |
| 140 // deleted. | |
| 141 void ForwardResult(const gfx::Image& image) { | |
| 142 std::vector<history::FaviconBitmapResult> favicon_bitmap_results; | |
| 143 const std::vector<gfx::ImageSkiaRep>& image_reps = | |
| 144 image.AsImageSkia().image_reps(); | |
| 145 for (size_t i = 0; i < image_reps.size(); ++i) { | |
| 146 const gfx::ImageSkiaRep& image_rep = image_reps[i]; | |
| 147 scoped_refptr<base::RefCountedBytes> bitmap_data( | |
| 148 new base::RefCountedBytes()); | |
| 149 if (gfx::PNGCodec::EncodeBGRASkBitmap(image_rep.sk_bitmap(), | |
| 150 false, | |
| 151 &bitmap_data->data())) { | |
| 152 history::FaviconBitmapResult bitmap_result; | |
| 153 bitmap_result.bitmap_data = bitmap_data; | |
| 154 bitmap_result.pixel_size = gfx::Size(image_rep.pixel_width(), | |
| 155 image_rep.pixel_height()); | |
| 156 // Leave |bitmap_result|'s icon URL as the default of GURL(). | |
| 157 bitmap_result.icon_type = history::FAVICON; | |
| 158 | |
| 159 favicon_bitmap_results.push_back(bitmap_result); | |
| 160 } else { | |
| 161 NOTREACHED() << "Could not encode extension favicon"; | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 // Populate IconURLSizesMap such that all the icon URLs in | |
| 166 // |favicon_bitmap_results| are present in |icon_url_sizes|. | |
| 167 // Populate the favicon sizes with the relevant pixel sizes in the | |
| 168 // extension's icon set. | |
| 169 history::IconURLSizesMap icon_url_sizes; | |
| 170 for (size_t i = 0; i < favicon_bitmap_results.size(); ++i) { | |
| 171 const history::FaviconBitmapResult& bitmap_result = | |
| 172 favicon_bitmap_results[i]; | |
| 173 const GURL& icon_url = bitmap_result.icon_url; | |
| 174 icon_url_sizes[icon_url].push_back(bitmap_result.pixel_size); | |
| 175 } | |
| 176 | |
| 177 request_->ForwardResultAsync(request_->handle(), favicon_bitmap_results, | |
| 178 icon_url_sizes); | |
| 179 delete this; | |
| 180 } | |
| 181 | |
| 182 ImageLoadingTracker tracker_; | |
| 183 scoped_refptr<FaviconService::GetFaviconRequest> request_; | |
| 184 const Extension* extension_; | |
| 185 | |
| 186 DISALLOW_COPY_AND_ASSIGN(ExtensionWebUIImageLoadingTracker); | |
| 187 }; | |
| 188 | 124 |
| 189 } // namespace | 125 } // namespace |
| 190 | 126 |
| 191 const char ExtensionWebUI::kExtensionURLOverrides[] = | 127 const char ExtensionWebUI::kExtensionURLOverrides[] = |
| 192 "extensions.chrome_url_overrides"; | 128 "extensions.chrome_url_overrides"; |
| 193 | 129 |
| 194 ExtensionWebUI::ExtensionWebUI(content::WebUI* web_ui, const GURL& url) | 130 ExtensionWebUI::ExtensionWebUI(content::WebUI* web_ui, const GURL& url) |
| 195 : WebUIController(web_ui), | 131 : WebUIController(web_ui), |
| 196 url_(url) { | 132 url_(url) { |
| 197 Profile* profile = Profile::FromWebUI(web_ui); | 133 Profile* profile = Profile::FromWebUI(web_ui); |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 StringValue override(iter->second.spec()); | 394 StringValue override(iter->second.spec()); |
| 459 UnregisterAndReplaceOverride(iter->first, profile, | 395 UnregisterAndReplaceOverride(iter->first, profile, |
| 460 page_overrides, &override); | 396 page_overrides, &override); |
| 461 } | 397 } |
| 462 } | 398 } |
| 463 } | 399 } |
| 464 | 400 |
| 465 // static | 401 // static |
| 466 void ExtensionWebUI::GetFaviconForURL(Profile* profile, | 402 void ExtensionWebUI::GetFaviconForURL(Profile* profile, |
| 467 FaviconService::GetFaviconRequest* request, const GURL& page_url) { | 403 FaviconService::GetFaviconRequest* request, const GURL& page_url) { |
| 468 // tracker deletes itself when done. | 404 // Even when the extensions service is enabled by default, it's still |
| 469 ExtensionWebUIImageLoadingTracker* tracker = | 405 // disabled in incognito mode. |
| 470 new ExtensionWebUIImageLoadingTracker(profile, request, page_url); | 406 ExtensionService* service = profile->GetExtensionService(); |
| 471 tracker->Init(); | 407 if (!service) { |
| 408 ForwardFaviconResult(request, gfx::Image()); |
| 409 return; |
| 410 } |
| 411 const Extension* extension = service->extensions()->GetByID(page_url.host()); |
| 412 if (!extension) { |
| 413 ForwardFaviconResult(request, gfx::Image()); |
| 414 return; |
| 415 } |
| 416 |
| 417 // Fetch resources for all supported scale factors for which there are |
| 418 // resources. Load image reps for all supported scale factors immediately |
| 419 // instead of in an as needed fashion to be consistent with how favicons |
| 420 // are requested for chrome:// and page URLs. |
| 421 const std::vector<ui::ScaleFactor>& scale_factors = |
| 422 ui::GetSupportedScaleFactors(); |
| 423 std::vector<extension_image_utils::ImageRepresentation> info_list; |
| 424 for (size_t i = 0; i < scale_factors.size(); ++i) { |
| 425 float scale = ui::GetScaleFactorScale(scale_factors[i]); |
| 426 int pixel_size = static_cast<int>(gfx::kFaviconSize * scale); |
| 427 ExtensionResource icon_resource = |
| 428 extension->GetIconResource(pixel_size, |
| 429 ExtensionIconSet::MATCH_BIGGER); |
| 430 |
| 431 info_list.push_back( |
| 432 extension_image_utils::ImageRepresentation( |
| 433 icon_resource, |
| 434 extension_image_utils::ImageRepresentation::ALWAYS_RESIZE, |
| 435 gfx::Size(pixel_size, pixel_size), |
| 436 scale_factors[i])); |
| 437 } |
| 438 |
| 439 extension_image_utils::LoadImagesAsync(extension, info_list, |
| 440 base::Bind(&ForwardFaviconResult, |
| 441 scoped_refptr<FaviconService::GetFaviconRequest>(request))); |
| 472 } | 442 } |
| OLD | NEW |