OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" | 5 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" |
6 | 6 |
7 #import <Foundation/Foundation.h> | 7 #import <Foundation/Foundation.h> |
8 #import <objc/runtime.h> | |
9 #import <WebKit/WebKit.h> | 8 #import <WebKit/WebKit.h> |
10 | 9 |
11 #include "base/ios/ios_util.h" | 10 #include "base/ios/ios_util.h" |
12 #import "base/ios/weak_nsobject.h" | 11 #import "base/ios/weak_nsobject.h" |
13 #import "base/logging.h" | 12 #import "base/logging.h" |
14 #import "ios/web/alloc_with_zone_interceptor.h" | |
15 #include "ios/web/public/browser_state.h" | 13 #include "ios/web/public/browser_state.h" |
16 #import "ios/web/web_state/js/page_script_util.h" | 14 #import "ios/web/web_state/js/page_script_util.h" |
17 #import "ios/web/web_state/ui/crw_wk_script_message_router.h" | 15 #import "ios/web/web_state/ui/crw_wk_script_message_router.h" |
18 #import "ios/web/web_state/web_view_internal_creation_util.h" | |
19 | |
20 #if !defined(NDEBUG) | |
21 | |
22 namespace { | |
23 BOOL gAllowWKProcessPoolCreation = NO; | |
24 | |
25 // By default WKProcessPool creation is not allowed by embedder to prevent | |
26 // issues with browsing data clearing. However some iOS system methods do create | |
27 // WKProcessPool inside, which is perfectly fine and should be allowed. This | |
28 // method whitelists given |klass| with given |selector|, so creation of | |
29 // WKProcessPool is allowed inside that selector call. This function currently | |
30 // supports Objective-C methods with up to 4 arguments and needs to be updated | |
31 // if support for more arguments is required. | |
32 void AllowWKProcessPoolCreation(Class klass, SEL selector) { | |
33 Method method = class_getInstanceMethod(klass, selector); | |
34 IMP originalImp = method_getImplementation(method); | |
35 IMP safeImp = imp_implementationWithBlock( | |
36 ^(id self, id arg1, id arg2, id arg3, id arg4) { | |
37 BOOL oldAllowWKProcessPoolCreation = gAllowWKProcessPoolCreation; | |
38 gAllowWKProcessPoolCreation = YES; | |
39 id result = originalImp(self, selector, arg1, arg2, arg3, arg4); | |
40 gAllowWKProcessPoolCreation = oldAllowWKProcessPoolCreation; | |
41 return result; | |
42 }); | |
43 | |
44 method_setImplementation(method, safeImp); | |
45 } | |
46 } | |
47 | |
48 @interface WKProcessPool (CRWAdditions) | |
49 @end | |
50 | |
51 @implementation WKProcessPool (CRWAdditions) | |
52 | |
53 + (void)load { | |
54 id (^allocator)(Class klass, NSZone* zone) = ^id(Class klass, NSZone* zone) { | |
55 if (gAllowWKProcessPoolCreation || web::IsWebViewAllocInitAllowed()) { | |
56 return NSAllocateObject(klass, 0, zone); | |
57 } | |
58 // You have hit this because you are trying to create a WKProcessPool | |
59 // directly or indirectly (f.e. by creating WKWebViewConfiguration | |
60 // manually). Please use GetWebViewConfiguration() to get | |
61 // WKWebViewConfiguration object. | |
62 NOTREACHED(); | |
63 return nil; | |
64 }; | |
65 web::AddAllocWithZoneMethod([WKProcessPool class], allocator); | |
66 | |
67 if (!base::ios::IsRunningOnIOS9OrLater()) | |
68 return; | |
69 | |
70 // Make sure that WKWebsiteDataStore is allowed to create WKProcessPool for | |
71 // internal implementation purposes. | |
72 AllowWKProcessPoolCreation( | |
73 [WKWebsiteDataStore class], | |
74 @selector(fetchDataRecordsOfTypes:completionHandler:completionHandler:)); | |
75 AllowWKProcessPoolCreation( | |
76 [WKWebsiteDataStore class], | |
77 @selector(removeDataOfTypes:forDataRecords:completionHandler:)); | |
78 AllowWKProcessPoolCreation( | |
79 [WKWebsiteDataStore class], | |
80 @selector(removeDataOfTypes:modifiedSince:completionHandler:)); | |
81 } | |
82 | |
83 @end | |
84 | |
85 #endif // !defined(NDEBUG) | |
86 | 16 |
87 namespace web { | 17 namespace web { |
88 | 18 |
89 namespace { | 19 namespace { |
90 // A key used to associate a WKWebViewConfigurationProvider with a BrowserState. | 20 // A key used to associate a WKWebViewConfigurationProvider with a BrowserState. |
91 const char kWKWebViewConfigProviderKeyName[] = "wk_web_view_config_provider"; | 21 const char kWKWebViewConfigProviderKeyName[] = "wk_web_view_config_provider"; |
92 | 22 |
93 // Returns an autoreleased instance of WKUserScript to be added to | 23 // Returns an autoreleased instance of WKUserScript to be added to |
94 // configuration's userContentController. | 24 // configuration's userContentController. |
95 WKUserScript* GetEarlyPageScript() { | 25 WKUserScript* GetEarlyPageScript() { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 if (!configuration_) { | 59 if (!configuration_) { |
130 configuration_.reset([[WKWebViewConfiguration alloc] init]); | 60 configuration_.reset([[WKWebViewConfiguration alloc] init]); |
131 if (is_off_the_record_ && base::ios::IsRunningOnIOS9OrLater()) { | 61 if (is_off_the_record_ && base::ios::IsRunningOnIOS9OrLater()) { |
132 // WKWebsiteDataStore is iOS9 only. | 62 // WKWebsiteDataStore is iOS9 only. |
133 [configuration_ | 63 [configuration_ |
134 setWebsiteDataStore:[WKWebsiteDataStore nonPersistentDataStore]]; | 64 setWebsiteDataStore:[WKWebsiteDataStore nonPersistentDataStore]]; |
135 } | 65 } |
136 // setJavaScriptCanOpenWindowsAutomatically is required to support popups. | 66 // setJavaScriptCanOpenWindowsAutomatically is required to support popups. |
137 [[configuration_ preferences] setJavaScriptCanOpenWindowsAutomatically:YES]; | 67 [[configuration_ preferences] setJavaScriptCanOpenWindowsAutomatically:YES]; |
138 [[configuration_ userContentController] addUserScript:GetEarlyPageScript()]; | 68 [[configuration_ userContentController] addUserScript:GetEarlyPageScript()]; |
139 #if !defined(NDEBUG) | |
140 // Lazily load WKProcessPool. -[[WKProcessPool alloc] init] call is not | |
141 // allowed except when creating config object inside this class. | |
142 // Unmanaged creation of WKProcessPool may lead to issues with cookie | |
143 // clearing and Browsing Data Partitioning implementation. | |
144 gAllowWKProcessPoolCreation = YES; | |
145 CHECK([configuration_ processPool]); | |
146 gAllowWKProcessPoolCreation = NO; | |
147 #endif // !defined(NDEBUG) | |
148 } | 69 } |
149 // Prevent callers from changing the internals of configuration. | 70 // Prevent callers from changing the internals of configuration. |
150 return [[configuration_ copy] autorelease]; | 71 return [[configuration_ copy] autorelease]; |
151 } | 72 } |
152 | 73 |
153 CRWWKScriptMessageRouter* | 74 CRWWKScriptMessageRouter* |
154 WKWebViewConfigurationProvider::GetScriptMessageRouter() { | 75 WKWebViewConfigurationProvider::GetScriptMessageRouter() { |
155 DCHECK([NSThread isMainThread]); | 76 DCHECK([NSThread isMainThread]); |
156 if (!router_) { | 77 if (!router_) { |
157 WKUserContentController* userContentController = | 78 WKUserContentController* userContentController = |
(...skipping 14 matching lines...) Expand all Loading... |
172 configuration_.reset(); | 93 configuration_.reset(); |
173 router_.reset(); | 94 router_.reset(); |
174 // Make sure that no one retains configuration, router, processPool. | 95 // Make sure that no one retains configuration, router, processPool. |
175 DCHECK(!weak_configuration); | 96 DCHECK(!weak_configuration); |
176 DCHECK(!weak_router); | 97 DCHECK(!weak_router); |
177 // TODO(crbug.com/522672): Enable this DCHECK. | 98 // TODO(crbug.com/522672): Enable this DCHECK. |
178 // DCHECK(!weak_process_pool); | 99 // DCHECK(!weak_process_pool); |
179 } | 100 } |
180 | 101 |
181 } // namespace web | 102 } // namespace web |
OLD | NEW |