15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_web_ui.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h" 178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/favicon_base/favicon_util.h" 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/bindings_policy.h" 2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_registry.h" 306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/browser/image_loader.h" 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/extension_icon_set.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/extension_resource.h" 34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.h" 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/incognito_info.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/file_stream.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/page_transition_types.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/favicon_size.h" 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/image/image_skia.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::URLOverrides; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// De-dupes the items in |list|. Assumes the values are strings. 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid CleanUpDuplicates(base::ListValue* list) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> seen_values; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Loop backwards as we may be removing items. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = list->GetSize() - 1; (i + 1) > 0; --i) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!list->GetString(i, &value)) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (seen_values.find(value) == seen_values.end()) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) seen_values.insert(value); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list->Remove(i, NULL); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reloads the page in |web_contents| if it uses the same profile as |profile| 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and if the current URL is a chrome URL. 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void UnregisterAndReplaceOverrideForWebContents(const std::string& page, 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile, 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebContents* web_contents) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Profile::FromBrowserContext(web_contents->GetBrowserContext()) != profile) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url = web_contents->GetURL(); 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!url.SchemeIs(content::kChromeUIScheme) || url.host() != page) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't use Reload() since |url| isn't the same as the internal URL that 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NavigationController has. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents->GetController().LoadURL( 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) url, content::Referrer(url, blink::WebReferrerPolicyDefault), 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::PAGE_TRANSITION_RELOAD, std::string()); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Run favicon callbck with image result. If no favicon was available then 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |image| will be empty. 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RunFaviconCallbackAsync( 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const favicon_base::FaviconResultsCallback& callback, 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Image& image) { 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* favicon_bitmap_results = 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new std::vector<favicon_base::FaviconRawBitmapResult>(); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<gfx::ImageSkiaRep>& image_reps = 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image.AsImageSkia().image_reps(); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < image_reps.size(); ++i) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::ImageSkiaRep& image_rep = image_reps[i]; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::RefCountedBytes> bitmap_data( 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new base::RefCountedBytes()); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (gfx::PNGCodec::EncodeBGRASkBitmap(image_rep.sk_bitmap(), 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false, 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &bitmap_data->data())) { 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult bitmap_result; 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_result.bitmap_data = bitmap_data; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_result.pixel_size = gfx::Size(image_rep.pixel_width(), 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_rep.pixel_height()); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Leave |bitmap_result|'s icon URL as the default of GURL(). 1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bitmap_result.icon_type = favicon_base::FAVICON; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_bitmap_results->push_back(bitmap_result); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "Could not encode extension favicon"; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::MessageLoopProxy::current()->PostTask( 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FaviconService::FaviconResultsCallbackRunner, 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback, 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Owned(favicon_bitmap_results))); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ValidateOverrideURL(const base::Value* override_url_value, 12523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const GURL& source_url, 12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const extensions::ExtensionSet& extensions, 12723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GURL* override_url, 12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const Extension** extension) { 12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) std::string override; 13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!override_url_value || !override_url_value->GetAsString(&override)) { 13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return false; 13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!source_url.query().empty()) 13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) override += "?" + source_url.query(); 13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!source_url.ref().empty()) 13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) override += "#" + source_url.ref(); 13723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) *override_url = GURL(override); 13823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!override_url->is_valid()) { 13923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return false; 14023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 14123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) *extension = extensions.GetByID(override_url->host()); 14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!*extension) { 14323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return false; 14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return true; 14623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 14723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char ExtensionWebUI::kExtensionURLOverrides[] = 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "extensions.chrome_url_overrides"; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebUI::ExtensionWebUI(content::WebUI* web_ui, const GURL& url) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : WebUIController(web_ui), 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_(url) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = Profile::FromWebUI(web_ui); 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Extension* extension = extensions::ExtensionRegistry::Get( 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch profile)->enabled_extensions().GetExtensionOrAppByURL(url); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(extension); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The base class defaults to enabling WebUI bindings, but we don't need 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // those (this is also reflected in ChromeWebUIControllerFactory:: 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // UseWebUIBindingsForURL). 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bindings = 0; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_ui->SetBindings(bindings); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hack: A few things we specialize just for the bookmark manager. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension->id() == extension_misc::kBookmarkManagerId) { 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bookmark_manager_private_drag_event_router_.reset( 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new extensions::BookmarkManagerPrivateDragEventRouter( 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) profile, web_ui->GetWebContents())); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_ui->SetLinkTransitionType(ui::PAGE_TRANSITION_AUTO_BOOKMARK); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebUI::~ExtensionWebUI() {} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)extensions::BookmarkManagerPrivateDragEventRouter* 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ExtensionWebUI::bookmark_manager_private_drag_event_router() { 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return bookmark_manager_private_drag_event_router_.get(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// chrome:// URL overrides 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ExtensionWebUI::RegisterProfilePrefs( 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable* registry) { 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registry->RegisterDictionaryPref( 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kExtensionURLOverrides, 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebUI::HandleChromeURLOverride( 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL* url, 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserContext* browser_context) { 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!url->SchemeIs(content::kChromeUIScheme)) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(browser_context); 203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::DictionaryValue* overrides = 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile->GetPrefs()->GetDictionary(kExtensionURLOverrides); 20523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 20623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) std::string url_host = url->host(); 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::ListValue* url_list = NULL; 20823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!overrides || !overrides->GetList(url_host, &url_list)) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) extensions::ExtensionRegistry* registry = 21223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) extensions::ExtensionRegistry::Get(browser_context); 21323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const extensions::ExtensionSet& extensions = registry->enabled_extensions(); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GURL component_url; 216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool found_component_override = false; 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 21823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Iterate over the URL list looking for a suitable override. If a 21923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // valid non-component override is encountered it is chosen immediately. 22023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for (size_t i = 0; i < url_list->GetSize(); ++i) { 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* val = NULL; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_list->Get(i, &val); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GURL override_url; 22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const Extension* extension; 22623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!ValidateOverrideURL( 22723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) val, *url, extensions, &override_url, &extension)) { 22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) LOG(WARNING) << "Invalid chrome URL override"; 22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) UnregisterChromeURLOverride(url_host, profile, val); 23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // The above Unregister call will remove this item from url_list. 23123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) --i; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't handle chrome-extension URLs in incognito mode unless the 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extension uses split mode. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool incognito_override_allowed = 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::IncognitoInfo::IsSplitMode(extension) && 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::util::IsIncognitoEnabled(extension->id(), profile); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile->IsOffTheRecord() && !incognito_override_allowed) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!extensions::Manifest::IsComponentLocation(extension->location())) { 24523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) *url = override_url; 24623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return true; 24723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 24823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 24923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!found_component_override) { 250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) found_component_override = true; 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) component_url = override_url; 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 25523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // If no other non-component overrides were found, use the first known 25623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // component override, if any. 257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (found_component_override) { 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *url = component_url; 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebUI::HandleChromeURLOverrideReverse( 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL* url, content::BrowserContext* browser_context) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(browser_context); 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::DictionaryValue* overrides = 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile->GetPrefs()->GetDictionary(kExtensionURLOverrides); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!overrides) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the reverse mapping based on the given URL. For example this maps the 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // internal URL 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chrome-extension://eemcgdkfndhakfknompkggombfjjjeno/main.html#1 to 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chrome://bookmarks/#1 for display in the omnibox. 278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (base::DictionaryValue::Iterator it(*overrides); !it.IsAtEnd(); 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it.Advance()) { 280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::ListValue* url_list = NULL; 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!it.value().GetAsList(&url_list)) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (base::ListValue::const_iterator it2 = url_list->begin(); 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it2 != url_list->end(); ++it2) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string override; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(*it2)->GetAsString(&override)) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StartsWithASCII(url->spec(), override, true)) { 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL original_url(content::kChromeUIScheme + std::string("://") + 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it.key() + url->spec().substr(override.length())); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *url = original_url; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebUI::RegisterChromeURLOverrides( 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile, const URLOverrides::URLOverrideMap& overrides) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (overrides.empty()) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* prefs = profile->GetPrefs(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryPrefUpdate update(prefs, kExtensionURLOverrides); 309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::DictionaryValue* all_overrides = update.Get(); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For each override provided by the extension, add it to the front of 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the override list if it's not already in the list. 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) URLOverrides::URLOverrideMap::const_iterator iter = overrides.begin(); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; iter != overrides.end(); ++iter) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& key = iter->first; 316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ListValue* page_overrides = NULL; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!all_overrides->GetList(key, &page_overrides)) { 318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch page_overrides = new base::ListValue(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_overrides->Set(key, page_overrides); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CleanUpDuplicates(page_overrides); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that the override isn't already in the list. 324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ListValue::iterator i = page_overrides->begin(); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; i != page_overrides->end(); ++i) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string override_val; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(*i)->GetAsString(&override_val)) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (override_val == iter->second.spec()) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This value is already in the list, leave it alone. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i != page_overrides->end()) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert the override at the front of the list. Last registered override 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // wins. 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) page_overrides->Insert(0, new base::StringValue(iter->second.spec())); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebUI::UnregisterAndReplaceOverride(const std::string& page, 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ListValue* list, 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* override) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index = 0; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool found = list->Remove(*override, &index); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found && index == 0) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is the active override, so we need to find all existing 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tabs for this override and get them to reload the original URL. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Callback<void(WebContents*)> callback = 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&UnregisterAndReplaceOverrideForWebContents, page, profile); 356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::ExtensionTabUtil::ForEachTab(callback); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebUI::UnregisterChromeURLOverride(const std::string& page, 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* override) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!override) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* prefs = profile->GetPrefs(); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryPrefUpdate update(prefs, kExtensionURLOverrides); 368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::DictionaryValue* all_overrides = update.Get(); 369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ListValue* page_overrides = NULL; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!all_overrides->GetList(page, &page_overrides)) { 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If it's being unregistered, it should already be in the list. 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnregisterAndReplaceOverride(page, profile, page_overrides, override); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebUI::UnregisterChromeURLOverrides( 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile, const URLOverrides::URLOverrideMap& overrides) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (overrides.empty()) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* prefs = profile->GetPrefs(); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryPrefUpdate update(prefs, kExtensionURLOverrides); 386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::DictionaryValue* all_overrides = update.Get(); 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) URLOverrides::URLOverrideMap::const_iterator iter = overrides.begin(); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; iter != overrides.end(); ++iter) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& page = iter->first; 390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ListValue* page_overrides = NULL; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!all_overrides->GetList(page, &page_overrides)) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If it's being unregistered, it should already be in the list. 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::StringValue override(iter->second.spec()); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnregisterAndReplaceOverride(iter->first, profile, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_overrides, &override); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionWebUI::GetFaviconForURL( 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile, 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& page_url, 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const favicon_base::FaviconResultsCallback& callback) { 408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Extension* extension = extensions::ExtensionRegistry::Get( 409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch profile)->enabled_extensions().GetByID(page_url.host()); 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!extension) { 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunFaviconCallbackAsync(callback, gfx::Image()); 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Fetch resources for all supported scale factors for which there are 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // resources. Load image reps for all supported scale factors (in addition to 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1x) immediately instead of in an as needed fashion to be consistent with 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // how favicons are requested for chrome:// and page URLs. 4196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::vector<float>& favicon_scales = favicon_base::GetFaviconScales(); 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<extensions::ImageLoader::ImageRepresentation> info_list; 4216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (size_t i = 0; i < favicon_scales.size(); ++i) { 4226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) float scale = favicon_scales[i]; 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int pixel_size = static_cast<int>(gfx::kFaviconSize * scale); 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ExtensionResource icon_resource = 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::IconsInfo::GetIconResource(extension, 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pixel_size, 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionIconSet::MATCH_BIGGER); 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ui::ScaleFactor resource_scale_factor = ui::GetSupportedScaleFactor(scale); 4306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) info_list.push_back(extensions::ImageLoader::ImageRepresentation( 4316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) icon_resource, 4326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE, 4336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) gfx::Size(pixel_size, pixel_size), 4346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) resource_scale_factor)); 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // LoadImagesAsync actually can run callback synchronously. We want to force 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // async. 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ImageLoader::Get(profile)->LoadImagesAsync( 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension, info_list, base::Bind(&RunFaviconCallbackAsync, callback)); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 442