suggestions_source.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/search/suggestions/suggestions_source.h"
6
7#include <vector>
8
9#include "base/bind.h"
10#include "base/memory/ref_counted_memory.h"
11#include "base/strings/string16.h"
12#include "base/strings/string_util.h"
13#include "base/strings/utf_string_conversions.h"
14#include "chrome/browser/profiles/profile.h"
15#include "chrome/browser/search/instant_io_context.h"
16#include "chrome/browser/search/suggestions/proto/suggestions.pb.h"
17#include "chrome/browser/search/suggestions/suggestions_service.h"
18#include "chrome/browser/search/suggestions/suggestions_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#include "url/gurl.h"
23
24namespace suggestions {
25
26namespace {
27
28const char kHtmlHeader[] =
29    "<!DOCTYPE html>\n<html>\n<head>\n<title>Suggestions</title>\n"
30    "<meta charset=\"utf-8\">\n"
31    "<style type=\"text/css\">\nli {white-space: nowrap;}\n</style>\n";
32const char kHtmlBody[] = "</head>\n<body>\n";
33const char kHtmlFooter[] = "</body>\n</html>\n";
34
35}  // namespace
36
37SuggestionsSource::SuggestionsSource(Profile* profile)
38    : profile_(profile),
39      weak_ptr_factory_(this) {
40}
41
42SuggestionsSource::~SuggestionsSource() {
43}
44
45std::string SuggestionsSource::GetSource() const {
46  return chrome::kChromeUISuggestionsHost;
47}
48
49void SuggestionsSource::StartDataRequest(
50    const std::string& path,
51    int render_process_id,
52    int render_frame_id,
53    const content::URLDataSource::GotDataCallback& callback) {
54  SuggestionsServiceFactory* suggestions_service_factory =
55      SuggestionsServiceFactory::GetInstance();
56
57  SuggestionsService* suggestions_service(
58      suggestions_service_factory->GetForProfile(profile_));
59
60  // If SuggestionsService is unavailable, then SuggestionsSource should not
61  // have been instantiated in the first place.
62  DCHECK(suggestions_service != NULL);
63
64  suggestions_service->FetchSuggestionsData(
65      base::Bind(&SuggestionsSource::OnSuggestionsAvailable,
66                 weak_ptr_factory_.GetWeakPtr(), callback));
67}
68
69std::string SuggestionsSource::GetMimeType(const std::string& path) const {
70  return "text/html";
71}
72
73base::MessageLoop* SuggestionsSource::MessageLoopForRequestPath(
74    const std::string& path) const {
75  // This can be accessed from the IO thread.
76  return content::URLDataSource::MessageLoopForRequestPath(path);
77}
78
79bool SuggestionsSource::ShouldServiceRequest(
80    const net::URLRequest* request) const {
81  if (request->url().SchemeIs(chrome::kChromeSearchScheme))
82    return InstantIOContext::ShouldServiceRequest(request);
83  return URLDataSource::ShouldServiceRequest(request);
84}
85
86void SuggestionsSource::OnSuggestionsAvailable(
87    const content::URLDataSource::GotDataCallback& callback,
88    const SuggestionsProfile& suggestions_profile) {
89  // Render HTML.
90  std::vector<std::string> out;
91  out.push_back(kHtmlHeader);
92  out.push_back(kHtmlBody);
93  out.push_back("<h1>Suggestions</h1>\n");
94
95  size_t size = suggestions_profile.suggestions_size();
96  if (size == 0) {
97    out.push_back("<p>You have no suggestions.</p>\n");
98  } else {
99    out.push_back("<ol>\n");
100    for (size_t i = 0; i < size; ++i) {
101      const ChromeSuggestion& suggestion = suggestions_profile.suggestions(i);
102      std::string line;
103      line.append("<li><a href=\"");
104      line.append(net::EscapeForHTML(suggestion.url()));
105      line.append("\" target=\"_blank\">");
106      line.append(net::EscapeForHTML(suggestion.title()));
107      line.append("</a></li>\n");
108      out.push_back(line);
109    }
110    out.push_back("</ol>\n");
111  }
112  out.push_back(kHtmlFooter);
113
114  std::string out_html = JoinString(out, "");
115  callback.Run(base::RefCountedString::TakeString(&out_html));
116}
117
118}  // namespace suggestions
119