Fix breakages in https://codereview.chromium.org/1155713003/
[chromium-blink-merge.git] / ios / web / web_state / ui / web_view_js_utils.mm
blob7bc4ecb7ff36f78166b39fb4af9ba0cccf72dd0a
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"
14 namespace {
16 // Converts result of WKWebView script evaluation to UIWebView format.
17 NSString* UIResultFromWKResult(id result) {
18   if (!result)
19     return @"";
21   CFTypeID result_type = CFGetTypeID(result);
22   if (result_type == CFStringGetTypeID())
23     return result;
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.
32   NOTREACHED();
33   return nil;
36 }  // namespace
38 namespace web {
40 void EvaluateJavaScript(UIWebView* web_view,
41                         NSString* script,
42                         JavaScriptCompletion completion_handler) {
43   base::WeakNSObject<UIWebView> weak_web_view(web_view);
44   dispatch_async(dispatch_get_main_queue(), ^{
45     NSString* result =
46         [weak_web_view stringByEvaluatingJavaScriptFromString:script];
47     if (completion_handler)
48       completion_handler(result, nil);
49   });
52 void EvaluateJavaScript(WKWebView* web_view,
53                         NSString* script,
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];
71     } copy];
72   }
73   [web_view evaluateJavaScript:script
74              completionHandler:web_view_completion_handler];
77 }  // namespace web