OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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/wk_web_view_configuration_provider.h" |
| 6 |
| 7 #import <Foundation/Foundation.h> |
| 8 #import <WebKit/WebKit.h> |
| 9 |
| 10 #import "base/ios/weak_nsobject.h" |
| 11 #import "base/logging.h" |
| 12 #include "ios/web/public/browser_state.h" |
| 13 #import "ios/web/web_state/js/page_script_util.h" |
| 14 #import "ios/web/web_state/ui/crw_wk_script_message_router.h" |
| 15 |
| 16 // TODO(eugenebut): swizzle [[WKWebViewConfiguration alloc] init] to make sure |
| 17 // that WKWebViewConfiguration is obtained only from provider and can not be |
| 18 // created by alloc/init call. |
| 19 |
| 20 namespace web { |
| 21 |
| 22 namespace { |
| 23 // A key used to associate a WKWebViewConfigurationProvider with a BrowserState. |
| 24 const char kWKWebViewConfigProviderKeyName[] = "wk_web_view_config_provider"; |
| 25 |
| 26 // Returns an autoreleased instance of WKUserScript to be added to |
| 27 // configuration's userContentController. |
| 28 WKUserScript* GetEarlyPageScript() { |
| 29 // Content of WKUserScript can be injected into the same page multiple times |
| 30 // without notifying WKNavigationDelegate (e.g. after window.document.write |
| 31 // JavaScript call). Injecting the script one more time will invalidate |
| 32 // __gCrWeb.windowId variable and will break the ability to send messages from |
| 33 // JS to the native code. Wrapping injected script into "if (!injected)" check |
| 34 // prevents multiple injections into the same page. |
| 35 NSString* const kSourceTemplate = |
| 36 @"if (!window.__gCrWKUserScriptInjected) {" |
| 37 " window.__gCrWKUserScriptInjected = true; %@" |
| 38 "}"; |
| 39 NSString* earlyScript = GetEarlyPageScript(WK_WEB_VIEW_TYPE); |
| 40 NSString* source = [NSString stringWithFormat:kSourceTemplate, earlyScript]; |
| 41 return [[[WKUserScript alloc] |
| 42 initWithSource:source |
| 43 injectionTime:WKUserScriptInjectionTimeAtDocumentStart |
| 44 forMainFrameOnly:YES] autorelease]; |
| 45 } |
| 46 |
| 47 } // namespace |
| 48 |
| 49 // static |
| 50 WKWebViewConfigurationProvider& |
| 51 WKWebViewConfigurationProvider::FromBrowserState(BrowserState* browser_state) { |
| 52 DCHECK([NSThread isMainThread]); |
| 53 DCHECK(browser_state); |
| 54 if (!browser_state->GetUserData(kWKWebViewConfigProviderKeyName)) { |
| 55 browser_state->SetUserData(kWKWebViewConfigProviderKeyName, |
| 56 new WKWebViewConfigurationProvider()); |
| 57 } |
| 58 return *(static_cast<WKWebViewConfigurationProvider*>( |
| 59 browser_state->GetUserData(kWKWebViewConfigProviderKeyName))); |
| 60 } |
| 61 |
| 62 WKWebViewConfigurationProvider::WKWebViewConfigurationProvider() { |
| 63 } |
| 64 |
| 65 WKWebViewConfigurationProvider::~WKWebViewConfigurationProvider() { |
| 66 } |
| 67 |
| 68 WKWebViewConfiguration* |
| 69 WKWebViewConfigurationProvider::GetWebViewConfiguration() { |
| 70 DCHECK([NSThread isMainThread]); |
| 71 if (!configuration_) { |
| 72 configuration_.reset([[WKWebViewConfiguration alloc] init]); |
| 73 // setJavaScriptCanOpenWindowsAutomatically is required to support popups. |
| 74 [[configuration_ preferences] setJavaScriptCanOpenWindowsAutomatically:YES]; |
| 75 [[configuration_ userContentController] addUserScript:GetEarlyPageScript()]; |
| 76 } |
| 77 // Prevent callers from changing the internals of configuration. |
| 78 return [[configuration_ copy] autorelease]; |
| 79 } |
| 80 |
| 81 CRWWKScriptMessageRouter* |
| 82 WKWebViewConfigurationProvider::GetScriptMessageRouter() { |
| 83 DCHECK([NSThread isMainThread]); |
| 84 if (!router_) { |
| 85 WKUserContentController* userContentController = |
| 86 [GetWebViewConfiguration() userContentController]; |
| 87 router_.reset([[CRWWKScriptMessageRouter alloc] |
| 88 initWithUserContentController:userContentController]); |
| 89 } |
| 90 return router_; |
| 91 } |
| 92 |
| 93 bool WKWebViewConfigurationProvider::HasWebViewConfiguration() const { |
| 94 DCHECK([NSThread isMainThread]); |
| 95 return configuration_; |
| 96 } |
| 97 |
| 98 void WKWebViewConfigurationProvider::Purge() { |
| 99 DCHECK([NSThread isMainThread]); |
| 100 #if !defined(NDEBUG) || !defined(DCHECK_ALWAYS_ON) // Matches DCHECK_IS_ON. |
| 101 base::WeakNSObject<id> weak_configuration(configuration_); |
| 102 base::WeakNSObject<id> weak_router(router_); |
| 103 base::WeakNSObject<id> weak_process_pool([configuration_ processPool]); |
| 104 #endif // !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) |
| 105 configuration_.reset(); |
| 106 router_.reset(); |
| 107 // Make sure that no one retains configuration, router, processPool. |
| 108 DCHECK(!weak_configuration); |
| 109 DCHECK(!weak_router); |
| 110 DCHECK(!weak_process_pool); |
| 111 } |
| 112 |
| 113 } // namespace web |
OLD | NEW |