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 if (result_type == CFNullGetTypeID())
34 // TODO(stuartmorgan): Stringify other types.
43 void EvaluateJavaScript(UIWebView* web_view,
45 JavaScriptCompletion completion_handler) {
46 base::WeakNSObject<UIWebView> weak_web_view(web_view);
47 dispatch_async(dispatch_get_main_queue(), ^{
49 [weak_web_view stringByEvaluatingJavaScriptFromString:script];
50 if (completion_handler)
51 completion_handler(result, nil);
55 void EvaluateJavaScript(WKWebView* web_view,
57 JavaScriptCompletion completion_handler) {
58 DCHECK([script length]);
59 // __block qualifier ensures that web_view_completion_handler is correctly
60 // captured by itself.
61 __block void (^web_view_completion_handler)(id, NSError*) = nil;
62 // Do not create a web_view_completion_handler if no |handler| is passed to
63 // this function. This results in no creation of an unnecessary block.
64 if (completion_handler) {
65 // WKWebView crashes on deallocation when it flushes scripts that did not
66 // finish the execution but have |completion_handler|. Passing
67 // |completion_handler| ownership to the block itself and keeping it alive
68 // until it's executed fixes the crash. No memory leak is expected since
69 // |completion_handler| is always executed even if WKWebView is deallocated.
70 // https://bugs.webkit.org/show_bug.cgi?id=140203
71 web_view_completion_handler = [^(id result, NSError* error) {
72 completion_handler(UIResultFromWKResult(result), error);
73 [web_view_completion_handler autorelease];
76 [web_view evaluateJavaScript:script
77 completionHandler:web_view_completion_handler];