Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / favicon_source.cc
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/webui/favicon_source.h"
6
7 #include <cmath>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "chrome/browser/favicon/favicon_service_factory.h"
13 #include "chrome/browser/history/top_sites.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/search/instant_io_context.h"
16 #include "chrome/browser/sync/open_tabs_ui_delegate.h"
17 #include "chrome/browser/sync/profile_sync_service.h"
18 #include "chrome/browser/sync/profile_sync_service_factory.h"
19 #include "chrome/common/favicon/favicon_url_parser.h"
20 #include "chrome/common/url_constants.h"
21 #include "chrome/grit/locale_settings.h"
22 #include "net/url_request/url_request.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/layout.h"
25 #include "ui/base/resource/resource_bundle.h"
26 #include "ui/base/webui/web_ui_util.h"
27 #include "ui/resources/grit/ui_resources.h"
28
29 FaviconSource::IconRequest::IconRequest()
30     : size_in_dip(gfx::kFaviconSize), device_scale_factor(1.0f) {
31 }
32
33 FaviconSource::IconRequest::IconRequest(
34     const content::URLDataSource::GotDataCallback& cb,
35     const GURL& path,
36     int size,
37     float scale)
38     : callback(cb),
39       request_path(path),
40       size_in_dip(size),
41       device_scale_factor(scale) {
42 }
43
44 FaviconSource::IconRequest::~IconRequest() {
45 }
46
47 FaviconSource::FaviconSource(Profile* profile, IconType type)
48     : profile_(profile->GetOriginalProfile()),
49       icon_types_(type == FAVICON ? favicon_base::FAVICON
50                                   : favicon_base::TOUCH_PRECOMPOSED_ICON |
51                                         favicon_base::TOUCH_ICON |
52                                         favicon_base::FAVICON) {}
53
54 FaviconSource::~FaviconSource() {
55 }
56
57 std::string FaviconSource::GetSource() const {
58   return icon_types_ == favicon_base::FAVICON ? chrome::kChromeUIFaviconHost
59                                               : chrome::kChromeUITouchIconHost;
60 }
61
62 void FaviconSource::StartDataRequest(
63     const std::string& path,
64     int render_process_id,
65     int render_frame_id,
66     const content::URLDataSource::GotDataCallback& callback) {
67   FaviconService* favicon_service =
68       FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);
69   if (!favicon_service) {
70     SendDefaultResponse(callback);
71     return;
72   }
73
74   chrome::ParsedFaviconPath parsed;
75   bool success = chrome::ParseFaviconPath(path, icon_types_, &parsed);
76   if (!success) {
77     SendDefaultResponse(callback);
78     return;
79   }
80
81   GURL url(parsed.url);
82   int desired_size_in_pixel =
83       std::ceil(parsed.size_in_dip * parsed.device_scale_factor);
84
85   if (parsed.is_icon_url) {
86     // TODO(michaelbai): Change GetRawFavicon to support combination of
87     // IconType.
88    favicon_service->GetRawFavicon(
89         url,
90         favicon_base::FAVICON,
91         desired_size_in_pixel,
92         base::Bind(
93             &FaviconSource::OnFaviconDataAvailable,
94             base::Unretained(this),
95             IconRequest(
96                 callback, url, parsed.size_in_dip, parsed.device_scale_factor)),
97         &cancelable_task_tracker_);
98   } else {
99     // Intercept requests for prepopulated pages.
100     for (int i = 0; i < history::kPrepopulatedPagesCount; i++) {
101       if (url.spec() ==
102           l10n_util::GetStringUTF8(history::kPrepopulatedPages[i].url_id)) {
103         ui::ScaleFactor resource_scale_factor =
104             ui::GetSupportedScaleFactor(parsed.device_scale_factor);
105         callback.Run(
106             ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
107                 history::kPrepopulatedPages[i].favicon_id,
108                 resource_scale_factor));
109         return;
110       }
111     }
112
113     favicon_service->GetRawFaviconForPageURL(
114         url,
115         icon_types_,
116         desired_size_in_pixel,
117         base::Bind(
118             &FaviconSource::OnFaviconDataAvailable,
119             base::Unretained(this),
120             IconRequest(
121                 callback, url, parsed.size_in_dip, parsed.device_scale_factor)),
122         &cancelable_task_tracker_);
123   }
124 }
125
126 std::string FaviconSource::GetMimeType(const std::string&) const {
127   // We need to explicitly return a mime type, otherwise if the user tries to
128   // drag the image they get no extension.
129   return "image/png";
130 }
131
132 bool FaviconSource::ShouldReplaceExistingSource() const {
133   // Leave the existing DataSource in place, otherwise we'll drop any pending
134   // requests on the floor.
135   return false;
136 }
137
138 bool FaviconSource::ShouldServiceRequest(const net::URLRequest* request) const {
139   if (request->url().SchemeIs(chrome::kChromeSearchScheme))
140     return InstantIOContext::ShouldServiceRequest(request);
141   return URLDataSource::ShouldServiceRequest(request);
142 }
143
144 bool FaviconSource::HandleMissingResource(const IconRequest& request) {
145   // If the favicon is not available, try to use the synced favicon.
146   ProfileSyncService* sync_service =
147       ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_);
148   browser_sync::OpenTabsUIDelegate* open_tabs = sync_service ?
149       sync_service->GetOpenTabsUIDelegate() : NULL;
150
151   scoped_refptr<base::RefCountedMemory> response;
152   if (open_tabs &&
153       open_tabs->GetSyncedFaviconForPageURL(request.request_path.spec(),
154                                             &response)) {
155     request.callback.Run(response.get());
156     return true;
157   }
158   return false;
159 }
160
161 void FaviconSource::OnFaviconDataAvailable(
162     const IconRequest& request,
163     const favicon_base::FaviconRawBitmapResult& bitmap_result) {
164   if (bitmap_result.is_valid()) {
165     // Forward the data along to the networking system.
166     request.callback.Run(bitmap_result.bitmap_data.get());
167   } else if (!HandleMissingResource(request)) {
168     SendDefaultResponse(request);
169   }
170 }
171
172 void FaviconSource::SendDefaultResponse(
173     const content::URLDataSource::GotDataCallback& callback) {
174   SendDefaultResponse(IconRequest(callback, GURL(), 16, 1.0f));
175 }
176
177 void FaviconSource::SendDefaultResponse(const IconRequest& icon_request) {
178   int favicon_index;
179   int resource_id;
180   switch (icon_request.size_in_dip) {
181     case 64:
182       favicon_index = SIZE_64;
183       resource_id = IDR_DEFAULT_FAVICON_64;
184       break;
185     case 32:
186       favicon_index = SIZE_32;
187       resource_id = IDR_DEFAULT_FAVICON_32;
188       break;
189     default:
190       favicon_index = SIZE_16;
191       resource_id = IDR_DEFAULT_FAVICON;
192       break;
193   }
194   base::RefCountedMemory* default_favicon =
195       default_favicons_[favicon_index].get();
196
197   if (!default_favicon) {
198     ui::ScaleFactor resource_scale_factor =
199         ui::GetSupportedScaleFactor(icon_request.device_scale_factor);
200     default_favicon =
201         ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
202             resource_id, resource_scale_factor);
203     default_favicons_[favicon_index] = default_favicon;
204   }
205
206   icon_request.callback.Run(default_favicon);
207 }