// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/webui/large_icon_source.h" #include #include "base/memory/ref_counted_memory.h" #include "chrome/browser/search/instant_io_context.h" #include "chrome/common/url_constants.h" #include "components/favicon/core/fallback_icon_service.h" #include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/fallback_icon_style.h" #include "components/favicon_base/favicon_types.h" #include "components/favicon_base/large_icon_url_parser.h" #include "net/url_request/url_request.h" namespace { const int kMaxLargeIconSize = 192; // Arbitrary bound to safeguard endpoint. } // namespace LargeIconSource::LargeIconSource( favicon::FallbackIconService* fallback_icon_service, favicon::LargeIconService* large_icon_service) : fallback_icon_service_(fallback_icon_service), large_icon_service_(large_icon_service) { } LargeIconSource::~LargeIconSource() { } std::string LargeIconSource::GetSource() const { return chrome::kChromeUILargeIconHost; } void LargeIconSource::StartDataRequest( const std::string& path, int render_process_id, int render_frame_id, const content::URLDataSource::GotDataCallback& callback) { if (!large_icon_service_) { SendNotFoundResponse(callback); return; } LargeIconUrlParser parser; bool success = parser.Parse(path); if (!success || parser.size_in_pixels() <= 0 || parser.size_in_pixels() > kMaxLargeIconSize) { SendNotFoundResponse(callback); return; } GURL url(parser.url_string()); if (!url.is_valid()) { SendNotFoundResponse(callback); return; } // TODO(beaudoin): Potentially allow icon to be scaled up. large_icon_service_->GetLargeIconOrFallbackStyle( url, parser.size_in_pixels(), // Reducing this will enable scale up. parser.size_in_pixels(), base::Bind(&LargeIconSource::OnLargeIconDataAvailable, base::Unretained(this), callback, url, parser.size_in_pixels()), &cancelable_task_tracker_); } std::string LargeIconSource::GetMimeType(const std::string&) const { // We need to explicitly return a mime type, otherwise if the user tries to // drag the image they get no extension. return "image/png"; } bool LargeIconSource::ShouldReplaceExistingSource() const { // Leave the existing DataSource in place, otherwise we'll drop any pending // requests on the floor. return false; } bool LargeIconSource::ShouldServiceRequest( const net::URLRequest* request) const { if (request->url().SchemeIs(chrome::kChromeSearchScheme)) return InstantIOContext::ShouldServiceRequest(request); return URLDataSource::ShouldServiceRequest(request); } void LargeIconSource::OnLargeIconDataAvailable( const content::URLDataSource::GotDataCallback& callback, const GURL& url, int size, const favicon_base::LargeIconResult& result) { if (result.bitmap.is_valid()) { callback.Run(result.bitmap.bitmap_data.get()); return; } // Bitmap is invalid, use the fallback if service is available. if (!fallback_icon_service_ || !result.fallback_icon_style) { SendNotFoundResponse(callback); return; } std::vector bitmap_data = fallback_icon_service_->RenderFallbackIconBitmap( url, size, *result.fallback_icon_style); callback.Run(base::RefCountedBytes::TakeVector(&bitmap_data)); } void LargeIconSource::SendNotFoundResponse( const content::URLDataSource::GotDataCallback& callback) { callback.Run(nullptr); }