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

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: rest of the commetns Created 5 years, 2 months 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 368587eab562249bab292466ff34a608391942d3..8dc33797769a63e33b5e1ebb9df9202da6601acb 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
@@ -9,6 +9,7 @@
#include "base/ios/ios_util.h"
#include "base/ios/weak_nsobject.h"
#include "base/json/json_reader.h"
+#import "base/mac/objc_property_releaser.h"
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "base/strings/sys_string_conversions.h"
@@ -31,6 +32,7 @@
#include "ios/web/web_state/blocked_popup_info.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/js/page_script_util.h"
#import "ios/web/web_state/ui/crw_web_controller+protected.h"
@@ -85,6 +87,8 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
@interface CRWWKWebViewWebController () <WKNavigationDelegate,
WKScriptMessageHandler,
WKUIDelegate> {
+ base::mac::ObjCPropertyReleaser _propertyReleaser_CRWWKWebViewWebController;
Eugene But (OOO till 7-30) 2015/10/08 17:46:33 I would prefer to avoid mixing ObjCPropertyRelease
stkhapugin 2015/12/03 15:43:01 Done.
+
// The WKWebView managed by this instance.
base::scoped_nsobject<WKWebView> _wkWebView;
@@ -150,6 +154,9 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
// Response's MIME type of the last known navigation.
@property(nonatomic, copy) NSString* documentMIMEType;
+// Object for loading POST requests with body.
+@property(nonatomic, retain) CRWJSPOSTRequestLoader* POSTRequestLoader;
+
// Dictionary where keys are the names of WKWebView properties and values are
// selector names which should be called when a corresponding property has
// changed. e.g. @{ @"URL" : @"webViewURLDidChange" } means that
@@ -169,6 +176,16 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
@property(nonatomic, readonly) int certGroupID;
#endif // #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW)
+// Loads POST request with body in |_wkWebView| by constructing an HTML page
+// that executes the request through javascript and replaces document with the
Eugene But (OOO till 7-30) 2015/10/08 17:46:33 NIT: s/javascript/JavaScript
stkhapugin 2015/12/03 15:43:01 Done.
+// result.
+// Note that this approach includes multiple body encodings and decodings, plus
+// the data is passed to |_wkWebView| on main thread, hence the performance is
+// expected to be low.
+// This is necessary because WKWebView ignores POST request body.
+// Workaround for https://bugs.webkit.org/show_bug.cgi?id=145410
+- (void)loadPOSTRequestWithBody:(NSMutableURLRequest*)request;
Eugene But (OOO till 7-30) 2015/10/08 17:46:33 Word before argument should describe argument. Thi
stkhapugin 2015/12/03 15:43:01 Done.
+
// Returns the WKWebViewConfigurationProvider associated with the web
// controller's BrowserState.
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider;
@@ -296,6 +313,7 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
@end
@implementation CRWWKWebViewWebController
+@synthesize POSTRequestLoader = _POSTRequestLoader;
#pragma mark CRWWebController public methods
@@ -304,6 +322,8 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
web::BrowserState* browserState = webState->GetBrowserState();
self = [super initWithWebState:webState.Pass()];
if (self) {
+ _propertyReleaser_CRWWKWebViewWebController.Init(
+ self, [CRWWKWebViewWebController class]);
_certVerificationController.reset([[CRWCertVerificationController alloc]
initWithBrowserState:browserState]);
}
@@ -477,25 +497,34 @@ 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];
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();
- return;
- }
+ ProceduralBlock POSTBlock = ^{
+ [request setHTTPMethod:@"POST"];
+ [request setHTTPBody:POSTData];
+ [request setAllHTTPHeaderFields:[self currentHTTPHeaders]];
+ [self registerLoadRequest:[self currentNavigationURL]
+ referrer:[self currentSessionEntryReferrer]
+ transition:[self currentTransition]];
+ [self loadPOSTRequestWithBody:request];
+ };
ProceduralBlock webViewNavigationBlock = ^{
// If the current navigation URL is the same as the URL of the visible
@@ -512,12 +541,26 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
}
};
+ // If the request has POST data and is not a form resubmission, configure and
+ // run the POST request.
+ if (POSTData.length && !isFormResubmission) {
+ POSTBlock();
+ return;
+ }
+
+ // 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.
+ if (!holder->back_forward_list_item() ||
+ ![self isBackForwardListItemValid:holder->back_forward_list_item()]) {
+ defaultNavigationBlock();
+ return;
+ }
+
// 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;
@@ -525,6 +568,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
@@ -635,6 +679,14 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
}
#endif
+- (void)loadPOSTRequestWithBody:(NSMutableURLRequest*)request {
+ if (!self.POSTRequestLoader) {
+ _POSTRequestLoader = [[CRWJSPOSTRequestLoader alloc] init];
+ }
+
+ [self.POSTRequestLoader loadPOSTRequest:request inWebView:_wkWebView];
+}
+
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider {
DCHECK(self.webStateImpl);
web::BrowserState* browserState = self.webStateImpl->GetBrowserState();

Powered by Google App Engine
This is Rietveld 408576698