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

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

Issue 2327783002: Fix domdistiller for new JS execution (Closed)
Patch Set: 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/memory/ptr_util.h"
13 #include "base/strings/sys_string_conversions.h" 14 #include "base/strings/sys_string_conversions.h"
14 #include "base/values.h" 15 #include "base/values.h"
15 #include "ios/public/provider/web/web_controller_provider.h" 16 #include "ios/public/provider/web/web_controller_provider.h"
16 #include "ios/web/public/browser_state.h" 17 #include "ios/web/public/browser_state.h"
17 18
18 namespace dom_distiller { 19 namespace dom_distiller {
19 20
20 // Helper class for observing the loading of URLs to distill. 21 // Helper class for observing the loading of URLs to distill.
21 class DistillerWebStateObserver : public web::WebStateObserver { 22 class DistillerWebStateObserver : public web::WebStateObserver {
22 public: 23 public:
(...skipping 24 matching lines...) Expand all
47 #pragma mark - 48 #pragma mark -
48 49
49 DistillerPageIOS::DistillerPageIOS(web::BrowserState* browser_state) 50 DistillerPageIOS::DistillerPageIOS(web::BrowserState* browser_state)
50 : browser_state_(browser_state), weak_ptr_factory_(this) { 51 : browser_state_(browser_state), weak_ptr_factory_(this) {
51 } 52 }
52 53
53 DistillerPageIOS::~DistillerPageIOS() { 54 DistillerPageIOS::~DistillerPageIOS() {
54 } 55 }
55 56
56 bool DistillerPageIOS::StringifyOutput() { 57 bool DistillerPageIOS::StringifyOutput() {
57 // UIWebView requires JavaScript to return a single string value. 58 return false;
58 return true;
59 } 59 }
60 60
61 void DistillerPageIOS::DistillPageImpl(const GURL& url, 61 void DistillerPageIOS::DistillPageImpl(const GURL& url,
62 const std::string& script) { 62 const std::string& script) {
63 if (!url.is_valid() || !script.length()) 63 if (!url.is_valid() || !script.length())
64 return; 64 return;
65 url_ = url; 65 url_ = url;
66 script_ = script; 66 script_ = script;
67 67
68 // Lazily create provider. 68 // Lazily create provider.
(...skipping 13 matching lines...) Expand all
82 else 82 else
83 OnLoadURLDone(web::PageLoadCompletionStatus::FAILURE); 83 OnLoadURLDone(web::PageLoadCompletionStatus::FAILURE);
84 } 84 }
85 85
86 void DistillerPageIOS::OnLoadURLDone( 86 void DistillerPageIOS::OnLoadURLDone(
87 web::PageLoadCompletionStatus load_completion_status) { 87 web::PageLoadCompletionStatus load_completion_status) {
88 // Don't attempt to distill if the page load failed or if there is no 88 // Don't attempt to distill if the page load failed or if there is no
89 // provider. 89 // provider.
90 if (load_completion_status == web::PageLoadCompletionStatus::FAILURE || 90 if (load_completion_status == web::PageLoadCompletionStatus::FAILURE ||
91 !provider_) { 91 !provider_) {
92 HandleJavaScriptResultString(@""); 92 HandleJavaScriptResult(nil);
93 return; 93 return;
94 } 94 }
95 95
96 // Inject the script. 96 // Inject the script.
97 base::WeakPtr<DistillerPageIOS> weak_this = weak_ptr_factory_.GetWeakPtr(); 97 base::WeakPtr<DistillerPageIOS> weak_this = weak_ptr_factory_.GetWeakPtr();
98 provider_->InjectScript(script_, ^(NSString* string, NSError* error) { 98 provider_->InjectScript(script_, ^(id result, NSError* error) {
99 DistillerPageIOS* distiller_page = weak_this.get(); 99 DistillerPageIOS* distiller_page = weak_this.get();
100 if (distiller_page) 100 if (distiller_page)
101 distiller_page->HandleJavaScriptResultString(string); 101 distiller_page->HandleJavaScriptResult(result);
102 }); 102 });
103 } 103 }
104 104
105 void DistillerPageIOS::HandleJavaScriptResultString(NSString* result) { 105 void DistillerPageIOS::HandleJavaScriptResult(id result) {
106 std::unique_ptr<base::Value> resultValue = base::Value::CreateNullValue(); 106 std::unique_ptr<base::Value> resultValue = base::Value::CreateNullValue();
107 if (result.length) { 107 if (result) {
108 std::unique_ptr<base::Value> dictionaryValue = 108 resultValue = ValueResultFromWKResult(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 } 109 }
115 OnDistillationDone(url_, resultValue.get()); 110 OnDistillationDone(url_, resultValue.get());
116 } 111 }
117 112
113 // This is duplicated here from ios/web/web_state/ui/web_view_js_utils.mm in
114 // order to handle numbers. The dom distiller proto expects integers and the
115 // generated JSON deserializer does not accept doubles in the place of ints.
116 // However WKWebView only allows us to return "numbers." We need to create
117 // integers and doubles as expected by the proto, which is done by checking if
118 // the number has a fraction or not; since this is a hacky method it's isolated
119 // to this file so as to limit the risk of broken JS calls.
120 std::unique_ptr<base::Value> DistillerPageIOS::ValueResultFromWKResult(
121 id wk_result) {
122 if (!wk_result)
123 return nullptr;
Eugene But (OOO till 7-30) 2016/09/09 15:28:28 Optional NIT: You can return |base::Value::CreateN
lody 2016/09/19 15:34:36 I'd rather not have any part of this be different
124
125 std::unique_ptr<base::Value> result;
126 CFTypeID result_type = CFGetTypeID(wk_result);
127 if (result_type == CFStringGetTypeID()) {
128 result.reset(new base::StringValue(base::SysNSStringToUTF16(wk_result)));
129 DCHECK(result->IsType(base::Value::TYPE_STRING));
130 } else if (result_type == CFNumberGetTypeID()) {
131 if ([wk_result intValue] != [wk_result doubleValue]) {
132 result.reset(new base::FundamentalValue([wk_result doubleValue]));
133 DCHECK(result->IsType(base::Value::TYPE_DOUBLE));
134 } else {
135 result.reset(new base::FundamentalValue([wk_result intValue]));
136 DCHECK(result->IsType(base::Value::TYPE_INTEGER));
137 }
138 } else if (result_type == CFBooleanGetTypeID()) {
139 result.reset(
140 new base::FundamentalValue(static_cast<bool>([wk_result boolValue])));
141 DCHECK(result->IsType(base::Value::TYPE_BOOLEAN));
142 } else if (result_type == CFNullGetTypeID()) {
143 result = base::Value::CreateNullValue();
144 DCHECK(result->IsType(base::Value::TYPE_NULL));
145 } else if (result_type == CFDictionaryGetTypeID()) {
146 std::unique_ptr<base::DictionaryValue> dictionary =
147 base::MakeUnique<base::DictionaryValue>();
148 for (id key in wk_result) {
149 DCHECK([key respondsToSelector:@selector(UTF8String)]);
150 const std::string& path([key UTF8String]);
Eugene But (OOO till 7-30) 2016/09/09 15:28:28 Please use sys_string_conversions instead of |UTF8
lody 2016/09/19 15:34:36 Done.
151 dictionary->Set(path,
152 ValueResultFromWKResult([wk_result objectForKey:key]));
Eugene But (OOO till 7-30) 2016/09/09 15:28:28 Can this recursion cause a stack overflow?
Eugene But (OOO till 7-30) 2016/09/09 15:28:28 NIT: s/[wk_result objectForKey:key]/wk_result[key]
Eugene But (OOO till 7-30) 2016/09/10 00:23:40 JsonParser measures stack depth: https://cs.chromi
lody 2016/09/19 15:34:36 Duplicated code fixed by jif.
153 }
154 result = std::move(dictionary);
155 } else if (result_type == CFArrayGetTypeID()) {
156 std::unique_ptr<base::ListValue> list = base::MakeUnique<base::ListValue>();
157 for (id value in wk_result) {
158 list->Append(ValueResultFromWKResult(value));
Eugene But (OOO till 7-30) 2016/09/09 15:28:28 Same question here
lody 2016/09/19 15:34:35 Acknowledged.
159 }
160 result = std::move(list);
161 } else {
162 NOTREACHED(); // Convert other types as needed.
163 }
164 return result;
165 }
166
118 } // namespace dom_distiller 167 } // namespace dom_distiller
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698