OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #import "ios/web/web_state/js/crw_js_post_request_loader.h" | |
6 | |
7 #import "base/json/string_escape.h" | |
Eugene But (OOO till 7-30)
2015/12/03 16:51:42
s/import/include
Sorry for missing this previousl
stkhapugin
2015/12/03 17:51:02
Done.
| |
8 #import "base/mac/objc_property_releaser.h" | |
9 #import "base/strings/sys_string_conversions.h" | |
10 #import "ios/web/web_state/js/page_script_util.h" | |
11 #import "ios/web/web_state/ui/crw_wk_script_message_router.h" | |
12 | |
13 namespace { | |
14 | |
15 // Escapes characters and encloses given string in quotes for use in JavaScript. | |
16 NSString* EscapeAndQuoteStringForJavaScript(NSString* unescapedString) { | |
17 std::string string = base::SysNSStringToUTF8(unescapedString); | |
18 return base::SysUTF8ToNSString(base::GetQuotedJSONString(string)); | |
19 } | |
20 | |
21 // JavaScript message handler name installed in WKWebView for request errors. | |
22 NSString* const kErrorHandlerName = @"POSTErrorHandler"; | |
23 | |
24 // JavaScript message handler name installed in WKWebView for successful | |
25 // request completion. | |
26 NSString* const kSuccessHandlerName = @"POSTSuccess"; | |
Eugene But (OOO till 7-30)
2015/12/03 16:51:42
NIT: s/POSTSuccess/POSTSuccessHandler
stkhapugin
2015/12/03 17:51:02
Done.
| |
27 | |
28 } // namespace | |
29 | |
30 @interface CRWJSPOSTRequestLoader () | |
31 | |
32 // JavaScript used to execute POST requests. Lazily instantiated. | |
33 @property(nonatomic, copy, readonly) NSString* requestScript; | |
34 | |
35 // Handler for UIApplicationDidReceiveMemoryWarningNotification. | |
36 - (void)handleMemoryWarning; | |
37 | |
38 // Forms a JavaScript method call to |requestScript| that executes given | |
39 // |request|. | |
40 - (NSString*)scriptToExecutePOSTRequest:(NSURLRequest*)request; | |
41 | |
42 // Converts a dictionary of HTTP request headers to a JavaScript object. | |
43 - (NSString*)JSONForJavaScriptFromRequestHeaders:(NSDictionary*)headers; | |
44 | |
45 @end | |
46 | |
47 @implementation CRWJSPOSTRequestLoader | |
48 @synthesize requestScript = _requestScript; | |
49 | |
50 - (void)dealloc { | |
51 [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
52 [_requestScript release]; | |
Eugene But (OOO till 7-30)
2015/12/03 16:51:42
We don't do manual memory management in Chromium.
stkhapugin
2015/12/03 17:51:02
Done.
| |
53 [super dealloc]; | |
54 } | |
55 | |
56 - (instancetype)init { | |
57 self = [super init]; | |
58 if (self) { | |
59 [[NSNotificationCenter defaultCenter] | |
60 addObserver:self | |
61 selector:@selector(handleMemoryWarning) | |
62 name:UIApplicationDidReceiveMemoryWarningNotification | |
63 object:nil]; | |
64 } | |
65 return self; | |
66 } | |
67 | |
68 - (NSString*)requestScript { | |
69 if (!_requestScript) { | |
70 _requestScript = [web::GetPageScript(@"post_request") copy]; | |
71 } | |
72 return _requestScript; | |
73 } | |
74 | |
75 - (void)loadPOSTRequest:(NSURLRequest*)request | |
76 inWebView:(WKWebView*)webView | |
77 messageRouter:(CRWWKScriptMessageRouter*)messageRouter | |
78 completionBlock:(void (^)(NSError*))completionBlock { | |
79 DCHECK([request.HTTPMethod isEqualToString:@"POST"]); | |
80 DCHECK(webView); | |
81 DCHECK(messageRouter); | |
82 DCHECK(completionBlock); | |
83 | |
84 // Install error handling and success routers. | |
85 [messageRouter setScriptMessageHandler:^(WKScriptMessage* message) { | |
86 // Cleaning up script handlers. | |
87 // This needs to be done on next runloop because this block gets deallocated | |
88 // during its execution otherwise. | |
89 dispatch_async(dispatch_get_main_queue(), ^{ | |
90 [messageRouter removeScriptMessageHandlerForName:kErrorHandlerName | |
91 webView:webView]; | |
92 [messageRouter removeScriptMessageHandlerForName:kSuccessHandlerName | |
93 webView:webView]; | |
94 completionBlock(nil); | |
95 }); | |
96 } | |
97 name:kSuccessHandlerName | |
98 webView:webView]; | |
99 | |
100 [messageRouter setScriptMessageHandler:^(WKScriptMessage* message) { | |
101 NSNumber* statusCode = message.body; | |
102 NSError* error = [NSError errorWithDomain:@"http" | |
103 code:statusCode.integerValue | |
104 userInfo:nil]; | |
105 // Cleaning up script handlers. | |
106 // This needs to be done on next runloop because this block gets deallocated | |
107 // during its execution otherwise. | |
108 dispatch_async(dispatch_get_main_queue(), ^{ | |
109 [messageRouter removeScriptMessageHandlerForName:kErrorHandlerName | |
110 webView:webView]; | |
111 [messageRouter removeScriptMessageHandlerForName:kSuccessHandlerName | |
112 webView:webView]; | |
113 completionBlock(error); | |
114 }); | |
115 } | |
116 name:kErrorHandlerName | |
117 webView:webView]; | |
118 | |
119 NSString* HTML = | |
120 [NSString stringWithFormat:@"<html><script>%@%@</script></html>", | |
121 self.requestScript, | |
122 [self scriptToExecutePOSTRequest:request]]; | |
123 [webView loadHTMLString:HTML baseURL:request.URL]; | |
124 } | |
125 | |
126 #pragma mark - Private methods. | |
127 | |
128 - (void)handleMemoryWarning { | |
129 // Request script can be recreated from file at any moment. | |
130 [_requestScript release]; | |
131 _requestScript = nil; | |
132 } | |
133 | |
134 - (NSString*)scriptToExecutePOSTRequest:(NSURLRequest*)request { | |
135 NSDictionary* headers = [request allHTTPHeaderFields]; | |
136 NSString* headerString = [self JSONForJavaScriptFromRequestHeaders:headers]; | |
137 NSString* URLString = [[request URL] absoluteString]; | |
138 NSString* contentType = headers[@"Content-Type"]; | |
139 NSString* base64Data = [[request HTTPBody] base64EncodedStringWithOptions:0]; | |
140 | |
141 // Here |headerString| is already properly escaped when returned from | |
142 // -JSONForJavaScriptFromRequestHeaders:. | |
143 return | |
144 [NSString stringWithFormat: | |
145 @"__crPostRequestWorkaround.runPostRequest(%@, %@, %@, %@)", | |
146 EscapeAndQuoteStringForJavaScript(URLString), headerString, | |
147 EscapeAndQuoteStringForJavaScript(base64Data), | |
148 EscapeAndQuoteStringForJavaScript(contentType)]; | |
149 } | |
150 | |
151 - (NSString*)JSONForJavaScriptFromRequestHeaders:(NSDictionary*)headers { | |
152 NSData* headerData = nil; | |
Eugene But (OOO till 7-30)
2015/12/03 16:51:42
NIT: Move variable declaration to line 154 and com
stkhapugin
2015/12/03 17:51:02
Done.
| |
153 if (headers) { | |
154 headerData = | |
155 [NSJSONSerialization dataWithJSONObject:headers options:0 error:nil]; | |
156 if (headerData) { | |
157 // This string is properly escaped by NSJSONSerialization. It needs to | |
158 // have | |
159 // no quotes since JavaScripts takes this parameter as an | |
160 // Object<string, string>. | |
161 return [[[NSString alloc] initWithData:headerData | |
162 encoding:NSUTF8StringEncoding] autorelease]; | |
163 } | |
164 } | |
165 return @"{}"; | |
166 } | |
167 | |
168 @end | |
OLD | NEW |