Add abhijeet.k@samsung.com to AUTHORS list.
[chromium-blink-merge.git] / components / dom_distiller / core / distiller_page.cc
blobb8bcd28ff8ea524faed199e3a185be1c86dfd71c
1 // Copyright 2013 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/distiller_page.h"
7 #include "base/bind.h"
8 #include "base/json/json_writer.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/metrics/histogram.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/time/time.h"
15 #include "grit/components_resources.h"
16 #include "third_party/dom_distiller_js/dom_distiller.pb.h"
17 #include "third_party/dom_distiller_js/dom_distiller_json_converter.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "url/gurl.h"
21 namespace dom_distiller {
23 namespace {
25 const char* kOptionsPlaceholder = "$$OPTIONS";
26 const char* kStringifyPlaceholder = "$$STRINGIFY";
27 const char* kNewContextPlaceholder = "$$NEW_CONTEXT";
29 std::string GetDistillerScriptWithOptions(
30 const dom_distiller::proto::DomDistillerOptions& options,
31 bool stringify_output,
32 bool create_new_context) {
33 std::string script = ResourceBundle::GetSharedInstance()
34 .GetRawDataResource(IDR_DISTILLER_JS)
35 .as_string();
36 if (script.empty()) {
37 return "";
40 scoped_ptr<base::Value> options_value(
41 dom_distiller::proto::json::DomDistillerOptions::WriteToValue(options));
42 std::string options_json;
43 if (!base::JSONWriter::Write(options_value.get(), &options_json)) {
44 NOTREACHED();
46 size_t options_offset = script.find(kOptionsPlaceholder);
47 DCHECK_NE(std::string::npos, options_offset);
48 DCHECK_EQ(std::string::npos,
49 script.find(kOptionsPlaceholder, options_offset + 1));
50 script =
51 script.replace(options_offset, strlen(kOptionsPlaceholder), options_json);
53 std::string stringify = stringify_output ? "true" : "false";
54 size_t stringify_offset = script.find(kStringifyPlaceholder);
55 DCHECK_NE(std::string::npos, stringify_offset);
56 DCHECK_EQ(std::string::npos,
57 script.find(kStringifyPlaceholder, stringify_offset + 1));
58 script = script.replace(stringify_offset,
59 strlen(kStringifyPlaceholder),
60 stringify);
62 std::string new_context = create_new_context ? "true" : "false";
63 size_t new_context_offset = script.find(kNewContextPlaceholder);
64 DCHECK_NE(std::string::npos, new_context_offset);
65 DCHECK_EQ(std::string::npos,
66 script.find(kNewContextPlaceholder, new_context_offset + 1));
67 script = script.replace(new_context_offset,
68 strlen(kNewContextPlaceholder),
69 new_context);
71 return script;
76 DistillerPageFactory::~DistillerPageFactory() {}
78 DistillerPage::DistillerPage() : ready_(true) {}
80 DistillerPage::~DistillerPage() {}
82 void DistillerPage::DistillPage(
83 const GURL& gurl,
84 const dom_distiller::proto::DomDistillerOptions options,
85 const DistillerPageCallback& callback) {
86 DCHECK(ready_);
87 // It is only possible to distill one page at a time. |ready_| is reset when
88 // the callback to OnDistillationDone happens.
89 ready_ = false;
90 distiller_page_callback_ = callback;
91 DistillPageImpl(gurl, GetDistillerScriptWithOptions(options,
92 StringifyOutput(),
93 CreateNewContext()));
96 void DistillerPage::OnDistillationDone(const GURL& page_url,
97 const base::Value* value) {
98 DCHECK(!ready_);
99 ready_ = true;
101 scoped_ptr<dom_distiller::proto::DomDistillerResult> distiller_result(
102 new dom_distiller::proto::DomDistillerResult());
103 bool found_content;
104 if (value->IsType(base::Value::TYPE_NULL)) {
105 found_content = false;
106 } else {
107 found_content =
108 dom_distiller::proto::json::DomDistillerResult::ReadFromValue(
109 value, distiller_result.get());
110 if (!found_content) {
111 DVLOG(1) << "Unable to parse DomDistillerResult.";
112 } else {
113 if (distiller_result->has_timing_info()) {
114 const dom_distiller::proto::TimingInfo& timing =
115 distiller_result->timing_info();
116 if (timing.has_markup_parsing_time()) {
117 UMA_HISTOGRAM_TIMES(
118 "DomDistiller.Time.MarkupParsing",
119 base::TimeDelta::FromMillisecondsD(timing.markup_parsing_time()));
121 if (timing.has_document_construction_time()) {
122 UMA_HISTOGRAM_TIMES(
123 "DomDistiller.Time.DocumentConstruction",
124 base::TimeDelta::FromMillisecondsD(
125 timing.document_construction_time()));
127 if (timing.has_article_processing_time()) {
128 UMA_HISTOGRAM_TIMES(
129 "DomDistiller.Time.ArticleProcessing",
130 base::TimeDelta::FromMillisecondsD(
131 timing.article_processing_time()));
133 if (timing.has_formatting_time()) {
134 UMA_HISTOGRAM_TIMES(
135 "DomDistiller.Time.Formatting",
136 base::TimeDelta::FromMillisecondsD(timing.formatting_time()));
138 if (timing.has_total_time()) {
139 UMA_HISTOGRAM_TIMES(
140 "DomDistiller.Time.DistillationTotal",
141 base::TimeDelta::FromMillisecondsD(timing.total_time()));
144 if (distiller_result->has_statistics_info()) {
145 const dom_distiller::proto::StatisticsInfo& statistics =
146 distiller_result->statistics_info();
147 if (statistics.has_word_count()) {
148 UMA_HISTOGRAM_CUSTOM_COUNTS(
149 "DomDistiller.Statistics.WordCount",
150 statistics.word_count(),
151 1, 4000, 50);
157 base::MessageLoop::current()->PostTask(
158 FROM_HERE,
159 base::Bind(distiller_page_callback_,
160 base::Passed(&distiller_result),
161 found_content));
164 } // namespace dom_distiller