Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ios / web / web_state / ui / web_view_js_utils.mm
blob8f7b202b044bd60289af98e906e276c243cbe1c2
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   if (result_type == CFNullGetTypeID())
32     return @"";
34   // TODO(stuartmorgan): Stringify other types.
35   NOTREACHED();
36   return nil;
39 }  // namespace
41 namespace web {
43 void EvaluateJavaScript(UIWebView* web_view,
44                         NSString* script,
45                         JavaScriptCompletion completion_handler) {
46   base::WeakNSObject<UIWebView> weak_web_view(web_view);
47   dispatch_async(dispatch_get_main_queue(), ^{
48     NSString* result =
49         [weak_web_view stringByEvaluatingJavaScriptFromString:script];
50     if (completion_handler)
51       completion_handler(result, nil);
52   });
55 void EvaluateJavaScript(WKWebView* web_view,
56                         NSString* script,
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];
74     } copy];
75   }
76   [web_view evaluateJavaScript:script
77              completionHandler:web_view_completion_handler];
80 }  // namespace web