OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #import "ios/web/web_state/ui/crw_wk_script_message_router.h" |
| 6 |
| 7 #import "base/logging.h" |
| 8 #import "base/mac/scoped_nsobject.h" |
| 9 |
| 10 @interface CRWWKScriptMessageRouter ()<WKScriptMessageHandler> |
| 11 |
| 12 // Removes a specific message handler. Does nothing if handler does not exist. |
| 13 - (void)tryRemoveScriptMessageHandlerForName:(NSString*)messageName |
| 14 webView:(WKWebView*)webView; |
| 15 |
| 16 @end |
| 17 |
| 18 @implementation CRWWKScriptMessageRouter { |
| 19 // Two level map of registed message handlers. Keys are message names and |
| 20 // values are more maps (where keys are web views and values are handlers). |
| 21 base::scoped_nsobject<NSMutableDictionary> _handlers; |
| 22 // Wrapped WKUserContentController. |
| 23 base::scoped_nsobject<WKUserContentController> _userContentController; |
| 24 } |
| 25 |
| 26 #pragma mark - |
| 27 #pragma mark Interface |
| 28 |
| 29 - (WKUserContentController*)userContentController { |
| 30 return _userContentController.get(); |
| 31 } |
| 32 |
| 33 - (instancetype)init { |
| 34 NOTREACHED(); |
| 35 return nil; |
| 36 } |
| 37 |
| 38 - (instancetype)initWithUserContentController: |
| 39 (WKUserContentController*)userContentController { |
| 40 DCHECK(userContentController); |
| 41 if ((self = [super init])) { |
| 42 _handlers.reset([[NSMutableDictionary alloc] init]); |
| 43 _userContentController.reset([userContentController retain]); |
| 44 } |
| 45 return self; |
| 46 } |
| 47 |
| 48 - (void)setScriptMessageHandler:(void(^)(WKScriptMessage*))handler |
| 49 name:(NSString*)messageName |
| 50 webView:(WKWebView*)webView { |
| 51 DCHECK(handler); |
| 52 DCHECK(messageName); |
| 53 DCHECK(webView); |
| 54 |
| 55 NSMapTable* webViewToHandlerMap = [_handlers objectForKey:messageName]; |
| 56 if (!webViewToHandlerMap) { |
| 57 webViewToHandlerMap = [NSMapTable |
| 58 mapTableWithKeyOptions:NSPointerFunctionsStrongMemory |
| 59 valueOptions:NSPointerFunctionsCopyIn]; |
| 60 [_handlers setObject:webViewToHandlerMap forKey:messageName]; |
| 61 [_userContentController addScriptMessageHandler:self name:messageName]; |
| 62 } |
| 63 DCHECK(![webViewToHandlerMap objectForKey:webView]); |
| 64 [webViewToHandlerMap setObject:handler forKey:webView]; |
| 65 } |
| 66 |
| 67 - (void)removeScriptMessageHandlerForName:(NSString*)messageName |
| 68 webView:(WKWebView*)webView { |
| 69 DCHECK(messageName); |
| 70 DCHECK(webView); |
| 71 DCHECK([[_handlers objectForKey:messageName] objectForKey:webView]); |
| 72 [self tryRemoveScriptMessageHandlerForName:messageName webView:webView]; |
| 73 } |
| 74 |
| 75 - (void)removeAllScriptMessageHandlersForWebView:(WKWebView*)webView { |
| 76 DCHECK(webView); |
| 77 for (NSString* messageName in [_handlers allKeys]) { |
| 78 [self tryRemoveScriptMessageHandlerForName:messageName webView:webView]; |
| 79 } |
| 80 } |
| 81 |
| 82 #pragma mark - |
| 83 #pragma mark WKScriptMessageHandler |
| 84 |
| 85 - (void)userContentController:(WKUserContentController*)userContentController |
| 86 didReceiveScriptMessage:(WKScriptMessage*)message { |
| 87 NSMapTable* webViewToHandlerMap = [_handlers objectForKey:message.name]; |
| 88 DCHECK(webViewToHandlerMap); |
| 89 id handler = [webViewToHandlerMap objectForKey:message.webView]; |
| 90 if (handler) { |
| 91 // Web process can send messages even if web view was reset and |
| 92 // script message handler has been removed from the router. |
| 93 ((void(^)(WKScriptMessage*))handler)(message); |
| 94 } |
| 95 } |
| 96 |
| 97 #pragma mark - |
| 98 #pragma mark Implementation |
| 99 |
| 100 - (void)tryRemoveScriptMessageHandlerForName:(NSString*)messageName |
| 101 webView:(WKWebView*)webView { |
| 102 NSMapTable* webViewToHandlerMap = [_handlers objectForKey:messageName]; |
| 103 if (![webViewToHandlerMap objectForKey:webView]) |
| 104 return; |
| 105 if (webViewToHandlerMap.count == 1) { |
| 106 [_handlers removeObjectForKey:messageName]; |
| 107 [_userContentController removeScriptMessageHandlerForName:messageName]; |
| 108 } else { |
| 109 [webViewToHandlerMap removeObjectForKey:webView]; |
| 110 } |
| 111 } |
| 112 |
| 113 @end |
OLD | NEW |