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

Unified Diff: ios/web/web_state/ui/crw_wk_web_view_web_controller.mm

Issue 1375023002: Adds support for POST request with bodies on WKWebView. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: All comments addressed Created 5 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 side-by-side diff with in-line comments
Download patch
Index: ios/web/web_state/ui/crw_wk_web_view_web_controller.mm
diff --git a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm
index c680bac819c6c8de6d660337a0b4c3c270862794..fa30d41dbc8a707166c845d36e62f7c20e17bb1a 100644
--- a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm
+++ b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm
@@ -10,7 +10,7 @@
#include "base/ios/ios_util.h"
#include "base/ios/weak_nsobject.h"
#include "base/json/json_reader.h"
-#include "base/mac/objc_property_releaser.h"
+#import "base/mac/objc_property_releaser.h"
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
@@ -39,6 +39,7 @@
#import "ios/web/web_state/crw_pass_kit_downloader.h"
#import "ios/web/web_state/error_translation_util.h"
#include "ios/web/web_state/frame_info.h"
+#import "ios/web/web_state/js/crw_js_post_request_loader.h"
#import "ios/web/web_state/js/crw_js_window_id_manager.h"
#import "ios/web/web_state/ui/crw_web_controller+protected.h"
#import "ios/web/web_state/ui/crw_wk_script_message_router.h"
@@ -187,6 +188,9 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
// Handles downloading PassKit data for WKWebView. Lazy initialized.
base::scoped_nsobject<CRWPassKitDownloader> _passKitDownloader;
+ // Object for loading POST requests with body.
+ base::scoped_nsobject<CRWJSPOSTRequestLoader> _POSTRequestLoader;
+
// Whether the web page is currently performing window.history.pushState or
// window.history.replaceState
// Set to YES on window.history.willChangeState message. To NO on
@@ -233,6 +237,15 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
// Downloader for PassKit files. Lazy initialized.
@property(nonatomic, readonly) CRWPassKitDownloader* passKitDownloader;
+// Loads POST request with body in |_wkWebView| by constructing an HTML page
+// that executes the request through JavaScript and replaces document with the
+// result.
+// Note that this approach includes multiple body encodings and decodings, plus
+// the data is passed to |_wkWebView| on main thread.
+// This is necessary because WKWebView ignores POST request body.
+// Workaround for https://bugs.webkit.org/show_bug.cgi?id=145410
+- (void)loadPOSTRequest:(NSMutableURLRequest*)request;
+
// Returns the WKWebViewConfigurationProvider associated with the web
// controller's BrowserState.
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider;
@@ -557,20 +570,42 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
- (void)loadRequestForCurrentNavigationItem {
DCHECK(self.webView && !self.nativeController);
+ DCHECK([self currentSessionEntry]);
+
+ web::WKBackForwardListItemHolder* holder =
+ [self currentBackForwardListItemHolder];
+ BOOL isFormResubmission =
+ (holder->navigation_type() == WKNavigationTypeFormResubmitted ||
+ holder->navigation_type() == WKNavigationTypeFormSubmitted);
+ web::NavigationItemImpl* currentItem =
+ [self currentSessionEntry].navigationItemImpl;
+ NSData* POSTData = currentItem->GetPostData();
+ NSMutableURLRequest* request = [self requestForCurrentNavigationItem];
+
+ // If the request has POST data and is not a form resubmission, configure and
+ // run the POST request.
+ if (POSTData.length && !isFormResubmission) {
+ [request setHTTPMethod:@"POST"];
+ [request setHTTPBody:POSTData];
+ [request setAllHTTPHeaderFields:[self currentHTTPHeaders]];
+ [self registerLoadRequest:[self currentNavigationURL]
+ referrer:[self currentSessionEntryReferrer]
+ transition:[self currentTransition]];
+ [self loadPOSTRequest:request];
+ return;
+ }
ProceduralBlock defaultNavigationBlock = ^{
[self registerLoadRequest:[self currentNavigationURL]
referrer:[self currentSessionEntryReferrer]
transition:[self currentTransition]];
- [self loadRequest:[self requestForCurrentNavigationItem]];
+ [self loadRequest:request];
};
// If there is no corresponding WKBackForwardListItem, or the item is not in
// the current WKWebView's back-forward list, navigating using WKWebView API
// is not possible. In this case, fall back to the default navigation
// mechanism.
- web::WKBackForwardListItemHolder* holder =
- [self currentBackForwardListItemHolder];
if (!holder->back_forward_list_item() ||
![self isBackForwardListItemValid:holder->back_forward_list_item()]) {
defaultNavigationBlock();
@@ -594,10 +629,7 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
// If the request is not a form submission or resubmission, or the user
// doesn't need to confirm the load, then continue right away.
- web::NavigationItemImpl* currentItem =
- [self currentSessionEntry].navigationItemImpl;
- if ((holder->navigation_type() != WKNavigationTypeFormResubmitted &&
- holder->navigation_type() != WKNavigationTypeFormSubmitted) ||
+ if (!isFormResubmission ||
currentItem->ShouldSkipResubmitDataConfirmation()) {
webViewNavigationBlock();
return;
@@ -605,6 +637,7 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
// If the request is form submission or resubmission, then prompt the
// user before proceeding.
+ DCHECK(isFormResubmission);
[self.delegate webController:self
onFormResubmissionForRequest:nil
continueBlock:webViewNavigationBlock
@@ -715,6 +748,25 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
return self.webStateImpl->GetRequestTracker()->identifier();
}
+- (void)loadPOSTRequest:(NSMutableURLRequest*)request {
+ if (!_POSTRequestLoader) {
+ _POSTRequestLoader.reset([[CRWJSPOSTRequestLoader alloc] init]);
+ }
+
+ CRWWKScriptMessageRouter* messageRouter =
+ [self webViewConfigurationProvider].GetScriptMessageRouter();
+
+ [_POSTRequestLoader loadPOSTRequest:request
+ inWebView:_wkWebView
+ messageRouter:messageRouter
+ completionBlock:^(NSError* loadError) {
+ if (loadError)
+ [self handleLoadError:loadError inMainFrame:YES];
+ else
+ self.webStateImpl->SetContentsMimeType("text/html");
+ }];
+}
+
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider {
DCHECK(self.webStateImpl);
web::BrowserState* browserState = self.webStateImpl->GetBrowserState();
@@ -850,19 +902,11 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
web::WKBackForwardListItemHolder* holder =
[self currentBackForwardListItemHolder];
-
WKNavigationType navigationType =
_pendingNavigationInfo ? [_pendingNavigationInfo navigationType]
: WKNavigationTypeOther;
holder->set_back_forward_list_item([_wkWebView backForwardList].currentItem);
holder->set_navigation_type(navigationType);
-
- // Only update the MIME type in the holder if there was MIME type information
- // as part of this pending load. It will be nil when doing a fast
- // back/forward navigation, for instance, because the callback that would
- // populate it is not called in that flow.
- if ([_pendingNavigationInfo MIMEType])
- holder->set_mime_type([_pendingNavigationInfo MIMEType]);
}
- (BOOL)isBackForwardListItemValid:(WKBackForwardListItem*)item {
@@ -1542,15 +1586,10 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
return;
}
GURL jsURL([result UTF8String]);
- // Make sure that the window location is as expected,
- // and re-check the origin and web view URL to prevent
- // race conditions.
- // TODO(crbug.com/563568): The third check may drop same
- // document URL changes if pending URL change occurs
- // immediately after. Revisit heuristics to prevent this.
+ // Make sure that the URL is as expected, and re-check
Eugene But (OOO till 7-30) 2015/12/03 16:51:43 Please revert
stkhapugin 2015/12/03 17:51:03 Done.
+ // the origin to prevent race conditions.
if (jsURL == url &&
- _documentURL.GetOrigin() == url.GetOrigin() &&
- net::GURLWithNSURL([_wkWebView URL]) == url) {
+ _documentURL.GetOrigin() == url.GetOrigin()) {
Eugene But (OOO till 7-30) 2015/12/03 16:51:42 ditto
stkhapugin 2015/12/03 17:51:03 Done.
[self URLDidChangeWithoutDocumentChange:url];
}
}];
@@ -1714,17 +1753,6 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
DCHECK(_documentURL == self.lastRegisteredRequestURL);
self.webStateImpl->OnNavigationCommitted(_documentURL);
[self commitPendingNavigationInfo];
- if ([self currentBackForwardListItemHolder]->navigation_type() ==
Eugene But (OOO till 7-30) 2015/12/03 16:51:42 ditto
stkhapugin 2015/12/03 17:51:03 Done.
- WKNavigationTypeBackForward) {
- // A fast back/forward won't call decidePolicyForNavigationResponse, so
- // the MIME type needs to be updated explicitly.
- NSString* storedMIMEType =
- [self currentBackForwardListItemHolder]->mime_type();
- if (storedMIMEType) {
- self.webStateImpl->SetContentsMimeType(
- base::SysNSStringToUTF8(storedMIMEType));
- }
- }
[self webPageChanged];
[self updateSSLStatusForCurrentNavigationItem];

Powered by Google App Engine
This is Rietveld 408576698