Home | History | Annotate | Download | only in thumbnails
      1 // Copyright 2014 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/thumbnails/thumbnail_list_source.h"
      6 
      7 #include <string>
      8 
      9 #include "base/base64.h"
     10 #include "base/bind.h"
     11 #include "base/logging.h"
     12 #include "base/memory/ref_counted_memory.h"
     13 #include "base/strings/string_util.h"
     14 #include "chrome/browser/history/top_sites.h"
     15 #include "chrome/browser/profiles/profile.h"
     16 #include "chrome/browser/search/instant_io_context.h"
     17 #include "chrome/browser/thumbnails/thumbnail_service.h"
     18 #include "chrome/browser/thumbnails/thumbnail_service_factory.h"
     19 #include "chrome/common/url_constants.h"
     20 #include "net/base/escape.h"
     21 #include "net/url_request/url_request.h"
     22 
     23 namespace {
     24 
     25 const char kHtmlHeader[] =
     26     "<!DOCTYPE html>\n<html>\n<head>\n<title>TopSites Thumbnails</title>\n"
     27     "<meta charset=\"utf-8\">\n"
     28     "<style type=\"text/css\">\nimg.thumb {border: 1px solid black;}\n"
     29     "li {white-space: nowrap;}\n</style>\n";
     30 const char kHtmlBody[] = "</head>\n<body>\n";
     31 const char kHtmlFooter[] = "</body>\n</html>\n";
     32 
     33 // If |want_thumbnails| == true, then renders elements in |mvurl_list| that have
     34 // thumbnails, with their thumbnails. Otherwise renders elements in |mvurl_list|
     35 // that have no thumbnails.
     36 void RenderMostVisitedURLList(
     37     const history::MostVisitedURLList& mvurl_list,
     38     const std::vector<std::string>& base64_encoded_pngs,
     39     bool want_thumbnails,
     40     std::vector<std::string>* out) {
     41   DCHECK_EQ(mvurl_list.size(), base64_encoded_pngs.size());
     42   bool doing_forced_urls = true;
     43   out->push_back("<div><b>Forced URLs:</b></div>\n"
     44                  "<div><ul>\n");
     45   for (size_t i = 0; i < mvurl_list.size(); ++i) {
     46     const history::MostVisitedURL& mvurl = mvurl_list[i];
     47     if (doing_forced_urls && mvurl.last_forced_time.is_null()) {
     48       out->push_back("</ul></div>\n"
     49                      "<div><b>Non-forced URLs:</b></div>\n"
     50                      "<div><ul>\n");
     51       doing_forced_urls = false;
     52     }
     53     bool has_thumbnail = !base64_encoded_pngs[i].empty();
     54     if (has_thumbnail == want_thumbnails) {
     55       out->push_back("<li>\n");
     56       out->push_back(net::EscapeForHTML(mvurl.url.spec()) + "\n");
     57       if (want_thumbnails) {
     58         out->push_back("<div><img class=\"thumb\" "
     59                        "src=\"data:image/png;base64," +
     60                        base64_encoded_pngs[i] + "\"/></div>\n");
     61       }
     62       if (!mvurl.redirects.empty()) {
     63         out->push_back("<ul>\n");
     64         history::RedirectList::const_iterator jt;
     65         for (jt = mvurl.redirects.begin();
     66              jt != mvurl.redirects.end(); ++jt) {
     67           out->push_back("<li>" + net::EscapeForHTML(jt->spec()) + "</li>\n");
     68         }
     69         out->push_back("</ul>\n");
     70       }
     71       out->push_back("</li>\n");
     72     }
     73   }
     74   out->push_back("</ul></div>\n");
     75 }
     76 
     77 }  // namespace
     78 
     79 ThumbnailListSource::ThumbnailListSource(Profile* profile)
     80     : thumbnail_service_(ThumbnailServiceFactory::GetForProfile(profile)),
     81       profile_(profile),
     82       weak_ptr_factory_(this) {
     83 }
     84 
     85 ThumbnailListSource::~ThumbnailListSource() {
     86 }
     87 
     88 std::string ThumbnailListSource::GetSource() const {
     89   return chrome::kChromeUIThumbnailListHost;
     90 }
     91 
     92 void ThumbnailListSource::StartDataRequest(
     93     const std::string& path,
     94     int render_process_id,
     95     int render_frame_id,
     96     const content::URLDataSource::GotDataCallback& callback) {
     97   profile_->GetTopSites()->GetMostVisitedURLs(
     98       base::Bind(&ThumbnailListSource::OnMostVisitedURLsAvailable,
     99                  weak_ptr_factory_.GetWeakPtr(),
    100                  callback), true);
    101 }
    102 
    103 std::string ThumbnailListSource::GetMimeType(const std::string& path) const {
    104   return "text/html";
    105 }
    106 
    107 base::MessageLoop* ThumbnailListSource::MessageLoopForRequestPath(
    108     const std::string& path) const {
    109   // TopSites can be accessed from the IO thread.
    110   return thumbnail_service_.get() ?
    111       NULL : content::URLDataSource::MessageLoopForRequestPath(path);
    112 }
    113 
    114 bool ThumbnailListSource::ShouldServiceRequest(
    115     const net::URLRequest* request) const {
    116   if (request->url().SchemeIs(chrome::kChromeSearchScheme))
    117     return InstantIOContext::ShouldServiceRequest(request);
    118   return URLDataSource::ShouldServiceRequest(request);
    119 }
    120 
    121 bool ThumbnailListSource::ShouldReplaceExistingSource() const {
    122   return false;
    123 }
    124 
    125 void ThumbnailListSource::OnMostVisitedURLsAvailable(
    126     const content::URLDataSource::GotDataCallback& callback,
    127     const history::MostVisitedURLList& mvurl_list) {
    128   const size_t num_mv = mvurl_list.size();
    129   size_t num_mv_with_thumb = 0;
    130 
    131   // Encode all available thumbnails and store into |base64_encoded_pngs|.
    132   std::vector<std::string> base64_encoded_pngs(num_mv);
    133   for (size_t i = 0; i < num_mv; ++i) {
    134     scoped_refptr<base::RefCountedMemory> data;
    135     if (thumbnail_service_->GetPageThumbnail(mvurl_list[i].url, false, &data)) {
    136       base::Base64Encode(std::string(data->front_as<char>(), data->size()),
    137                          &base64_encoded_pngs[i]);
    138       ++num_mv_with_thumb;
    139     }
    140   }
    141 
    142   // Render HTML to embed URLs and thumbnails.
    143   std::vector<std::string> out;
    144   out.push_back(kHtmlHeader);
    145   out.push_back(kHtmlBody);
    146   if (num_mv_with_thumb > 0) {
    147     out.push_back("<h2>TopSites URLs with Thumbnails</h2>\n");
    148     RenderMostVisitedURLList(mvurl_list, base64_encoded_pngs, true, &out);
    149   }
    150   if (num_mv_with_thumb < num_mv) {
    151     out.push_back("<h2>TopSites URLs without Thumbnails</h2>\n");
    152     RenderMostVisitedURLList(mvurl_list, base64_encoded_pngs, false, &out);
    153   }
    154   out.push_back(kHtmlFooter);
    155 
    156   std::string out_html = JoinString(out, "");
    157   callback.Run(base::RefCountedString::TakeString(&out_html));
    158 }
    159