OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 #include "ios/chrome/browser/ui/static_content/static_html_view_controller.h" | 5 #include "ios/chrome/browser/ui/static_content/static_html_view_controller.h" |
6 | 6 |
7 #import <WebKit/WebKit.h> | 7 #import <WebKit/WebKit.h> |
8 | 8 |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 | 10 |
11 #import "base/ios/weak_nsobject.h" | |
12 #include "base/logging.h" | 11 #include "base/logging.h" |
13 #include "base/mac/bundle_locations.h" | 12 #include "base/mac/bundle_locations.h" |
14 #include "base/mac/foundation_util.h" | 13 #include "base/mac/foundation_util.h" |
15 #include "base/mac/scoped_nsobject.h" | |
16 #include "ios/web/public/referrer.h" | 14 #include "ios/web/public/referrer.h" |
17 #import "ios/web/public/web_state/ui/crw_context_menu_delegate.h" | 15 #import "ios/web/public/web_state/ui/crw_context_menu_delegate.h" |
18 #import "ios/web/public/web_state/ui/crw_native_content.h" | 16 #import "ios/web/public/web_state/ui/crw_native_content.h" |
19 #import "ios/web/public/web_view_creation_util.h" | 17 #import "ios/web/public/web_view_creation_util.h" |
20 #import "net/base/mac/url_conversions.h" | 18 #import "net/base/mac/url_conversions.h" |
21 #include "ui/base/page_transition_types.h" | 19 #include "ui/base/page_transition_types.h" |
22 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
23 | 21 |
22 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
23 #error "This file requires ARC support." | |
24 #endif | |
25 | |
24 @implementation IdrHtmlGenerator | 26 @implementation IdrHtmlGenerator |
25 - (id)initWithResourceId:(int)resourceId encoding:(NSStringEncoding)encoding { | 27 - (id)initWithResourceId:(int)resourceId encoding:(NSStringEncoding)encoding { |
26 if ((self = [super init])) { | 28 if ((self = [super init])) { |
27 resourceId_ = resourceId; | 29 resourceId_ = resourceId; |
28 encoding_ = encoding; | 30 encoding_ = encoding; |
29 } | 31 } |
30 return self; | 32 return self; |
31 } | 33 } |
32 | 34 |
33 - (id)initWithResourceId:(int)resourceId { | 35 - (id)initWithResourceId:(int)resourceId { |
34 return [self initWithResourceId:resourceId encoding:NSUTF8StringEncoding]; | 36 return [self initWithResourceId:resourceId encoding:NSUTF8StringEncoding]; |
35 } | 37 } |
36 | 38 |
37 - (void)generateHtml:(HtmlCallback)callback { | 39 - (void)generateHtml:(HtmlCallback)callback { |
38 base::StringPiece html( | 40 base::StringPiece html( |
39 ResourceBundle::GetSharedInstance().GetRawDataResource(resourceId_)); | 41 ResourceBundle::GetSharedInstance().GetRawDataResource(resourceId_)); |
40 base::scoped_nsobject<NSString> result([[NSString alloc] | 42 NSString* result = [[NSString alloc] initWithBytes:html.data() |
41 initWithBytes:html.data() | 43 length:html.size() |
42 length:html.size() | 44 encoding:encoding_]; |
43 encoding:encoding_]); | |
44 callback(result); | 45 callback(result); |
45 } | 46 } |
46 @end | 47 @end |
47 | 48 |
48 @interface StaticHtmlViewController ()<CRWContextMenuDelegate, | 49 @interface StaticHtmlViewController ()<CRWContextMenuDelegate, |
49 WKNavigationDelegate> { | 50 WKNavigationDelegate> { |
50 @private | 51 @private |
51 // The referrer that will be passed when navigating from this page. | 52 // The referrer that will be passed when navigating from this page. |
52 web::Referrer referrer_; | 53 web::Referrer referrer_; |
53 | 54 |
54 // The URL that will be passed to the web page when loading. | 55 // The URL that will be passed to the web page when loading. |
55 // If the page is displaying a local HTML file, it contains the file URL to | 56 // If the page is displaying a local HTML file, it contains the file URL to |
56 // the file. | 57 // the file. |
57 // If the page is a generated HTML, it contains a random resource URL. | 58 // If the page is a generated HTML, it contains a random resource URL. |
58 base::scoped_nsobject<NSURL> resourceUrl_; | 59 NSURL* resourceUrl_; |
59 | 60 |
60 // If the view is displaying a local file, contains the URL of the root | 61 // If the view is displaying a local file, contains the URL of the root |
61 // directory containing all resources needed by the page. | 62 // directory containing all resources needed by the page. |
62 // The web view will get access to this page. | 63 // The web view will get access to this page. |
63 base::scoped_nsobject<NSURL> resourcesRootDirectory_; | 64 NSURL* resourcesRootDirectory_; |
64 | 65 |
65 // If the view is displaying a resources, contains the name of the resource. | 66 // If the view is displaying a resources, contains the name of the resource. |
66 base::scoped_nsobject<NSString> resource_; | 67 NSString* resource_; |
67 | 68 |
68 // If the view displayes a generated HTML, contains the |HtmlGenerator| to | 69 // If the view displayes a generated HTML, contains the |HtmlGenerator| to |
69 // generate it. | 70 // generate it. |
70 base::scoped_nsprotocol<id<HtmlGenerator>> generator_; | 71 id<HtmlGenerator> generator_; |
71 | 72 |
72 // Browser state associated with the view controller, used to create the | 73 // Browser state associated with the view controller, used to create the |
73 // WKWebView. | 74 // WKWebView. |
74 web::BrowserState* browserState_; // Weak. | 75 web::BrowserState* browserState_; // Weak. |
75 | 76 |
76 // The web view that is used to display the content. | 77 // The web view that is used to display the content. |
77 base::scoped_nsobject<WKWebView> webView_; | 78 WKWebView* webView_; |
78 | 79 |
79 // The delegate of the native content. | 80 // The delegate of the native content. |
80 base::WeakNSProtocol<id<CRWNativeContentDelegate>> delegate_; // weak | 81 __weak id<CRWNativeContentDelegate> delegate_; // weak |
stkhapugin
2017/05/30 13:28:16
remove "// weak" comment
lindsayw
2017/06/01 16:02:09
Done.
| |
81 | 82 |
82 // The loader to navigate from the page. | 83 // The loader to navigate from the page. |
83 base::WeakNSProtocol<id<UrlLoader>> loader_; // weak | 84 __weak id<UrlLoader> loader_; // weak |
stkhapugin
2017/05/30 13:28:16
remove "// weak" comment
lindsayw
2017/06/01 16:02:08
Done.
| |
84 } | 85 } |
85 | 86 |
86 // Returns the URL of the static page to display. | 87 // Returns the URL of the static page to display. |
87 - (NSURL*)resourceURL; | 88 - (NSURL*)resourceURL; |
88 // Ensures that webView_ has been created, creating it if necessary. | 89 // Ensures that webView_ has been created, creating it if necessary. |
89 - (void)ensureWebViewCreated; | 90 - (void)ensureWebViewCreated; |
90 // Determines if the page load should begin based on the current |resourceURL| | 91 // Determines if the page load should begin based on the current |resourceURL| |
91 // and if the request is issued by the main frame (|fromMainFrame|). | 92 // and if the request is issued by the main frame (|fromMainFrame|). |
92 - (BOOL)shouldStartLoadWithRequest:(NSURLRequest*)request | 93 - (BOOL)shouldStartLoadWithRequest:(NSURLRequest*)request |
93 fromMainFrame:(BOOL)fromMainFrame; | 94 fromMainFrame:(BOOL)fromMainFrame; |
94 @end | 95 @end |
95 | 96 |
96 @implementation StaticHtmlViewController | 97 @implementation StaticHtmlViewController |
97 | 98 |
98 - (instancetype)initWithResource:(NSString*)resource | 99 - (instancetype)initWithResource:(NSString*)resource |
99 browserState:(web::BrowserState*)browserState { | 100 browserState:(web::BrowserState*)browserState { |
100 DCHECK(resource); | 101 DCHECK(resource); |
101 DCHECK(browserState); | 102 DCHECK(browserState); |
102 if ((self = [super init])) { | 103 if ((self = [super init])) { |
103 resource_.reset([resource copy]); | 104 resource_ = [resource copy]; |
104 browserState_ = browserState; | 105 browserState_ = browserState; |
105 } | 106 } |
106 return self; | 107 return self; |
107 } | 108 } |
108 | 109 |
109 - (instancetype)initWithGenerator:(id<HtmlGenerator>)generator | 110 - (instancetype)initWithGenerator:(id<HtmlGenerator>)generator |
110 browserState:(web::BrowserState*)browserState { | 111 browserState:(web::BrowserState*)browserState { |
111 DCHECK(generator); | 112 DCHECK(generator); |
112 DCHECK(browserState); | 113 DCHECK(browserState); |
113 if ((self = [super init])) { | 114 if ((self = [super init])) { |
114 generator_.reset([generator retain]); | 115 generator_ = generator; |
115 browserState_ = browserState; | 116 browserState_ = browserState; |
116 } | 117 } |
117 return self; | 118 return self; |
118 } | 119 } |
119 | 120 |
120 - (instancetype)initWithFileURL:(const GURL&)URL | 121 - (instancetype)initWithFileURL:(const GURL&)URL |
121 allowingReadAccessToURL:(const GURL&)resourcesRoot | 122 allowingReadAccessToURL:(const GURL&)resourcesRoot |
122 browserState:(web::BrowserState*)browserState { | 123 browserState:(web::BrowserState*)browserState { |
123 DCHECK(URL.is_valid()); | 124 DCHECK(URL.is_valid()); |
124 DCHECK(URL.SchemeIsFile()); | 125 DCHECK(URL.SchemeIsFile()); |
125 DCHECK(browserState); | 126 DCHECK(browserState); |
126 if ((self = [super init])) { | 127 if ((self = [super init])) { |
127 resourceUrl_.reset([net::NSURLWithGURL(URL) retain]); | 128 resourceUrl_ = net::NSURLWithGURL(URL); |
128 resourcesRootDirectory_.reset([net::NSURLWithGURL(resourcesRoot) retain]); | 129 resourcesRootDirectory_ = net::NSURLWithGURL(resourcesRoot); |
129 browserState_ = browserState; | 130 browserState_ = browserState; |
130 } | 131 } |
131 return self; | 132 return self; |
132 } | 133 } |
133 | 134 |
134 - (void)dealloc { | 135 - (void)dealloc { |
135 [self removeWebViewObservers]; | 136 [self removeWebViewObservers]; |
136 [super dealloc]; | |
137 } | 137 } |
138 | 138 |
139 - (void)removeWebViewObservers { | 139 - (void)removeWebViewObservers { |
140 [webView_ removeObserver:self forKeyPath:@"title"]; | 140 [webView_ removeObserver:self forKeyPath:@"title"]; |
141 } | 141 } |
142 | 142 |
143 - (void)setLoader:(id<UrlLoader>)loader | 143 - (void)setLoader:(id<UrlLoader>)loader |
144 referrer:(const web::Referrer&)referrer { | 144 referrer:(const web::Referrer&)referrer { |
145 loader_.reset(loader); | 145 loader_ = loader; |
146 referrer_ = referrer; | 146 referrer_ = referrer; |
147 } | 147 } |
148 | 148 |
149 - (void)executeJavaScript:(NSString*)script | 149 - (void)executeJavaScript:(NSString*)script |
150 completionHandler:(web::JavaScriptResultBlock)handler { | 150 completionHandler:(web::JavaScriptResultBlock)handler { |
151 [webView_ evaluateJavaScript:script completionHandler:handler]; | 151 [webView_ evaluateJavaScript:script completionHandler:handler]; |
152 } | 152 } |
153 | 153 |
154 - (UIScrollView*)scrollView { | 154 - (UIScrollView*)scrollView { |
155 return [[self webView] scrollView]; | 155 return [[self webView] scrollView]; |
156 } | 156 } |
157 | 157 |
158 - (WKWebView*)webView { | 158 - (WKWebView*)webView { |
159 [self ensureWebViewCreated]; | 159 [self ensureWebViewCreated]; |
160 return webView_; | 160 return webView_; |
161 } | 161 } |
162 | 162 |
163 - (void)handleLowMemory { | 163 - (void)handleLowMemory { |
164 [self removeWebViewObservers]; | 164 [self removeWebViewObservers]; |
165 webView_.reset(); | 165 webView_ = nil; |
166 } | 166 } |
167 | 167 |
168 - (BOOL)isViewAlive { | 168 - (BOOL)isViewAlive { |
169 return webView_.get() != nil; | 169 return webView_ != nil; |
170 } | 170 } |
171 | 171 |
172 - (NSString*)title { | 172 - (NSString*)title { |
173 return [[self webView] title]; | 173 return [[self webView] title]; |
174 } | 174 } |
175 | 175 |
176 - (void)reload { | 176 - (void)reload { |
177 if (!generator_) { | 177 if (!generator_) { |
178 [webView_ reload]; | 178 [webView_ reload]; |
179 } else { | 179 } else { |
180 NSURL* resourceURL = [self resourceURL]; | 180 NSURL* resourceURL = [self resourceURL]; |
181 [generator_ generateHtml:^(NSString* HTML) { | 181 [generator_ generateHtml:^(NSString* HTML) { |
182 [webView_ loadHTMLString:HTML baseURL:resourceURL]; | 182 [webView_ loadHTMLString:HTML baseURL:resourceURL]; |
183 }]; | 183 }]; |
184 } | 184 } |
185 } | 185 } |
186 | 186 |
187 - (void)triggerPendingLoad { | 187 - (void)triggerPendingLoad { |
188 // Ensure that the web view is created, which triggers loading. | 188 // Ensure that the web view is created, which triggers loading. |
189 [self ensureWebViewCreated]; | 189 [self ensureWebViewCreated]; |
190 } | 190 } |
191 | 191 |
192 - (void)setDelegate:(id<CRWNativeContentDelegate>)delegate { | 192 - (void)setDelegate:(id<CRWNativeContentDelegate>)delegate { |
193 delegate_.reset(delegate); | 193 delegate_ = delegate; |
194 } | 194 } |
195 | 195 |
196 - (void)setScrollEnabled:(BOOL)enabled { | 196 - (void)setScrollEnabled:(BOOL)enabled { |
197 [[self scrollView] setScrollEnabled:enabled]; | 197 [[self scrollView] setScrollEnabled:enabled]; |
198 } | 198 } |
199 | 199 |
200 #pragma mark - | 200 #pragma mark - |
201 #pragma mark WKNavigationDelegate implementation | 201 #pragma mark WKNavigationDelegate implementation |
202 | 202 |
203 - (void)webView:(WKWebView*)webView | 203 - (void)webView:(WKWebView*)webView |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
256 referrer:referrer_ | 256 referrer:referrer_ |
257 transition:ui::PAGE_TRANSITION_LINK | 257 transition:ui::PAGE_TRANSITION_LINK |
258 rendererInitiated:YES]; | 258 rendererInitiated:YES]; |
259 }); | 259 }); |
260 } | 260 } |
261 return NO; | 261 return NO; |
262 } | 262 } |
263 | 263 |
264 - (NSURL*)resourceURL { | 264 - (NSURL*)resourceURL { |
265 if (resourceUrl_) | 265 if (resourceUrl_) |
266 return resourceUrl_.get(); | 266 return resourceUrl_; |
267 | 267 |
268 DCHECK(resource_ || generator_); | 268 DCHECK(resource_ || generator_); |
269 NSString* path = nil; | 269 NSString* path = nil; |
270 if (resource_) { | 270 if (resource_) { |
271 NSBundle* bundle = base::mac::FrameworkBundle(); | 271 NSBundle* bundle = base::mac::FrameworkBundle(); |
272 NSString* bundlePath = [bundle bundlePath]; | 272 NSString* bundlePath = [bundle bundlePath]; |
273 path = [bundlePath stringByAppendingPathComponent:resource_.get()]; | 273 path = [bundlePath stringByAppendingPathComponent:resource_]; |
274 } else { | 274 } else { |
275 // Generate a random resource URL to whitelist the load in | 275 // Generate a random resource URL to whitelist the load in |
276 // |webView:shouldStartLoadWithRequest:navigationType:| method. | 276 // |webView:shouldStartLoadWithRequest:navigationType:| method. |
277 path = [NSString stringWithFormat:@"/whitelist%u%u%u%u", arc4random(), | 277 path = [NSString stringWithFormat:@"/whitelist%u%u%u%u", arc4random(), |
278 arc4random(), arc4random(), arc4random()]; | 278 arc4random(), arc4random(), arc4random()]; |
279 } | 279 } |
280 DCHECK(path); | 280 DCHECK(path); |
281 // Necessary because the |fileURLWithPath:| method adds a localhost in the | 281 // Necessary because the |fileURLWithPath:| method adds a localhost in the |
282 // URL, and this prevents the URL from being comparable with the ones that | 282 // URL, and this prevents the URL from being comparable with the ones that |
283 // UIWebView uses when calling the delegate. | 283 // UIWebView uses when calling the delegate. |
284 base::scoped_nsobject<NSURLComponents> components( | 284 NSURLComponents* components = [[NSURLComponents alloc] init]; |
285 [[NSURLComponents alloc] init]); | |
286 [components setScheme:@"file"]; | 285 [components setScheme:@"file"]; |
287 [components setHost:@""]; | 286 [components setHost:@""]; |
288 [components setPath:path]; | 287 [components setPath:path]; |
289 resourceUrl_.reset([[components URL] retain]); | 288 resourceUrl_ = [components URL]; |
290 resourcesRootDirectory_.reset([resourceUrl_ copy]); | 289 resourcesRootDirectory_ = [resourceUrl_ copy]; |
291 return resourceUrl_; | 290 return resourceUrl_; |
292 } | 291 } |
293 | 292 |
294 - (void)ensureWebViewCreated { | 293 - (void)ensureWebViewCreated { |
295 if (!webView_) { | 294 if (!webView_) { |
296 WKWebView* webView = web::BuildWKWebViewWithCustomContextMenu( | 295 WKWebView* webView = web::BuildWKWebViewWithCustomContextMenu( |
297 CGRectZero, browserState_, self); | 296 CGRectZero, browserState_, self); |
298 [webView addObserver:self forKeyPath:@"title" options:0 context:nullptr]; | 297 [webView addObserver:self forKeyPath:@"title" options:0 context:nullptr]; |
299 [webView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | | 298 [webView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | |
300 UIViewAutoresizingFlexibleHeight]; | 299 UIViewAutoresizingFlexibleHeight]; |
301 [self loadWebViewContents:webView]; | 300 [self loadWebViewContents:webView]; |
302 [webView setNavigationDelegate:self]; | 301 [webView setNavigationDelegate:self]; |
303 webView_.reset([webView retain]); | 302 webView_ = webView; |
304 } | 303 } |
305 } | 304 } |
306 | 305 |
307 - (void)loadWebViewContents:(WKWebView*)webView { | 306 - (void)loadWebViewContents:(WKWebView*)webView { |
308 if (!generator_) { | 307 if (!generator_) { |
309 [webView loadFileURL:[self resourceURL] | 308 [webView loadFileURL:[self resourceURL] |
310 allowingReadAccessToURL:resourcesRootDirectory_]; | 309 allowingReadAccessToURL:resourcesRootDirectory_]; |
311 } else { | 310 } else { |
312 NSURL* resourceURL = [self resourceURL]; | 311 NSURL* resourceURL = [self resourceURL]; |
313 [generator_ generateHtml:^(NSString* HTML) { | 312 [generator_ generateHtml:^(NSString* HTML) { |
314 [webView loadHTMLString:HTML baseURL:resourceURL]; | 313 [webView loadHTMLString:HTML baseURL:resourceURL]; |
315 }]; | 314 }]; |
316 } | 315 } |
317 } | 316 } |
318 | 317 |
319 @end | 318 @end |
OLD | NEW |