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 #import "ios/web/web_state/ui/web_view_js_utils.h"
7 #import <UIKit/UIKit.h>
8 #import <WebKit/WebKit.h>
10 #include "base/ios/weak_nsobject.h"
11 #include "base/logging.h"
12 #include "base/mac/scoped_nsobject.h"
16 // Converts result of WKWebView script evaluation to UIWebView format.
17 NSString* UIResultFromWKResult(id result) {
21 CFTypeID result_type = CFGetTypeID(result);
22 if (result_type == CFStringGetTypeID())
25 if (result_type == CFNumberGetTypeID())
26 return [result stringValue];
28 if (result_type == CFBooleanGetTypeID())
29 return [result boolValue] ? @"true" : @"false";
31 // TODO(stuartmorgan): Stringify other types.
40 void EvaluateJavaScript(UIWebView* web_view,
42 JavaScriptCompletion completion_handler) {
43 base::WeakNSObject<UIWebView> weak_web_view(web_view);
44 dispatch_async(dispatch_get_main_queue(), ^{
46 [weak_web_view stringByEvaluatingJavaScriptFromString:script];
47 if (completion_handler)
48 completion_handler(result, nil);
52 void EvaluateJavaScript(WKWebView* web_view,
54 JavaScriptCompletion completion_handler) {
55 DCHECK([script length]);
56 // __block qualifier ensures that web_view_completion_handler is correctly
57 // captured by itself.
58 __block void (^web_view_completion_handler)(id, NSError*) = nil;
59 // Do not create a web_view_completion_handler if no |handler| is passed to
60 // this function. This results in no creation of an unnecessary block.
61 if (completion_handler) {
62 // WKWebView crashes on deallocation when it flushes scripts that did not
63 // finish the execution but have |completion_handler|. Passing
64 // |completion_handler| ownership to the block itself and keeping it alive
65 // until it's executed fixes the crash. No memory leak is expected since
66 // |completion_handler| is always executed even if WKWebView is deallocated.
67 // https://bugs.webkit.org/show_bug.cgi?id=140203
68 web_view_completion_handler = [^(id result, NSError* error) {
69 completion_handler(UIResultFromWKResult(result), error);
70 [web_view_completion_handler autorelease];
73 [web_view evaluateJavaScript:script
74 completionHandler:web_view_completion_handler];