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/ui/webui/theme_source.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted_memory.h"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/resources_util.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/search/instant_io_context.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/themes/theme_properties.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/themes/theme_service.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/themes/theme_service_factory.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/ntp/ntp_resource_cache.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/layout.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/base/webui/web_ui_util.h"
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetThemePath() {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return std::string(content::kChromeUIScheme) + "://" +
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         std::string(chrome::kChromeUIThemePath) + "/";
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// use a resource map rather than hard-coded strings.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* kNewTabCSSPath = "css/new_tab_theme.css";
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* kNewIncognitoTabCSSPath = "css/incognito_new_tab_theme.css";
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ThemeSource, public:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ThemeSource::ThemeSource(Profile* profile)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : profile_(profile->GetOriginalProfile()) {
463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NTPResourceCache::WindowType win_type = NTPResourceCache::GetWindowType(
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      profile_, NULL);
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  css_bytes_ =
493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NTPResourceCacheFactory::GetForProfile(profile)->GetNewTabCSS(win_type);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ThemeSource::~ThemeSource() {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string ThemeSource::GetSource() const {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return chrome::kChromeUIThemePath;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ThemeSource::StartDataRequest(
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& path,
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int render_process_id,
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int render_frame_id,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::URLDataSource::GotDataCallback& callback) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Default scale factor if not specified.
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  float scale_factor = 1.0f;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string uncached_path;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  webui::ParsePathAndScale(GURL(GetThemePath() + path),
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &uncached_path,
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &scale_factor);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (uncached_path == kNewTabCSSPath ||
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uncached_path == kNewIncognitoTabCSSPath) {
73e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK_CURRENTLY_ON(BrowserThread::IO);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callback.Run(css_bytes_.get());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int resource_id = ResourcesUtil::GetThemeResourceId(uncached_path);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (resource_id != -1) {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendThemeBitmap(callback, resource_id, scale_factor);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't have any data to send back.
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(NULL);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ThemeSource::GetMimeType(const std::string& path) const {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string uncached_path;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  webui::ParsePathAndScale(GURL(GetThemePath() + path), &uncached_path, NULL);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (uncached_path == kNewTabCSSPath ||
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uncached_path == kNewIncognitoTabCSSPath) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "text/css";
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "image/png";
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)base::MessageLoop* ThemeSource::MessageLoopForRequestPath(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& path) const {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string uncached_path;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  webui::ParsePathAndScale(GURL(GetThemePath() + path), &uncached_path, NULL);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (uncached_path == kNewTabCSSPath ||
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uncached_path == kNewIncognitoTabCSSPath) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We generated and cached this when we initialized the object.  We don't
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // have to go back to the UI thread to send the data.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If it's not a themeable image, we don't need to go to the UI thread.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int resource_id = ResourcesUtil::GetThemeResourceId(uncached_path);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ThemeProperties::IsThemeableImage(resource_id))
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return content::URLDataSource::MessageLoopForRequestPath(path);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ThemeSource::ShouldReplaceExistingSource() const {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We currently get the css_bytes_ in the ThemeSource constructor, so we need
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to recreate the source itself when a theme changes.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ThemeSource::ShouldServiceRequest(const net::URLRequest* request) const {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (request->url().SchemeIs(chrome::kChromeSearchScheme))
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return InstantIOContext::ShouldServiceRequest(request);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return URLDataSource::ShouldServiceRequest(request);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ThemeSource, private:
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ThemeSource::SendThemeBitmap(
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::URLDataSource::GotDataCallback& callback,
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int resource_id,
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    float scale_factor) {
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ui::ScaleFactor resource_scale_factor =
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ui::GetSupportedScaleFactor(scale_factor);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ThemeProperties::IsThemeableImage(resource_id)) {
144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK_CURRENTLY_ON(BrowserThread::UI);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::ThemeProvider* tp = ThemeServiceFactory::GetForProfile(profile_);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(tp);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<base::RefCountedMemory> image_data(
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        tp->GetRawData(resource_id, resource_scale_factor));
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callback.Run(image_data.get());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
152e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK_CURRENTLY_ON(BrowserThread::IO);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        rb.LoadDataResourceBytesForScale(resource_id, resource_scale_factor));
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
158