Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: ios/chrome/browser/ui/static_content/static_html_view_controller.mm

Issue 2587023002: Upstream Chrome on iOS source code [8/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ios/chrome/browser/ui/static_content/static_html_view_controller.h"
6
7 #include <WebKit/WebKit.h>
8
9 #include <stdlib.h>
10
11 #include "base/logging.h"
12 #include "base/mac/bundle_locations.h"
13 #include "base/mac/foundation_util.h"
14 #include "base/mac/scoped_nsobject.h"
15 #include "ios/web/public/referrer.h"
16 #import "ios/web/public/web_state/ui/crw_native_content.h"
17 #import "ios/web/public/web_view_creation_util.h"
18 #import "net/base/mac/url_conversions.h"
19 #include "ui/base/page_transition_types.h"
20 #include "ui/base/resource/resource_bundle.h"
21
22 @implementation IdrHtmlGenerator
23 - (id)initWithResourceId:(int)resourceId encoding:(NSStringEncoding)encoding {
24 if ((self = [super init])) {
25 resourceId_ = resourceId;
26 encoding_ = encoding;
27 }
28 return self;
29 }
30
31 - (id)initWithResourceId:(int)resourceId {
32 return [self initWithResourceId:resourceId encoding:NSUTF8StringEncoding];
33 }
34
35 - (void)generateHtml:(HtmlCallback)callback {
36 base::StringPiece html(
37 ResourceBundle::GetSharedInstance().GetRawDataResource(resourceId_));
38 base::scoped_nsobject<NSString> result([[NSString alloc]
39 initWithBytes:html.data()
40 length:html.size()
41 encoding:encoding_]);
42 callback(result);
43 }
44 @end
45
46 @interface StaticHtmlViewController ()<WKNavigationDelegate> {
47 @private
48 // The referrer that will be passed when navigating from this page.
49 web::Referrer referrer_;
50
51 // The URL that will be passed to the web page when loading.
52 // If the page is displaying a local HTML file, it contains the file URL to
53 // the file.
54 // If the page is a generated HTML, it contains a random resource URL.
55 base::scoped_nsobject<NSURL> resourceUrl_;
56
57 // If the view is displaying a local file, contains the URL of the root
58 // directory containing all resources needed by the page.
59 // The web view will get access to this page.
60 base::scoped_nsobject<NSURL> resourcesRootDirectory_;
61
62 // If the view is displaying a resources, contains the name of the resource.
63 base::scoped_nsobject<NSString> resource_;
64
65 // If the view displayes a generated HTML, contains the |HtmlGenerator| to
66 // generate it.
67 base::scoped_nsprotocol<id<HtmlGenerator>> generator_;
68
69 // Browser state associated with the view controller, used to create the
70 // WKWebView.
71 web::BrowserState* browserState_; // Weak.
72
73 // The web view that is used to display the content.
74 base::scoped_nsobject<WKWebView> webView_;
75
76 // The delegate of the native content.
77 id<CRWNativeContentDelegate> delegate_; // weak
78
79 // The loader to navigate from the page.
80 id<UrlLoader> loader_; // weak
81 }
82
83 // Returns the URL of the static page to display.
84 - (NSURL*)resourceURL;
85 // Ensures that webView_ has been created, creating it if necessary.
86 - (void)ensureWebViewCreated;
87 // Determines if the page load should begin based on the current |resourceURL|.
88 - (BOOL)shouldStartLoadWithRequest:(NSURLRequest*)request;
89 @end
90
91 @implementation StaticHtmlViewController
92
93 - (instancetype)initWithResource:(NSString*)resource
94 browserState:(web::BrowserState*)browserState {
95 DCHECK(resource);
96 DCHECK(browserState);
97 if ((self = [super init])) {
98 resource_.reset([resource copy]);
99 browserState_ = browserState;
100 }
101 return self;
102 }
103
104 - (instancetype)initWithGenerator:(id<HtmlGenerator>)generator
105 browserState:(web::BrowserState*)browserState {
106 DCHECK(generator);
107 DCHECK(browserState);
108 if ((self = [super init])) {
109 generator_.reset([generator retain]);
110 browserState_ = browserState;
111 }
112 return self;
113 }
114
115 - (instancetype)initWithFileURL:(const GURL&)URL
116 allowingReadAccessToURL:(const GURL&)resourcesRoot
117 browserState:(web::BrowserState*)browserState {
118 DCHECK(URL.is_valid());
119 DCHECK(URL.SchemeIsFile());
120 DCHECK(browserState);
121 if ((self = [super init])) {
122 resourceUrl_.reset([net::NSURLWithGURL(URL) retain]);
123 resourcesRootDirectory_.reset([net::NSURLWithGURL(resourcesRoot) retain]);
124 browserState_ = browserState;
125 }
126 return self;
127 }
128
129 - (void)dealloc {
130 [self removeWebViewObservers];
131 [super dealloc];
132 }
133
134 - (void)removeWebViewObservers {
135 [webView_ removeObserver:self forKeyPath:@"title"];
136 }
137
138 - (void)setLoader:(id<UrlLoader>)loader
139 referrer:(const web::Referrer&)referrer {
140 loader_ = loader;
141 referrer_ = referrer;
142 }
143
144 - (void)executeJavaScript:(NSString*)script
145 completionHandler:(web::JavaScriptResultBlock)handler {
146 [webView_ evaluateJavaScript:script completionHandler:handler];
147 }
148
149 - (UIScrollView*)scrollView {
150 return [[self webView] scrollView];
151 }
152
153 - (WKWebView*)webView {
154 [self ensureWebViewCreated];
155 return webView_;
156 }
157
158 - (void)handleLowMemory {
159 [self removeWebViewObservers];
160 webView_.reset();
161 }
162
163 - (BOOL)isViewAlive {
164 return webView_.get() != nil;
165 }
166
167 - (NSString*)title {
168 return [[self webView] title];
169 }
170
171 - (void)reload {
172 if (!generator_) {
173 [webView_ reload];
174 } else {
175 NSURL* resourceURL = [self resourceURL];
176 [generator_ generateHtml:^(NSString* HTML) {
177 [webView_ loadHTMLString:HTML baseURL:resourceURL];
178 }];
179 }
180 }
181
182 - (void)triggerPendingLoad {
183 // Ensure that the web view is created, which triggers loading.
184 [self ensureWebViewCreated];
185 }
186
187 - (void)setDelegate:(id<CRWNativeContentDelegate>)delegate {
188 delegate_ = delegate;
189 }
190
191 - (void)setScrollEnabled:(BOOL)enabled {
192 [[self scrollView] setScrollEnabled:enabled];
193 }
194
195 #pragma mark -
196 #pragma mark WKNavigationDelegate implementation
197
198 - (void)webView:(WKWebView*)webView
199 decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction
200 decisionHandler:
201 (void (^)(WKNavigationActionPolicy))decisionHandler {
202 decisionHandler([self shouldStartLoadWithRequest:navigationAction.request]
203 ? WKNavigationActionPolicyAllow
204 : WKNavigationActionPolicyCancel);
205 }
206
207 #pragma mark -
208 #pragma mark KVO callback
209
210 - (void)observeValueForKeyPath:(NSString*)keyPath
211 ofObject:(id)object
212 change:(NSDictionary*)change
213 context:(void*)context {
214 DCHECK([keyPath isEqualToString:@"title"]);
215 if ([delegate_ respondsToSelector:@selector(nativeContent:titleDidChange:)]) {
216 // WKWebView's |title| changes to nil when its web process crashes.
217 if ([webView_ title])
218 [delegate_ nativeContent:self titleDidChange:[webView_ title]];
219 }
220 }
221
222 #pragma mark -
223 #pragma mark Private
224
225 - (BOOL)shouldStartLoadWithRequest:(NSURLRequest*)request {
226 // Only allow displaying the URL which correspond to the authorized resource.
227 if ([[request URL] isEqual:[self resourceURL]])
228 return YES;
229
230 // All other URLs will be loaded by our UrlLoader if we have one.
231 if (loader_) {
232 dispatch_async(dispatch_get_main_queue(), ^{
233 [loader_ loadURL:net::GURLWithNSURL([request URL])
234 referrer:referrer_
235 transition:ui::PAGE_TRANSITION_LINK
236 rendererInitiated:YES];
237 });
238 }
239 return NO;
240 }
241
242 - (NSURL*)resourceURL {
243 if (resourceUrl_)
244 return resourceUrl_.get();
245
246 DCHECK(resource_ || generator_);
247 NSString* path = nil;
248 if (resource_) {
249 NSBundle* bundle = base::mac::FrameworkBundle();
250 NSString* bundlePath = [bundle bundlePath];
251 path = [bundlePath stringByAppendingPathComponent:resource_.get()];
252 } else {
253 // Generate a random resource URL to whitelist the load in
254 // |webView:shouldStartLoadWithRequest:navigationType:| method.
255 path = [NSString stringWithFormat:@"/whitelist%u%u%u%u", arc4random(),
256 arc4random(), arc4random(), arc4random()];
257 }
258 DCHECK(path);
259 // Necessary because the |fileURLWithPath:| method adds a localhost in the
260 // URL, and this prevents the URL from being comparable with the ones that
261 // UIWebView uses when calling the delegate.
262 base::scoped_nsobject<NSURLComponents> components(
263 [[NSURLComponents alloc] init]);
264 [components setScheme:@"file"];
265 [components setHost:@""];
266 [components setPath:path];
267 resourceUrl_.reset([[components URL] retain]);
268 resourcesRootDirectory_.reset([resourceUrl_ copy]);
269 return resourceUrl_;
270 }
271
272 - (void)ensureWebViewCreated {
273 if (!webView_) {
274 WKWebView* webView = web::BuildWKWebView(CGRectZero, browserState_);
275 [webView addObserver:self forKeyPath:@"title" options:0 context:nullptr];
276 [webView setAutoresizingMask:UIViewAutoresizingFlexibleWidth |
277 UIViewAutoresizingFlexibleHeight];
278 [self loadWebViewContents:webView];
279 [webView setNavigationDelegate:self];
280 webView_.reset([webView retain]);
281 }
282 }
283
284 - (void)loadWebViewContents:(WKWebView*)webView {
285 if (!generator_) {
286 [webView loadFileURL:[self resourceURL]
287 allowingReadAccessToURL:resourcesRootDirectory_];
288 } else {
289 NSURL* resourceURL = [self resourceURL];
290 [generator_ generateHtml:^(NSString* HTML) {
291 [webView loadHTMLString:HTML baseURL:resourceURL];
292 }];
293 }
294 }
295
296 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698