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.
5 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
7 #import <Foundation/Foundation.h>
8 #import <WebKit/WebKit.h>
10 #import "base/ios/weak_nsobject.h"
11 #import "base/logging.h"
12 #import "ios/web/alloc_with_zone_interceptor.h"
13 #include "ios/web/public/browser_state.h"
14 #import "ios/web/web_state/js/page_script_util.h"
19 BOOL gAllowWKProcessPoolCreation = NO;
22 @interface WKProcessPool (CRWAdditions)
25 @implementation WKProcessPool (CRWAdditions)
28 id (^allocator)(Class klass, NSZone* zone) = ^id(Class klass, NSZone* zone) {
29 if (gAllowWKProcessPoolCreation) {
30 return NSAllocateObject(klass, 0, zone);
32 // You have hit this because you are trying to create a WKProcessPool
33 // directly or indirectly (f.e. by creating WKWebViewConfiguration
34 // manually). Please use GetWebViewConfiguration() to get
35 // WKWebViewConfiguration object.
39 web::AddAllocWithZoneMethod([WKProcessPool class], allocator);
44 #endif // !defined(NDEBUG)
49 // A key used to associate a WKWebViewConfigurationProvider with a BrowserState.
50 const char kWKWebViewConfigProviderKeyName[] = "wk_web_view_config_provider";
52 // Returns an autoreleased instance of WKUserScript to be added to
53 // configuration's userContentController.
54 WKUserScript* GetEarlyPageScript() {
55 return [[[WKUserScript alloc]
56 initWithSource:GetEarlyPageScript(WK_WEB_VIEW_TYPE)
57 injectionTime:WKUserScriptInjectionTimeAtDocumentStart
58 forMainFrameOnly:YES] autorelease];
64 WKWebViewConfigurationProvider&
65 WKWebViewConfigurationProvider::FromBrowserState(BrowserState* browser_state) {
66 DCHECK([NSThread isMainThread]);
67 DCHECK(browser_state);
68 if (!browser_state->GetUserData(kWKWebViewConfigProviderKeyName)) {
69 browser_state->SetUserData(kWKWebViewConfigProviderKeyName,
70 new WKWebViewConfigurationProvider());
72 return *(static_cast<WKWebViewConfigurationProvider*>(
73 browser_state->GetUserData(kWKWebViewConfigProviderKeyName)));
76 WKWebViewConfigurationProvider::WKWebViewConfigurationProvider() {
79 WKWebViewConfigurationProvider::~WKWebViewConfigurationProvider() {
82 WKWebViewConfiguration*
83 WKWebViewConfigurationProvider::GetWebViewConfiguration() {
84 DCHECK([NSThread isMainThread]);
85 if (!configuration_) {
86 configuration_.reset([[WKWebViewConfiguration alloc] init]);
87 // setJavaScriptCanOpenWindowsAutomatically is required to support popups.
88 [[configuration_ preferences] setJavaScriptCanOpenWindowsAutomatically:YES];
89 [[configuration_ userContentController] addUserScript:GetEarlyPageScript()];
91 // Lazily load WKProcessPool. -[[WKProcessPool alloc] init] call is not
92 // allowed except when creating config object inside this class.
93 // Unmanaged creation of WKProcessPool may lead to issues with cookie
94 // clearing and Browsing Data Partitioning implementation.
95 gAllowWKProcessPoolCreation = YES;
96 CHECK([configuration_ processPool]);
97 gAllowWKProcessPoolCreation = NO;
98 #endif // !defined(NDEBUG)
100 // Prevent callers from changing the internals of configuration.
101 return [[configuration_ copy] autorelease];
104 bool WKWebViewConfigurationProvider::HasWebViewConfiguration() const {
105 DCHECK([NSThread isMainThread]);
106 return configuration_;
109 void WKWebViewConfigurationProvider::Purge() {
110 DCHECK([NSThread isMainThread]);
111 #if !defined(NDEBUG) || !defined(DCHECK_ALWAYS_ON) // Matches DCHECK_IS_ON.
112 base::WeakNSObject<id> weak_configuration(configuration_);
113 base::WeakNSObject<id> weak_process_pool([configuration_ processPool]);
114 #endif // !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
115 configuration_.reset();
116 // Make sure that no one retains configuration and processPool.
117 DCHECK(!weak_configuration);
118 DCHECK(!weak_process_pool);