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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: components/dom_distiller/ios/distiller_page_ios.mm
diff --git a/components/dom_distiller/ios/distiller_page_ios.mm b/components/dom_distiller/ios/distiller_page_ios.mm
index a20326d2b7e9152d4586bf6b66baded77b1e2646..dd287aae43384ef4a05b4ce55fc127df3088cb52 100644
--- a/components/dom_distiller/ios/distiller_page_ios.mm
+++ b/components/dom_distiller/ios/distiller_page_ios.mm
@@ -10,11 +10,85 @@
#include "base/json/json_reader.h"
#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/values.h"
#include "ios/public/provider/web/web_controller_provider.h"
#include "ios/web/public/browser_state.h"
+namespace {
+
+// This is duplicated here from ios/web/web_state/ui/web_view_js_utils.mm in
+// order to handle numbers. The dom distiller proto expects integers and the
+// generated JSON deserializer does not accept doubles in the place of ints.
+// 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.
+// integers and doubles as expected by the proto, which is done by checking if
+// the number has a fraction or not; since this is a hacky method it's isolated
+// to this file so as to limit the risk of broken JS calls.
+
+int const kMaximumParsingRecursionDepth = 6;
+// Converts result of WKWebView script evaluation to base::Value, parsing
+// |wk_result| up to a depth of |max_depth|.
+std::unique_ptr<base::Value> ValueResultFromScriptResult(id wk_result,
+ int max_depth) {
+ if (!wk_result)
+ return nullptr;
+
+ std::unique_ptr<base::Value> result;
+
+ if (max_depth < 0) {
+ DLOG(WARNING) << "JS maximum recursion depth exceeded.";
+ return result;
+ }
+
+ CFTypeID result_type = CFGetTypeID(wk_result);
+ if (result_type == CFStringGetTypeID()) {
+ result.reset(new base::StringValue(base::SysNSStringToUTF16(wk_result)));
+ DCHECK(result->IsType(base::Value::TYPE_STRING));
+ } else if (result_type == CFNumberGetTypeID()) {
+ // Different implementation is here.
+ if ([wk_result intValue] != [wk_result doubleValue]) {
+ result.reset(new base::FundamentalValue([wk_result doubleValue]));
+ DCHECK(result->IsType(base::Value::TYPE_DOUBLE));
+ } else {
+ result.reset(new base::FundamentalValue([wk_result intValue]));
+ DCHECK(result->IsType(base::Value::TYPE_INTEGER));
+ }
+ // End of different implementation.
+ } else if (result_type == CFBooleanGetTypeID()) {
+ result.reset(
+ new base::FundamentalValue(static_cast<bool>([wk_result boolValue])));
+ DCHECK(result->IsType(base::Value::TYPE_BOOLEAN));
+ } else if (result_type == CFNullGetTypeID()) {
+ result = base::Value::CreateNullValue();
+ DCHECK(result->IsType(base::Value::TYPE_NULL));
+ } else if (result_type == CFDictionaryGetTypeID()) {
+ std::unique_ptr<base::DictionaryValue> dictionary =
+ base::MakeUnique<base::DictionaryValue>();
+ for (id key in wk_result) {
+ NSString* obj_c_string = base::mac::ObjCCast<NSString>(key);
+ const std::string path = base::SysNSStringToUTF8(obj_c_string);
+ std::unique_ptr<base::Value> value =
+ ValueResultFromScriptResult(wk_result[obj_c_string], max_depth - 1);
+ if (value) {
+ dictionary->Set(path, std::move(value));
+ }
+ }
+ result = std::move(dictionary);
+ } else if (result_type == CFArrayGetTypeID()) {
+ std::unique_ptr<base::ListValue> list = base::MakeUnique<base::ListValue>();
+ for (id value in wk_result) {
+ list->Append(ValueResultFromScriptResult(value, max_depth - 1));
+ }
+ result = std::move(list);
+ } else {
+ NOTREACHED(); // Convert other types as needed.
+ }
+ return result;
+}
+}
+
namespace dom_distiller {
// Helper class for observing the loading of URLs to distill.
@@ -54,8 +128,7 @@ DistillerPageIOS::~DistillerPageIOS() {
}
bool DistillerPageIOS::StringifyOutput() {
- // UIWebView requires JavaScript to return a single string value.
- return true;
+ return false;
}
void DistillerPageIOS::DistillPageImpl(const GURL& url,
@@ -89,30 +162,30 @@ void DistillerPageIOS::OnLoadURLDone(
// provider.
if (load_completion_status == web::PageLoadCompletionStatus::FAILURE ||
!provider_) {
- HandleJavaScriptResultString(@"");
+ HandleJavaScriptResult(nil);
return;
}
// Inject the script.
base::WeakPtr<DistillerPageIOS> weak_this = weak_ptr_factory_.GetWeakPtr();
- provider_->InjectScript(script_, ^(NSString* string, NSError* error) {
+ provider_->InjectScript(script_, ^(id result, NSError* error) {
DistillerPageIOS* distiller_page = weak_this.get();
if (distiller_page)
- distiller_page->HandleJavaScriptResultString(string);
+ distiller_page->HandleJavaScriptResult(result);
});
}
-void DistillerPageIOS::HandleJavaScriptResultString(NSString* result) {
+void DistillerPageIOS::HandleJavaScriptResult(id result) {
std::unique_ptr<base::Value> resultValue = base::Value::CreateNullValue();
- if (result.length) {
- std::unique_ptr<base::Value> dictionaryValue =
- base::JSONReader::Read(base::SysNSStringToUTF8(result));
- if (dictionaryValue &&
- dictionaryValue->IsType(base::Value::TYPE_DICTIONARY)) {
- resultValue = std::move(dictionaryValue);
- }
+ if (result) {
+ resultValue = ValueResultFromScriptResult(result);
}
OnDistillationDone(url_, resultValue.get());
}
+std::unique_ptr<base::Value> DistillerPageIOS::ValueResultFromScriptResult(
+ id wk_result) {
+ return ::ValueResultFromScriptResult(wk_result,
+ kMaximumParsingRecursionDepth);
+}
} // namespace dom_distiller

Powered by Google App Engine
This is Rietveld 408576698