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_page.h" 6 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/strings/string_util.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "grit/component_resources.h" 14 #include "third_party/dom_distiller_js/dom_distiller.pb.h" 15 #include "third_party/dom_distiller_js/dom_distiller_json_converter.h" 16 #include "ui/base/resource/resource_bundle.h" 17 #include "url/gurl.h" 18 19 namespace dom_distiller { 20 21 namespace { 22 23 const char* kOptionsPlaceholder = "$$OPTIONS"; 24 25 std::string GetDistillerScriptWithOptions( 26 const dom_distiller::proto::DomDistillerOptions& options) { 27 std::string script = ResourceBundle::GetSharedInstance() 28 .GetRawDataResource(IDR_DISTILLER_JS) 29 .as_string(); 30 if (script.empty()) { 31 return ""; 32 } 33 34 scoped_ptr<base::Value> options_value( 35 dom_distiller::proto::json::DomDistillerOptions::WriteToValue(options)); 36 std::string options_json; 37 if (!base::JSONWriter::Write(options_value.get(), &options_json)) { 38 NOTREACHED(); 39 } 40 size_t options_offset = script.find(kOptionsPlaceholder); 41 DCHECK_NE(std::string::npos, options_offset); 42 DCHECK_EQ(std::string::npos, 43 script.find(kOptionsPlaceholder, options_offset + 1)); 44 script = 45 script.replace(options_offset, strlen(kOptionsPlaceholder), options_json); 46 return script; 47 } 48 49 } 50 51 DistilledPageInfo::DistilledPageInfo() {} 52 53 DistilledPageInfo::~DistilledPageInfo() {} 54 55 DistillerPageFactory::~DistillerPageFactory() {} 56 57 DistillerPage::DistillerPage() : ready_(true) {} 58 59 DistillerPage::~DistillerPage() {} 60 61 void DistillerPage::DistillPage( 62 const GURL& gurl, 63 const dom_distiller::proto::DomDistillerOptions options, 64 const DistillerPageCallback& callback) { 65 DCHECK(ready_); 66 // It is only possible to distill one page at a time. |ready_| is reset when 67 // the callback to OnDistillationDone happens. 68 ready_ = false; 69 distiller_page_callback_ = callback; 70 DistillPageImpl(gurl, GetDistillerScriptWithOptions(options)); 71 } 72 73 void DistillerPage::OnDistillationDone(const GURL& page_url, 74 const base::Value* value) { 75 DCHECK(!ready_); 76 ready_ = true; 77 78 scoped_ptr<DistilledPageInfo> page_info(new DistilledPageInfo()); 79 bool found_content = !value->IsType(base::Value::TYPE_NULL); 80 if (found_content) { 81 dom_distiller::proto::DomDistillerResult distiller_result = 82 dom_distiller::proto::json::DomDistillerResult::ReadFromValue(value); 83 84 page_info->title = distiller_result.title(); 85 page_info->html = distiller_result.distilled_content().html(); 86 page_info->next_page_url = distiller_result.pagination_info().next_page(); 87 page_info->prev_page_url = distiller_result.pagination_info().prev_page(); 88 for (int i = 0; i < distiller_result.image_urls_size(); ++i) { 89 const std::string image_url = distiller_result.image_urls(i); 90 if (GURL(image_url).is_valid()) { 91 page_info->image_urls.push_back(image_url); 92 } 93 } 94 } 95 96 base::MessageLoop::current()->PostTask( 97 FROM_HERE, 98 base::Bind( 99 distiller_page_callback_, base::Passed(&page_info), found_content)); 100 } 101 102 } // namespace dom_distiller 103