Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: components/dom_distiller/ios/distiller_page_ios.mm

Issue 2327783002: Fix domdistiller for new JS execution (Closed)
Patch Set: comments test Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/dom_distiller/ios/distiller_page_ios.h" 5 #include "components/dom_distiller/ios/distiller_page_ios.h"
6 6
7 #import <UIKit/UIKit.h> 7 #import <UIKit/UIKit.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/json/json_reader.h" 11 #include "base/json/json_reader.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/mac/foundation_util.h"
14 #include "base/memory/ptr_util.h"
13 #include "base/strings/sys_string_conversions.h" 15 #include "base/strings/sys_string_conversions.h"
14 #include "base/values.h" 16 #include "base/values.h"
15 #include "ios/public/provider/web/web_controller_provider.h" 17 #include "ios/public/provider/web/web_controller_provider.h"
16 #include "ios/web/public/browser_state.h" 18 #include "ios/web/public/browser_state.h"
17 19
20 namespace {
21
22 // This is duplicated here from ios/web/web_state/ui/web_view_js_utils.mm in
23 // order to handle numbers. The dom distiller proto expects integers and the
24 // generated JSON deserializer does not accept doubles in the place of ints.
25 // However WKWebView only allows us to return "numbers." We need to create
Eugene But (OOO till 7-30) 2016/09/19 21:52:27 NIT: Please avoid using "we" and generally pronoun
lody 2016/09/20 13:41:37 Done.
26 // integers and doubles as expected by the proto, which is done by checking if
27 // the number has a fraction or not; since this is a hacky method it's isolated
28 // to this file so as to limit the risk of broken JS calls.
29
30 int const kMaximumParsingRecursionDepth = 6;
31 // Converts result of WKWebView script evaluation to base::Value, parsing
32 // |wk_result| up to a depth of |max_depth|.
33 std::unique_ptr<base::Value> ValueResultFromScriptResult(id wk_result,
34 int max_depth) {
35 if (!wk_result)
36 return nullptr;
37
38 std::unique_ptr<base::Value> result;
39
40 if (max_depth < 0) {
41 DLOG(WARNING) << "JS maximum recursion depth exceeded.";
42 return result;
43 }
44
45 CFTypeID result_type = CFGetTypeID(wk_result);
46 if (result_type == CFStringGetTypeID()) {
47 result.reset(new base::StringValue(base::SysNSStringToUTF16(wk_result)));
48 DCHECK(result->IsType(base::Value::TYPE_STRING));
49 } else if (result_type == CFNumberGetTypeID()) {
50 // Different implementation is here.
51 if ([wk_result intValue] != [wk_result doubleValue]) {
52 result.reset(new base::FundamentalValue([wk_result doubleValue]));
53 DCHECK(result->IsType(base::Value::TYPE_DOUBLE));
54 } else {
55 result.reset(new base::FundamentalValue([wk_result intValue]));
56 DCHECK(result->IsType(base::Value::TYPE_INTEGER));
57 }
58 // End of different implementation.
59 } else if (result_type == CFBooleanGetTypeID()) {
60 result.reset(
61 new base::FundamentalValue(static_cast<bool>([wk_result boolValue])));
62 DCHECK(result->IsType(base::Value::TYPE_BOOLEAN));
63 } else if (result_type == CFNullGetTypeID()) {
64 result = base::Value::CreateNullValue();
65 DCHECK(result->IsType(base::Value::TYPE_NULL));
66 } else if (result_type == CFDictionaryGetTypeID()) {
67 std::unique_ptr<base::DictionaryValue> dictionary =
68 base::MakeUnique<base::DictionaryValue>();
69 for (id key in wk_result) {
70 NSString* obj_c_string = base::mac::ObjCCast<NSString>(key);
71 const std::string path = base::SysNSStringToUTF8(obj_c_string);
72 std::unique_ptr<base::Value> value =
73 ValueResultFromScriptResult(wk_result[obj_c_string], max_depth - 1);
74 if (value) {
75 dictionary->Set(path, std::move(value));
76 }
77 }
78 result = std::move(dictionary);
79 } else if (result_type == CFArrayGetTypeID()) {
80 std::unique_ptr<base::ListValue> list = base::MakeUnique<base::ListValue>();
81 for (id value in wk_result) {
82 list->Append(ValueResultFromScriptResult(value, max_depth - 1));
83 }
84 result = std::move(list);
85 } else {
86 NOTREACHED(); // Convert other types as needed.
87 }
88 return result;
89 }
90 }
91
18 namespace dom_distiller { 92 namespace dom_distiller {
19 93
20 // Helper class for observing the loading of URLs to distill. 94 // Helper class for observing the loading of URLs to distill.
21 class DistillerWebStateObserver : public web::WebStateObserver { 95 class DistillerWebStateObserver : public web::WebStateObserver {
22 public: 96 public:
23 DistillerWebStateObserver(web::WebState* web_state, 97 DistillerWebStateObserver(web::WebState* web_state,
24 DistillerPageIOS* distiller_page); 98 DistillerPageIOS* distiller_page);
25 99
26 // WebStateObserver implementation: 100 // WebStateObserver implementation:
27 void PageLoaded( 101 void PageLoaded(
(...skipping 19 matching lines...) Expand all
47 #pragma mark - 121 #pragma mark -
48 122
49 DistillerPageIOS::DistillerPageIOS(web::BrowserState* browser_state) 123 DistillerPageIOS::DistillerPageIOS(web::BrowserState* browser_state)
50 : browser_state_(browser_state), weak_ptr_factory_(this) { 124 : browser_state_(browser_state), weak_ptr_factory_(this) {
51 } 125 }
52 126
53 DistillerPageIOS::~DistillerPageIOS() { 127 DistillerPageIOS::~DistillerPageIOS() {
54 } 128 }
55 129
56 bool DistillerPageIOS::StringifyOutput() { 130 bool DistillerPageIOS::StringifyOutput() {
57 // UIWebView requires JavaScript to return a single string value. 131 return false;
58 return true;
59 } 132 }
60 133
61 void DistillerPageIOS::DistillPageImpl(const GURL& url, 134 void DistillerPageIOS::DistillPageImpl(const GURL& url,
62 const std::string& script) { 135 const std::string& script) {
63 if (!url.is_valid() || !script.length()) 136 if (!url.is_valid() || !script.length())
64 return; 137 return;
65 url_ = url; 138 url_ = url;
66 script_ = script; 139 script_ = script;
67 140
68 // Lazily create provider. 141 // Lazily create provider.
(...skipping 13 matching lines...) Expand all
82 else 155 else
83 OnLoadURLDone(web::PageLoadCompletionStatus::FAILURE); 156 OnLoadURLDone(web::PageLoadCompletionStatus::FAILURE);
84 } 157 }
85 158
86 void DistillerPageIOS::OnLoadURLDone( 159 void DistillerPageIOS::OnLoadURLDone(
87 web::PageLoadCompletionStatus load_completion_status) { 160 web::PageLoadCompletionStatus load_completion_status) {
88 // Don't attempt to distill if the page load failed or if there is no 161 // Don't attempt to distill if the page load failed or if there is no
89 // provider. 162 // provider.
90 if (load_completion_status == web::PageLoadCompletionStatus::FAILURE || 163 if (load_completion_status == web::PageLoadCompletionStatus::FAILURE ||
91 !provider_) { 164 !provider_) {
92 HandleJavaScriptResultString(@""); 165 HandleJavaScriptResult(nil);
93 return; 166 return;
94 } 167 }
95 168
96 // Inject the script. 169 // Inject the script.
97 base::WeakPtr<DistillerPageIOS> weak_this = weak_ptr_factory_.GetWeakPtr(); 170 base::WeakPtr<DistillerPageIOS> weak_this = weak_ptr_factory_.GetWeakPtr();
98 provider_->InjectScript(script_, ^(NSString* string, NSError* error) { 171 provider_->InjectScript(script_, ^(id result, NSError* error) {
99 DistillerPageIOS* distiller_page = weak_this.get(); 172 DistillerPageIOS* distiller_page = weak_this.get();
100 if (distiller_page) 173 if (distiller_page)
101 distiller_page->HandleJavaScriptResultString(string); 174 distiller_page->HandleJavaScriptResult(result);
102 }); 175 });
103 } 176 }
104 177
105 void DistillerPageIOS::HandleJavaScriptResultString(NSString* result) { 178 void DistillerPageIOS::HandleJavaScriptResult(id result) {
106 std::unique_ptr<base::Value> resultValue = base::Value::CreateNullValue(); 179 std::unique_ptr<base::Value> resultValue = base::Value::CreateNullValue();
107 if (result.length) { 180 if (result) {
108 std::unique_ptr<base::Value> dictionaryValue = 181 resultValue = ValueResultFromScriptResult(result);
109 base::JSONReader::Read(base::SysNSStringToUTF8(result));
110 if (dictionaryValue &&
111 dictionaryValue->IsType(base::Value::TYPE_DICTIONARY)) {
112 resultValue = std::move(dictionaryValue);
113 }
114 } 182 }
115 OnDistillationDone(url_, resultValue.get()); 183 OnDistillationDone(url_, resultValue.get());
116 } 184 }
117 185
186 std::unique_ptr<base::Value> DistillerPageIOS::ValueResultFromScriptResult(
187 id wk_result) {
188 return ::ValueResultFromScriptResult(wk_result,
189 kMaximumParsingRecursionDepth);
190 }
118 } // namespace dom_distiller 191 } // namespace dom_distiller
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698