Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / components / dom_distiller / core / viewer.cc
blob57d547320558cdde5e4f44f212c234aa658fa6ee
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.
5 #include "components/dom_distiller/core/viewer.h"
7 #include <string>
8 #include <vector>
10 #include "base/json/json_writer.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/string_util.h"
13 #include "components/dom_distiller/core/distilled_page_prefs.h"
14 #include "components/dom_distiller/core/dom_distiller_service.h"
15 #include "components/dom_distiller/core/proto/distilled_article.pb.h"
16 #include "components/dom_distiller/core/proto/distilled_page.pb.h"
17 #include "components/dom_distiller/core/task_tracker.h"
18 #include "components/dom_distiller/core/url_constants.h"
19 #include "components/dom_distiller/core/url_utils.h"
20 #include "grit/component_resources.h"
21 #include "grit/components_strings.h"
22 #include "net/base/escape.h"
23 #include "net/url_request/url_request.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/base/resource/resource_bundle.h"
26 #include "url/gurl.h"
28 namespace dom_distiller {
30 namespace {
32 // JS Themes. Must agree with useTheme() in dom_distiller_viewer.js.
33 const char kDarkJsTheme[] = "dark";
34 const char kLightJsTheme[] = "light";
35 const char kSepiaJsTheme[] = "sepia";
37 // CSS Theme classes. Must agree with classes in distilledpage.css.
38 const char kDarkCssClass[] = "dark";
39 const char kLightCssClass[] = "light";
40 const char kSepiaCssClass[] = "sepia";
42 // JS FontFamilies. Must agree with useFontFamily() in dom_distiller_viewer.js.
43 const char kSerifJsFontFamily[] = "serif";
44 const char kSansSerifJsFontFamily[] = "sans-serif";
45 const char kMonospaceJsFontFamily[] = "monospace";
47 // CSS FontFamily classes. Must agree with classes in distilledpage.css.
48 const char kSerifCssClass[] = "serif";
49 const char kSansSerifCssClass[] = "sans-serif";
50 const char kMonospaceCssClass[] = "monospace";
52 // Maps themes to JS themes.
53 const std::string GetJsTheme(DistilledPagePrefs::Theme theme) {
54 if (theme == DistilledPagePrefs::DARK) {
55 return kDarkJsTheme;
56 } else if (theme == DistilledPagePrefs::SEPIA) {
57 return kSepiaJsTheme;
59 return kLightJsTheme;
62 // Maps themes to CSS classes.
63 const std::string GetThemeCssClass(DistilledPagePrefs::Theme theme) {
64 if (theme == DistilledPagePrefs::DARK) {
65 return kDarkCssClass;
66 } else if (theme == DistilledPagePrefs::SEPIA) {
67 return kSepiaCssClass;
69 return kLightCssClass;
72 // Maps font families to JS font families.
73 const std::string GetJsFontFamily(DistilledPagePrefs::FontFamily font_family) {
74 if (font_family == DistilledPagePrefs::SERIF) {
75 return kSerifJsFontFamily;
76 } else if (font_family == DistilledPagePrefs::MONOSPACE) {
77 return kMonospaceJsFontFamily;
79 return kSansSerifJsFontFamily;
82 // Maps fontFamilies to CSS fontFamily classes.
83 const std::string GetFontCssClass(DistilledPagePrefs::FontFamily font_family) {
84 if (font_family == DistilledPagePrefs::SERIF) {
85 return kSerifCssClass;
86 } else if (font_family == DistilledPagePrefs::MONOSPACE) {
87 return kMonospaceCssClass;
89 return kSansSerifCssClass;
92 std::string ReplaceHtmlTemplateValues(
93 const std::string& title,
94 const std::string& content,
95 const std::string& loading_indicator_class,
96 const std::string& original_url,
97 const DistilledPagePrefs::Theme theme,
98 const DistilledPagePrefs::FontFamily font_family) {
99 base::StringPiece html_template =
100 ResourceBundle::GetSharedInstance().GetRawDataResource(
101 IDR_DOM_DISTILLER_VIEWER_HTML);
102 std::vector<std::string> substitutions;
103 substitutions.push_back(title); // $1
104 substitutions.push_back(kViewerCssPath); // $2
105 substitutions.push_back(kViewerJsPath); // $3
106 substitutions.push_back(GetThemeCssClass(theme) + " " +
107 GetFontCssClass(font_family)); // $4
108 substitutions.push_back(content); // $5
109 substitutions.push_back(loading_indicator_class); // $6
110 substitutions.push_back(original_url); // $7
111 substitutions.push_back(
112 l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_VIEW_ORIGINAL)); // $8
113 return ReplaceStringPlaceholders(html_template, substitutions, NULL);
116 } // namespace
118 namespace viewer {
120 const std::string GetUnsafeIncrementalDistilledPageJs(
121 const DistilledPageProto* page_proto,
122 const bool is_last_page) {
123 std::string output;
124 base::StringValue value(page_proto->html());
125 base::JSONWriter::Write(&value, &output);
126 std::string page_update("addToPage(");
127 page_update += output + ");";
128 return page_update + GetToggleLoadingIndicatorJs(
129 is_last_page);
133 const std::string GetToggleLoadingIndicatorJs(const bool is_last_page) {
134 if (is_last_page)
135 return "showLoadingIndicator(true);";
136 else
137 return "showLoadingIndicator(false);";
140 const std::string GetUnsafePartialArticleHtml(
141 const DistilledPageProto* page_proto,
142 const DistilledPagePrefs::Theme theme,
143 const DistilledPagePrefs::FontFamily font_family) {
144 DCHECK(page_proto);
145 std::string title = net::EscapeForHTML(page_proto->title());
146 std::ostringstream unsafe_output_stream;
147 unsafe_output_stream << page_proto->html();
148 std::string unsafe_article_html = unsafe_output_stream.str();
149 std::string original_url = page_proto->url();
150 return ReplaceHtmlTemplateValues(
151 title, unsafe_article_html, "visible", original_url, theme, font_family);
154 const std::string GetUnsafeArticleHtml(
155 const DistilledArticleProto* article_proto,
156 const DistilledPagePrefs::Theme theme,
157 const DistilledPagePrefs::FontFamily font_family) {
158 DCHECK(article_proto);
159 std::string title;
160 std::string unsafe_article_html;
161 if (article_proto->has_title() && article_proto->pages_size() > 0 &&
162 article_proto->pages(0).has_html()) {
163 title = net::EscapeForHTML(article_proto->title());
164 std::ostringstream unsafe_output_stream;
165 for (int page_num = 0; page_num < article_proto->pages_size(); ++page_num) {
166 unsafe_output_stream << article_proto->pages(page_num).html();
168 unsafe_article_html = unsafe_output_stream.str();
169 } else {
170 title = l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_TITLE);
171 unsafe_article_html =
172 l10n_util::GetStringUTF8(IDS_DOM_DISTILLER_VIEWER_NO_DATA_CONTENT);
175 std::string original_url;
176 if (article_proto->pages_size() > 0 && article_proto->pages(0).has_url()) {
177 original_url = article_proto->pages(0).url();
180 return ReplaceHtmlTemplateValues(
181 title, unsafe_article_html, "hidden", original_url, theme, font_family);
184 const std::string GetErrorPageHtml(
185 const DistilledPagePrefs::Theme theme,
186 const DistilledPagePrefs::FontFamily font_family) {
187 std::string title = l10n_util::GetStringUTF8(
188 IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_TITLE);
189 std::string content = l10n_util::GetStringUTF8(
190 IDS_DOM_DISTILLER_VIEWER_FAILED_TO_FIND_ARTICLE_CONTENT);
191 return ReplaceHtmlTemplateValues(
192 title, content, "hidden", "", theme, font_family);
195 const std::string GetCss() {
196 return ResourceBundle::GetSharedInstance().GetRawDataResource(
197 IDR_DISTILLER_CSS).as_string();
200 const std::string GetJavaScript() {
201 return ResourceBundle::GetSharedInstance()
202 .GetRawDataResource(IDR_DOM_DISTILLER_VIEWER_JS)
203 .as_string();
206 scoped_ptr<ViewerHandle> CreateViewRequest(
207 DomDistillerServiceInterface* dom_distiller_service,
208 const std::string& path,
209 ViewRequestDelegate* view_request_delegate,
210 const gfx::Size& render_view_size) {
211 std::string entry_id =
212 url_utils::GetValueForKeyInUrlPathQuery(path, kEntryIdKey);
213 bool has_valid_entry_id = !entry_id.empty();
214 entry_id = StringToUpperASCII(entry_id);
216 std::string requested_url_str =
217 url_utils::GetValueForKeyInUrlPathQuery(path, kUrlKey);
218 GURL requested_url(requested_url_str);
219 bool has_valid_url = url_utils::IsUrlDistillable(requested_url);
221 if (has_valid_entry_id && has_valid_url) {
222 // It is invalid to specify a query param for both |kEntryIdKey| and
223 // |kUrlKey|.
224 return scoped_ptr<ViewerHandle>();
227 if (has_valid_entry_id) {
228 return dom_distiller_service->ViewEntry(
229 view_request_delegate,
230 dom_distiller_service->CreateDefaultDistillerPage(render_view_size),
231 entry_id).Pass();
232 } else if (has_valid_url) {
233 return dom_distiller_service->ViewUrl(
234 view_request_delegate,
235 dom_distiller_service->CreateDefaultDistillerPage(render_view_size),
236 requested_url).Pass();
239 // It is invalid to not specify a query param for |kEntryIdKey| or |kUrlKey|.
240 return scoped_ptr<ViewerHandle>();
243 const std::string GetDistilledPageThemeJs(DistilledPagePrefs::Theme theme) {
244 return "useTheme('" + GetJsTheme(theme) + "');";
247 const std::string GetDistilledPageFontFamilyJs(
248 DistilledPagePrefs::FontFamily font_family) {
249 return "useFontFamily('" + GetJsFontFamily(font_family) + "');";
252 } // namespace viewer
254 } // namespace dom_distiller