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"
15 #import "ios/web/web_state/web_view_internal_creation_util.h"
20 BOOL gAllowWKProcessPoolCreation = NO;
23 @interface WKProcessPool (CRWAdditions)
26 @implementation WKProcessPool (CRWAdditions)
29 id (^allocator)(Class klass, NSZone* zone) = ^id(Class klass, NSZone* zone) {
30 if (gAllowWKProcessPoolCreation || web::IsWebViewAllocInitAllowed()) {
31 return NSAllocateObject(klass, 0, zone);
33 // You have hit this because you are trying to create a WKProcessPool
34 // directly or indirectly (f.e. by creating WKWebViewConfiguration
35 // manually). Please use GetWebViewConfiguration() to get
36 // WKWebViewConfiguration object.
40 web::AddAllocWithZoneMethod([WKProcessPool class], allocator);
45 #endif // !defined(NDEBUG)
50 // A key used to associate a WKWebViewConfigurationProvider with a BrowserState.
51 const char kWKWebViewConfigProviderKeyName[] = "wk_web_view_config_provider";
53 // Returns an autoreleased instance of WKUserScript to be added to
54 // configuration's userContentController.
55 WKUserScript* GetEarlyPageScript() {
56 return [[[WKUserScript alloc]
57 initWithSource:GetEarlyPageScript(WK_WEB_VIEW_TYPE)
58 injectionTime:WKUserScriptInjectionTimeAtDocumentStart
59 forMainFrameOnly:YES] autorelease];
65 WKWebViewConfigurationProvider&
66 WKWebViewConfigurationProvider::FromBrowserState(BrowserState* browser_state) {
67 DCHECK([NSThread isMainThread]);
68 DCHECK(browser_state);
69 if (!browser_state->GetUserData(kWKWebViewConfigProviderKeyName)) {
70 browser_state->SetUserData(kWKWebViewConfigProviderKeyName,
71 new WKWebViewConfigurationProvider());
73 return *(static_cast<WKWebViewConfigurationProvider*>(
74 browser_state->GetUserData(kWKWebViewConfigProviderKeyName)));
77 WKWebViewConfigurationProvider::WKWebViewConfigurationProvider() {
80 WKWebViewConfigurationProvider::~WKWebViewConfigurationProvider() {
83 WKWebViewConfiguration*
84 WKWebViewConfigurationProvider::GetWebViewConfiguration() {
85 DCHECK([NSThread isMainThread]);
86 if (!configuration_) {
87 configuration_.reset([[WKWebViewConfiguration alloc] init]);
88 // setJavaScriptCanOpenWindowsAutomatically is required to support popups.
89 [[configuration_ preferences] setJavaScriptCanOpenWindowsAutomatically:YES];
90 [[configuration_ userContentController] addUserScript:GetEarlyPageScript()];
92 // Lazily load WKProcessPool. -[[WKProcessPool alloc] init] call is not
93 // allowed except when creating config object inside this class.
94 // Unmanaged creation of WKProcessPool may lead to issues with cookie
95 // clearing and Browsing Data Partitioning implementation.
96 gAllowWKProcessPoolCreation = YES;
97 CHECK([configuration_ processPool]);
98 gAllowWKProcessPoolCreation = NO;
99 #endif // !defined(NDEBUG)
101 // Prevent callers from changing the internals of configuration.
102 return [[configuration_ copy] autorelease];
105 bool WKWebViewConfigurationProvider::HasWebViewConfiguration() const {
106 DCHECK([NSThread isMainThread]);
107 return configuration_;
110 void WKWebViewConfigurationProvider::Purge() {
111 DCHECK([NSThread isMainThread]);
112 #if !defined(NDEBUG) || !defined(DCHECK_ALWAYS_ON) // Matches DCHECK_IS_ON.
113 base::WeakNSObject<id> weak_configuration(configuration_);
114 base::WeakNSObject<id> weak_process_pool([configuration_ processPool]);
115 #endif // !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
116 configuration_.reset();
117 // Make sure that no one retains configuration and processPool.
118 DCHECK(!weak_configuration);
119 DCHECK(!weak_process_pool);