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/ui/webui/theme_source.h" | 5 #include "chrome/browser/ui/webui/theme_source.h" |
6 | 6 |
7 #include "base/memory/ref_counted_memory.h" | 7 #include "base/memory/ref_counted_memory.h" |
8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "chrome/browser/profiles/profile.h" | 10 #include "chrome/browser/profiles/profile.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 #include "grit/theme_resources.h" | 23 #include "grit/theme_resources.h" |
24 #include "net/url_request/url_request.h" | 24 #include "net/url_request/url_request.h" |
25 #include "ui/base/layout.h" | 25 #include "ui/base/layout.h" |
26 #include "ui/base/resource/resource_bundle.h" | 26 #include "ui/base/resource/resource_bundle.h" |
27 #include "ui/base/webui/web_ui_util.h" | 27 #include "ui/base/webui/web_ui_util.h" |
28 #include "ui/gfx/codec/png_codec.h" | 28 #include "ui/gfx/codec/png_codec.h" |
29 #include "ui/gfx/image/image_skia.h" | 29 #include "ui/gfx/image/image_skia.h" |
30 #include "ui/gfx/image/image_skia_rep.h" | 30 #include "ui/gfx/image/image_skia_rep.h" |
31 #include "url/gurl.h" | 31 #include "url/gurl.h" |
32 | 32 |
33 using content::BrowserThread; | |
34 | |
35 namespace { | 33 namespace { |
36 | 34 |
37 GURL GetThemePath(const std::string& path) { | 35 GURL GetThemeURL(const std::string& path) { |
Dan Beam
2016/08/30 01:27:28
guidelines i've heard for new code using 3+ letter
Peter Kasting
2016/08/30 22:51:29
Done.
| |
38 return GURL(std::string(content::kChromeUIScheme) + "://" + | 36 return GURL(std::string(content::kChromeUIScheme) + "://" + |
39 std::string(chrome::kChromeUIThemeHost) + "/" + path); | 37 std::string(chrome::kChromeUIThemeHost) + "/" + path); |
40 } | 38 } |
41 | 39 |
42 // use a resource map rather than hard-coded strings. | 40 bool IsNewTabCSSPath(const std::string& path) { |
Dan Beam
2016/08/30 01:27:29
as well as IsNewTabCssPath() (if this were abbrevi
Peter Kasting
2016/08/30 22:51:29
Done.
| |
43 static const char* kNewTabCSSPath = "css/new_tab_theme.css"; | 41 static const char kNewTabCSSPath[] = "css/new_tab_theme.css"; |
44 static const char* kNewIncognitoTabCSSPath = "css/incognito_new_tab_theme.css"; | 42 static const char kIncognitoNewTabCSSPath[] = |
43 "css/incognito_new_tab_theme.css"; | |
44 return (path == kNewTabCSSPath) || (path == kIncognitoNewTabCSSPath); | |
Dan Beam
2016/08/30 01:27:29
nit: the C++ style guide discourages () around ret
Peter Kasting
2016/08/30 01:48:46
There's nothing different about the rules for whet
| |
45 } | |
45 | 46 |
46 void ProcessImageOnUIThread(const gfx::ImageSkia& image, | 47 void ProcessImageOnUIThread(const gfx::ImageSkia& image, |
47 float scale_factor, | 48 float scale, |
48 scoped_refptr<base::RefCountedBytes> data) { | 49 scoped_refptr<base::RefCountedBytes> data) { |
49 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 50 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
50 const gfx::ImageSkiaRep& rep = image.GetRepresentation(scale_factor); | 51 const gfx::ImageSkiaRep& rep = image.GetRepresentation(scale); |
51 gfx::PNGCodec::EncodeBGRASkBitmap( | 52 gfx::PNGCodec::EncodeBGRASkBitmap( |
52 rep.sk_bitmap(), false /* discard transparency */, &data->data()); | 53 rep.sk_bitmap(), false /* discard transparency */, &data->data()); |
53 } | 54 } |
54 | 55 |
55 void ProcessResourceOnUIThread(int resource_id, | 56 void ProcessResourceOnUIThread(int resource_id, |
56 float scale_factor, | 57 float scale, |
57 scoped_refptr<base::RefCountedBytes> data) { | 58 scoped_refptr<base::RefCountedBytes> data) { |
58 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 59 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
59 ProcessImageOnUIThread( | 60 ProcessImageOnUIThread( |
60 *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id), | 61 *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id), |
61 scale_factor, data); | 62 scale, data); |
62 } | 63 } |
63 | 64 |
64 } // namespace | 65 } // namespace |
65 | 66 |
66 //////////////////////////////////////////////////////////////////////////////// | 67 //////////////////////////////////////////////////////////////////////////////// |
67 // ThemeSource, public: | 68 // ThemeSource, public: |
68 | 69 |
69 ThemeSource::ThemeSource(Profile* profile) | 70 ThemeSource::ThemeSource(Profile* profile) |
70 : profile_(profile->GetOriginalProfile()) { | 71 : profile_(profile->GetOriginalProfile()) { |
71 // NB: it's important that this is |profile| and not |profile_|. | 72 // NB: it's important that this is |profile| and not |profile_|. |
72 NTPResourceCache::WindowType win_type = NTPResourceCache::GetWindowType( | 73 NTPResourceCache::WindowType win_type = |
73 profile, NULL); | 74 NTPResourceCache::GetWindowType(profile, nullptr); |
74 css_bytes_ = | 75 css_bytes_ = |
75 NTPResourceCacheFactory::GetForProfile(profile)->GetNewTabCSS(win_type); | 76 NTPResourceCacheFactory::GetForProfile(profile)->GetNewTabCSS(win_type); |
76 } | 77 } |
77 | 78 |
78 ThemeSource::~ThemeSource() { | 79 ThemeSource::~ThemeSource() { |
79 } | 80 } |
80 | 81 |
81 std::string ThemeSource::GetSource() const { | 82 std::string ThemeSource::GetSource() const { |
82 return chrome::kChromeUIThemeHost; | 83 return chrome::kChromeUIThemeHost; |
83 } | 84 } |
84 | 85 |
85 void ThemeSource::StartDataRequest( | 86 void ThemeSource::StartDataRequest( |
86 const std::string& path, | 87 const std::string& path, |
87 int render_process_id, | 88 int render_process_id, |
88 int render_frame_id, | 89 int render_frame_id, |
89 const content::URLDataSource::GotDataCallback& callback) { | 90 const content::URLDataSource::GotDataCallback& callback) { |
90 // Default scale factor if not specified. | 91 // Default scale factor if not specified. |
91 float scale_factor = 1.0f; | 92 float scale = 1.0f; |
92 std::string uncached_path; | 93 std::string parsed_path; |
93 webui::ParsePathAndScale(GetThemePath(path), &uncached_path, &scale_factor); | 94 webui::ParsePathAndScale(GetThemeURL(path), &parsed_path, &scale); |
94 scale_factor = | 95 scale = ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactor(scale)); |
95 ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactor(scale_factor)); | |
96 | 96 |
97 if (uncached_path == kNewTabCSSPath || | 97 if (IsNewTabCSSPath(parsed_path)) { |
98 uncached_path == kNewIncognitoTabCSSPath) { | 98 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
99 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
100 | |
101 callback.Run(css_bytes_.get()); | 99 callback.Run(css_bytes_.get()); |
102 return; | 100 return; |
103 } | 101 } |
104 | 102 |
105 int resource_id = -1; | 103 int resource_id = -1; |
106 if (uncached_path == "current-channel-logo") { | 104 if (parsed_path == "current-channel-logo") { |
107 switch (chrome::GetChannel()) { | 105 switch (chrome::GetChannel()) { |
108 #if defined(GOOGLE_CHROME_BUILD) | 106 #if defined(GOOGLE_CHROME_BUILD) |
109 case version_info::Channel::CANARY: | 107 case version_info::Channel::CANARY: |
110 resource_id = IDR_PRODUCT_LOGO_32_CANARY; | 108 resource_id = IDR_PRODUCT_LOGO_32_CANARY; |
111 break; | 109 break; |
112 case version_info::Channel::DEV: | 110 case version_info::Channel::DEV: |
113 resource_id = IDR_PRODUCT_LOGO_32_DEV; | 111 resource_id = IDR_PRODUCT_LOGO_32_DEV; |
114 break; | 112 break; |
115 case version_info::Channel::BETA: | 113 case version_info::Channel::BETA: |
116 resource_id = IDR_PRODUCT_LOGO_32_BETA; | 114 resource_id = IDR_PRODUCT_LOGO_32_BETA; |
117 break; | 115 break; |
118 case version_info::Channel::STABLE: | 116 case version_info::Channel::STABLE: |
119 resource_id = IDR_PRODUCT_LOGO_32; | 117 resource_id = IDR_PRODUCT_LOGO_32; |
120 break; | 118 break; |
121 #else | 119 #else |
122 case version_info::Channel::CANARY: | 120 case version_info::Channel::CANARY: |
123 case version_info::Channel::DEV: | 121 case version_info::Channel::DEV: |
124 case version_info::Channel::BETA: | 122 case version_info::Channel::BETA: |
125 case version_info::Channel::STABLE: | 123 case version_info::Channel::STABLE: |
126 NOTREACHED(); | 124 NOTREACHED(); |
127 #endif | 125 #endif |
128 case version_info::Channel::UNKNOWN: | 126 case version_info::Channel::UNKNOWN: |
129 resource_id = IDR_PRODUCT_LOGO_32; | 127 resource_id = IDR_PRODUCT_LOGO_32; |
130 break; | 128 break; |
131 } | 129 } |
132 } else { | 130 } else { |
133 resource_id = ResourcesUtil::GetThemeResourceId(uncached_path); | 131 resource_id = ResourcesUtil::GetThemeResourceId(parsed_path); |
134 } | |
135 if (resource_id != -1) { | |
136 if (GetMimeType(path) == "image/png") | |
137 SendThemeImage(callback, resource_id, scale_factor); | |
138 else | |
139 SendThemeBitmap(callback, resource_id, scale_factor); | |
140 return; | |
141 } | 132 } |
142 | 133 |
143 // We don't have any data to send back. This shouldn't happen normally, as | 134 const float max_scale = ui::GetScaleForScaleFactor( |
Dan Beam
2016/08/30 01:27:29
do we have to get max_scale in the event that reso
Peter Kasting
2016/08/30 01:48:47
Another CL I have LGTM on already that's waiting o
| |
144 // chrome://theme/ data source is used only by chrome WebUI pages and | 135 ResourceBundle::GetSharedInstance().GetMaxScaleFactor()); |
145 // component extensions. We don't want to crash in Release build though, as | 136 if (resource_id == -1) { |
146 // it is possible that a user has entered an unexisting chrome://theme URL | 137 // We have no data to send back. This shouldn't happen normally, as |
147 // into the address bar. | 138 // chrome://theme/ URLs are only used by WebUI pages and component |
148 NOTREACHED() << path << " not found."; | 139 // extensions. However, the user can also enter these into the omnibox, so |
149 callback.Run(NULL); | 140 // we need to fail gracefully. |
141 callback.Run(nullptr); | |
142 } else if ((GetMimeType(path) == "image/png") && (scale > max_scale)) { | |
Dan Beam
2016/08/30 01:27:29
i don't really see the point to these () either, b
| |
143 SendThemeImage(callback, resource_id, scale); | |
144 } else { | |
145 SendThemeBitmap(callback, resource_id, scale); | |
146 } | |
150 } | 147 } |
151 | 148 |
152 std::string ThemeSource::GetMimeType(const std::string& path) const { | 149 std::string ThemeSource::GetMimeType(const std::string& path) const { |
153 std::string uncached_path; | 150 std::string parsed_path; |
154 webui::ParsePathAndScale(GetThemePath(path), &uncached_path, NULL); | 151 webui::ParsePathAndScale(GetThemeURL(path), &parsed_path, nullptr); |
155 | 152 return IsNewTabCSSPath(parsed_path) ? "text/css" : "image/png"; |
156 if (uncached_path == kNewTabCSSPath || | |
157 uncached_path == kNewIncognitoTabCSSPath) { | |
158 return "text/css"; | |
159 } | |
160 | |
161 return "image/png"; | |
162 } | 153 } |
163 | 154 |
164 base::MessageLoop* ThemeSource::MessageLoopForRequestPath( | 155 base::MessageLoop* ThemeSource::MessageLoopForRequestPath( |
165 const std::string& path) const { | 156 const std::string& path) const { |
166 std::string uncached_path; | 157 std::string parsed_path; |
167 webui::ParsePathAndScale(GetThemePath(path), &uncached_path, NULL); | 158 webui::ParsePathAndScale(GetThemeURL(path), &parsed_path, nullptr); |
168 | 159 |
169 if (uncached_path == kNewTabCSSPath || | 160 if (IsNewTabCSSPath(parsed_path)) { |
170 uncached_path == kNewIncognitoTabCSSPath) { | |
171 // We generated and cached this when we initialized the object. We don't | 161 // We generated and cached this when we initialized the object. We don't |
172 // have to go back to the UI thread to send the data. | 162 // have to go back to the UI thread to send the data. |
173 return NULL; | 163 return nullptr; |
174 } | 164 } |
175 | 165 |
176 // If it's not a themeable image, we don't need to go to the UI thread. | 166 // If it's not a themeable image, we don't need to go to the UI thread. |
177 int resource_id = ResourcesUtil::GetThemeResourceId(uncached_path); | 167 int resource_id = ResourcesUtil::GetThemeResourceId(parsed_path); |
178 if (!BrowserThemePack::IsPersistentImageID(resource_id)) | 168 return BrowserThemePack::IsPersistentImageID(resource_id) ? |
179 return NULL; | 169 content::URLDataSource::MessageLoopForRequestPath(path) : nullptr; |
180 | |
181 return content::URLDataSource::MessageLoopForRequestPath(path); | |
182 } | 170 } |
183 | 171 |
184 bool ThemeSource::ShouldReplaceExistingSource() const { | 172 bool ThemeSource::ShouldReplaceExistingSource() const { |
185 // We currently get the css_bytes_ in the ThemeSource constructor, so we need | 173 // We currently get the css_bytes_ in the ThemeSource constructor, so we need |
186 // to recreate the source itself when a theme changes. | 174 // to recreate the source itself when a theme changes. |
187 return true; | 175 return true; |
188 } | 176 } |
189 | 177 |
190 bool ThemeSource::ShouldServiceRequest(const net::URLRequest* request) const { | 178 bool ThemeSource::ShouldServiceRequest(const net::URLRequest* request) const { |
191 if (request->url().SchemeIs(chrome::kChromeSearchScheme)) | 179 return request->url().SchemeIs(chrome::kChromeSearchScheme) ? |
192 return InstantIOContext::ShouldServiceRequest(request); | 180 InstantIOContext::ShouldServiceRequest(request) : |
193 return URLDataSource::ShouldServiceRequest(request); | 181 URLDataSource::ShouldServiceRequest(request); |
194 } | 182 } |
195 | 183 |
196 //////////////////////////////////////////////////////////////////////////////// | 184 //////////////////////////////////////////////////////////////////////////////// |
197 // ThemeSource, private: | 185 // ThemeSource, private: |
198 | 186 |
199 void ThemeSource::SendThemeBitmap( | 187 void ThemeSource::SendThemeBitmap( |
200 const content::URLDataSource::GotDataCallback& callback, | 188 const content::URLDataSource::GotDataCallback& callback, |
201 int resource_id, | 189 int resource_id, |
202 float scale_factor) { | 190 float scale) { |
203 ui::ScaleFactor resource_scale_factor = | 191 ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactor(scale); |
204 ui::GetSupportedScaleFactor(scale_factor); | |
205 if (BrowserThemePack::IsPersistentImageID(resource_id)) { | 192 if (BrowserThemePack::IsPersistentImageID(resource_id)) { |
206 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 193 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
207 const ui::ThemeProvider& tp = | |
208 ThemeService::GetThemeProviderForProfile(profile_); | |
209 | |
210 scoped_refptr<base::RefCountedMemory> image_data( | 194 scoped_refptr<base::RefCountedMemory> image_data( |
211 tp.GetRawData(resource_id, resource_scale_factor)); | 195 ThemeService::GetThemeProviderForProfile(profile_).GetRawData( |
196 resource_id, scale_factor)); | |
212 callback.Run(image_data.get()); | 197 callback.Run(image_data.get()); |
213 } else { | 198 } else { |
214 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 199 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
215 const ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 200 const ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
216 callback.Run( | 201 callback.Run(rb.LoadDataResourceBytesForScale(resource_id, scale_factor)); |
217 rb.LoadDataResourceBytesForScale(resource_id, resource_scale_factor)); | |
218 } | 202 } |
219 } | 203 } |
220 | 204 |
221 void ThemeSource::SendThemeImage( | 205 void ThemeSource::SendThemeImage( |
222 const content::URLDataSource::GotDataCallback& callback, | 206 const content::URLDataSource::GotDataCallback& callback, |
223 int resource_id, | 207 int resource_id, |
224 float scale_factor) { | 208 float scale) { |
225 // If the resource bundle contains the data pack for |scale_factor|, we can | |
226 // safely fallback to SendThemeBitmap(). | |
227 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
228 if (ui::GetScaleForScaleFactor(rb.GetMaxScaleFactor()) >= scale_factor) { | |
229 SendThemeBitmap(callback, resource_id, scale_factor); | |
230 return; | |
231 } | |
232 | |
233 // Otherwise, we should use gfx::ImageSkia to obtain the data. ImageSkia can | |
234 // rescale the bitmap if its backend doesn't contain the representation for | |
235 // the specified scale factor. This is the fallback path in case chrome is | |
236 // shipped without 2x resource pack but needs to use HighDPI display, which | |
237 // can happen in ChromeOS or Linux. | |
238 scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); | 209 scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); |
239 if (BrowserThemePack::IsPersistentImageID(resource_id)) { | 210 if (BrowserThemePack::IsPersistentImageID(resource_id)) { |
240 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 211 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
241 const ui::ThemeProvider& tp = | 212 const ui::ThemeProvider& tp = |
242 ThemeService::GetThemeProviderForProfile(profile_); | 213 ThemeService::GetThemeProviderForProfile(profile_); |
243 ProcessImageOnUIThread(*tp.GetImageSkiaNamed(resource_id), scale_factor, | 214 ProcessImageOnUIThread(*tp.GetImageSkiaNamed(resource_id), scale, data); |
244 data); | |
245 callback.Run(data.get()); | 215 callback.Run(data.get()); |
246 } else { | 216 } else { |
247 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 217 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
248 // Fetching image data in ResourceBundle should happen on the UI thread. See | 218 // Fetching image data in ResourceBundle should happen on the UI thread. See |
249 // crbug.com/449277 | 219 // crbug.com/449277 |
250 content::BrowserThread::PostTaskAndReply( | 220 content::BrowserThread::PostTaskAndReply( |
251 content::BrowserThread::UI, FROM_HERE, | 221 content::BrowserThread::UI, FROM_HERE, |
252 base::Bind(&ProcessResourceOnUIThread, resource_id, scale_factor, data), | 222 base::Bind(&ProcessResourceOnUIThread, resource_id, scale, data), |
253 base::Bind(callback, data)); | 223 base::Bind(callback, data)); |
254 } | 224 } |
255 } | 225 } |
OLD | NEW |