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