Add abhijeet.k@samsung.com to AUTHORS list.
[chromium-blink-merge.git] / components / dom_distiller / ios / distiller_page_ios.mm
blobbdf41087079c5c68539af796214980b3beee25da
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/ios/distiller_page_ios.h"
7 #import <UIKit/UIKit.h>
9 #include "base/json/json_reader.h"
10 #include "base/logging.h"
11 #include "base/strings/sys_string_conversions.h"
12 #include "base/values.h"
13 #include "ios/public/provider/web/web_controller_provider.h"
14 #include "ios/web/public/browser_state.h"
16 namespace dom_distiller {
18 // Helper class for observing the loading of URLs to distill.
19 class DistillerWebStateObserver : public web::WebStateObserver {
20  public:
21   DistillerWebStateObserver(web::WebState* web_state,
22                             DistillerPageIOS* distiller_page);
24   // WebStateObserver implementation:
25   void PageLoaded(
26       web::PageLoadCompletionStatus load_completion_status) override;
28  private:
29   DistillerPageIOS* distiller_page_;  // weak, owns this object.
32 DistillerWebStateObserver::DistillerWebStateObserver(
33     web::WebState* web_state,
34     DistillerPageIOS* distiller_page)
35     : web::WebStateObserver(web_state), distiller_page_(distiller_page) {
36   DCHECK(web_state);
37   DCHECK(distiller_page_);
40 void DistillerWebStateObserver::PageLoaded(
41     web::PageLoadCompletionStatus load_completion_status) {
42   distiller_page_->OnLoadURLDone(load_completion_status);
45 #pragma mark -
47 DistillerPageIOS::DistillerPageIOS(web::BrowserState* browser_state)
48     : browser_state_(browser_state), weak_ptr_factory_(this) {
51 DistillerPageIOS::~DistillerPageIOS() {
54 bool DistillerPageIOS::StringifyOutput() {
55  // UIWebView requires JavaScript to return a single string value.
56  return true;
59 bool DistillerPageIOS::CreateNewContext() {
60   // UIWebView's JavaScript engine has a bug that causes crashes when
61   // creating a separate window object, so allow the script to run directly
62   // in the window until a better solution is created.
63   // TODO(kkhorimoto): investigate whether this is necessary for WKWebView.
64  return false;
67 void DistillerPageIOS::DistillPageImpl(const GURL& url,
68                                        const std::string& script) {
69   if (!url.is_valid() || !script.length())
70     return;
71   url_ = url;
72   script_ = script;
74   // Lazily create provider.
75   if (!provider_) {
76     if (ios::GetWebControllerProviderFactory()) {
77       provider_ =
78           ios::GetWebControllerProviderFactory()->CreateWebControllerProvider(
79               browser_state_);
80       web_state_observer_.reset(
81           new DistillerWebStateObserver(provider_->GetWebState(), this));
82     }
83   }
85   // Load page using provider.
86   if (provider_)
87     provider_->LoadURL(url_);
88   else
89     OnLoadURLDone(web::PageLoadCompletionStatus::FAILURE);
92 void DistillerPageIOS::OnLoadURLDone(
93     web::PageLoadCompletionStatus load_completion_status) {
94   // Don't attempt to distill if the page load failed or if there is no
95   // provider.
96   if (load_completion_status == web::PageLoadCompletionStatus::FAILURE ||
97       !provider_) {
98     HandleJavaScriptResultString(@"");
99     return;
100   }
102   // Inject the script.
103   base::WeakPtr<DistillerPageIOS> weak_this = weak_ptr_factory_.GetWeakPtr();
104   provider_->InjectScript(script_, ^(NSString* string, NSError* error) {
105     DistillerPageIOS* distiller_page = weak_this.get();
106     if (distiller_page)
107       distiller_page->HandleJavaScriptResultString(string);
108   });
111 void DistillerPageIOS::HandleJavaScriptResultString(NSString* result) {
112   scoped_ptr<base::Value> resultValue(base::Value::CreateNullValue());
113   if (result.length) {
114     scoped_ptr<base::Value> dictionaryValue(
115         base::JSONReader::Read(base::SysNSStringToUTF8(result)));
116     if (dictionaryValue &&
117         dictionaryValue->IsType(base::Value::TYPE_DICTIONARY)) {
118       resultValue = dictionaryValue.Pass();
119     }
120   }
121   OnDistillationDone(url_, resultValue.get());
124 }  // namespace dom_distiller