Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / components / dom_distiller / core / distiller.cc
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.
4
5 #include "components/dom_distiller/core/distiller.h"
6
7 #include <map>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "components/dom_distiller/core/distiller_page.h"
15 #include "components/dom_distiller/core/distiller_url_fetcher.h"
16 #include "components/dom_distiller/core/proto/distilled_page.pb.h"
17 #include "grit/dom_distiller_resources.h"
18 #include "net/url_request/url_request_context_getter.h"
19 #include "ui/base/resource/resource_bundle.h"
20 #include "url/gurl.h"
21
22 namespace dom_distiller {
23
24 DistillerFactoryImpl::DistillerFactoryImpl(
25     scoped_ptr<DistillerPageFactory> distiller_page_factory,
26     scoped_ptr<DistillerURLFetcherFactory> distiller_url_fetcher_factory)
27   : distiller_page_factory_(distiller_page_factory.Pass()),
28     distiller_url_fetcher_factory_(distiller_url_fetcher_factory.Pass()) {}
29
30 DistillerFactoryImpl::~DistillerFactoryImpl() {}
31
32 scoped_ptr<Distiller> DistillerFactoryImpl::CreateDistiller() {
33   scoped_ptr<DistillerImpl> distiller(new DistillerImpl(
34       *distiller_page_factory_, *distiller_url_fetcher_factory_));
35   distiller->Init();
36   return distiller.PassAs<Distiller>();
37 }
38
39 DistillerImpl::DistillerImpl(
40     const DistillerPageFactory& distiller_page_factory,
41     const DistillerURLFetcherFactory& distiller_url_fetcher_factory)
42   : distiller_page_factory_(distiller_page_factory),
43     distiller_url_fetcher_factory_(distiller_url_fetcher_factory) {
44   distiller_page_ = distiller_page_factory_.CreateDistillerPage(this).Pass();
45 }
46
47 DistillerImpl::~DistillerImpl() {
48 }
49
50 void DistillerImpl::Init() {
51   distiller_page_->Init();
52 }
53
54 void DistillerImpl::DistillPage(const GURL& url,
55                             const DistillerCallback& distillation_cb) {
56   distillation_cb_ = distillation_cb;
57   proto_.reset(new DistilledPageProto());
58   proto_->set_url(url.spec());
59   LoadURL(url);
60 }
61
62 void DistillerImpl::LoadURL(const GURL& url) {
63   distiller_page_->LoadURL(url);
64 }
65
66 void DistillerImpl::OnLoadURLDone() {
67   GetDistilledContent();
68 }
69
70 void DistillerImpl::GetDistilledContent() {
71   std::string script =
72       ResourceBundle::GetSharedInstance().GetRawDataResource(
73           IDR_DISTILLER_JS).as_string();
74   distiller_page_->ExecuteJavaScript(script);
75 }
76
77 void DistillerImpl::OnExecuteJavaScriptDone(const base::Value* value) {
78   std::string result;
79   bool fetched_image = false;
80   const base::ListValue* result_list = NULL;
81   if (!value->GetAsList(&result_list)) {
82     DCHECK(proto_);
83     distillation_cb_.Run(proto_.Pass());
84     return;
85   }
86   int i = 0;
87   for (base::ListValue::const_iterator iter = result_list->begin();
88       iter != result_list->end(); ++iter, ++i) {
89     std::string item;
90     (*iter)->GetAsString(&item);
91     // The JavaScript returns an array where the first element is the title,
92     // the second element is the article content HTML, and the remaining
93     // elements are image URLs referenced in the HTML.
94     switch (i) {
95       case 0:
96         proto_->set_title(item);
97         break;
98       case 1:
99         proto_->set_html(item);
100         break;
101       default:
102         int image_number = i - 2;
103         std::string image_id = base::StringPrintf("%d", image_number);
104         FetchImage(image_id, item);
105         fetched_image = true;
106     }
107   }
108   if (!fetched_image)
109     distillation_cb_.Run(proto_.Pass());
110 }
111
112 void DistillerImpl::FetchImage(const std::string& image_id,
113                                const std::string& item) {
114   DistillerURLFetcher* fetcher =
115       distiller_url_fetcher_factory_.CreateDistillerURLFetcher();
116   image_fetchers_[image_id] = fetcher;
117   fetcher->FetchURL(item,
118                     base::Bind(&DistillerImpl::OnFetchImageDone,
119                                base::Unretained(this), image_id));
120 }
121
122 void DistillerImpl::OnFetchImageDone(const std::string& id,
123                                      const std::string& response) {
124   DCHECK(proto_);
125   DistilledPageProto_Image* image = proto_->add_image();
126   image->set_name(id);
127   image->set_data(response);
128   DCHECK(image_fetchers_.end() != image_fetchers_.find(id));
129   DistillerURLFetcher* fetcher = image_fetchers_[id];
130   int result = image_fetchers_.erase(id);
131   delete fetcher;
132   DCHECK_EQ(1, result);
133   if (image_fetchers_.empty()) {
134     distillation_cb_.Run(proto_.Pass());
135   }
136 }
137
138 }  // namespace dom_distiller