Commit e630daa3 authored by Yi Su's avatar Yi Su Committed by Commit Bot

Create CRWJSNavigationHandler.

This CL creates CRWJSNavigationHandler, and moves "window.hashchange"
handling from CRWWebController into this new class.

Bug: 956511
Change-Id: I84d756a80b3b34773fcd4bc02c9ba3da6d1398db
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1649683
Commit-Queue: Yi Su <mrsuyi@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#669157}
parent dbb68898
......@@ -25,6 +25,7 @@ source_set("navigation") {
"//ios/web/public",
"//ios/web/public/deprecated",
"//ios/web/public/download",
"//ios/web/public/js_messaging",
"//ios/web/public/security",
"//ios/web/public/session",
"//ios/web/security",
......@@ -39,6 +40,8 @@ source_set("navigation") {
]
sources = [
"crw_js_navigation_handler.h",
"crw_js_navigation_handler.mm",
"crw_navigation_item_holder.h",
"crw_navigation_item_holder.mm",
"crw_pending_navigation_info.h",
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_WEB_NAVIGATION_CRW_JS_NAVIGATION_HANDLER_H_
#define IOS_WEB_NAVIGATION_CRW_JS_NAVIGATION_HANDLER_H_
#import <Foundation/Foundation.h>
namespace web {
class WebStateImpl;
}
@class CRWJSNavigationHandler;
@protocol CRWJSNavigationHandlerDelegate
// Returns the WebStateImpl associated with this handler.
- (web::WebStateImpl*)webStateImplForJSNavigationHandler:
(CRWJSNavigationHandler*)navigationHandler;
@end
// Handles JS messages related to navigation(e.g. window.history.forward).
@interface CRWJSNavigationHandler : NSObject
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithDelegate:(id<CRWJSNavigationHandlerDelegate>)delegate
NS_DESIGNATED_INITIALIZER;
// Set to YES when a hashchange event is manually dispatched for same-document
// history navigations.
@property(nonatomic, assign) BOOL dispatchingSameDocumentHashChangeEvent;
// Instructs this handler to stop handling js navigation messages.
- (void)close;
@end
#endif // IOS_WEB_NAVIGATION_CRW_JS_NAVIGATION_HANDLER_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/web/navigation/crw_js_navigation_handler.h"
#import "ios/web/navigation/navigation_item_impl.h"
#import "ios/web/navigation/navigation_manager_impl.h"
#include "ios/web/public/js_messaging/web_frame.h"
#import "ios/web/web_state/web_state_impl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
const char kCommandPrefix[] = "navigation";
} // namespace
@interface CRWJSNavigationHandler ()
@property(nonatomic, weak) id<CRWJSNavigationHandlerDelegate> delegate;
@property(nonatomic, readonly, assign) web::WebStateImpl* webStateImpl;
@property(nonatomic, readonly, assign)
web::NavigationManagerImpl* navigationManagerImpl;
@end
@implementation CRWJSNavigationHandler
#pragma mark - Public
- (instancetype)initWithDelegate:(id<CRWJSNavigationHandlerDelegate>)delegate {
if (self = [super init]) {
_delegate = delegate;
__weak CRWJSNavigationHandler* weakSelf = self;
auto navigationStateCallback =
^bool(const base::DictionaryValue& message, const GURL&,
bool /* is_main_frame */, bool /* user_is_interacting */,
web::WebFrame* senderFrame) {
const std::string* command = message.FindStringKey("command");
DCHECK(command);
if (*command == "navigation.hashchange") {
[weakSelf handleWindowHashChangeInFrame:senderFrame];
return true;
}
return false;
};
self.webStateImpl->AddScriptCommandCallback(
base::BindRepeating(navigationStateCallback), kCommandPrefix);
}
return self;
}
- (void)close {
self.webStateImpl->RemoveScriptCommandCallback(kCommandPrefix);
}
#pragma mark - Private
- (web::WebStateImpl*)webStateImpl {
return [self.delegate webStateImplForJSNavigationHandler:self];
}
- (web::NavigationManagerImpl*)navigationManagerImpl {
return &(self.webStateImpl->GetNavigationManagerImpl());
}
// Handles the window.hashchange event emitted from |senderFrame|.
- (void)handleWindowHashChangeInFrame:(web::WebFrame*)senderFrame {
if (!senderFrame->IsMainFrame())
return;
// Record that the current NavigationItem was created by a hash change, but
// ignore hashchange events that are manually dispatched for same-document
// navigations.
if (self.dispatchingSameDocumentHashChangeEvent) {
self.dispatchingSameDocumentHashChangeEvent = NO;
} else {
web::NavigationItemImpl* item =
self.navigationManagerImpl->GetCurrentItemImpl();
item->SetIsCreatedFromHashChange(true);
}
}
@end
......@@ -110,7 +110,7 @@ window.addEventListener('hashchange', function(evt) {
'favicons': __gCrWeb.common.getFavicons()
});
__gCrWeb.message.invokeOnHost({'command': 'window.hashchange'});
__gCrWeb.message.invokeOnHost({'command': 'navigation.hashchange'});
});
/** Flush the message queue. */
......
......@@ -54,6 +54,7 @@
#import "ios/web/js_messaging/crw_wk_script_message_router.h"
#import "ios/web/js_messaging/web_frame_impl.h"
#import "ios/web/js_messaging/web_frames_manager_impl.h"
#import "ios/web/navigation/crw_js_navigation_handler.h"
#import "ios/web/navigation/crw_navigation_item_holder.h"
#import "ios/web/navigation/crw_pending_navigation_info.h"
#import "ios/web/navigation/crw_web_view_navigation_observer.h"
......@@ -184,6 +185,7 @@ GURL URLEscapedForHistory(const GURL& url) {
CRWWebControllerContainerViewDelegate,
CRWWebViewNavigationObserverDelegate,
CRWWebRequestControllerDelegate,
CRWJSNavigationHandlerDelegate,
CRWWebViewScrollViewProxyObserver,
CRWWKNavigationHandlerDelegate,
CRWWKUIHandlerDelegate,
......@@ -220,9 +222,6 @@ GURL URLEscapedForHistory(const GURL& url) {
// Set to YES on window.history.willChangeState message. To NO on
// window.history.didPushState or window.history.didReplaceState.
BOOL _changingHistoryState;
// Set to YES when a hashchange event is manually dispatched for same-document
// history navigations.
BOOL _dispatchingSameDocumentHashChangeEvent;
// Updates SSLStatus for current navigation item.
CRWSSLStatusUpdater* _SSLStatusUpdater;
......@@ -239,6 +238,8 @@ GURL URLEscapedForHistory(const GURL& url) {
// The WKNavigationDelegate handler class.
@property(nonatomic, readonly, strong)
CRWWKNavigationHandler* navigationHandler;
@property(nonatomic, readonly, strong)
CRWJSNavigationHandler* JSNavigationHandler;
// The WKUIDelegate handler class.
@property(nonatomic, readonly, strong) CRWWKUIHandler* UIHandler;
......@@ -431,6 +432,9 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
_navigationHandler.delegate = self;
_requestController.navigationHandler = _navigationHandler;
_JSNavigationHandler =
[[CRWJSNavigationHandler alloc] initWithDelegate:self];
_UIHandler = [[CRWWKUIHandler alloc] init];
_UIHandler.delegate = self;
......@@ -723,6 +727,7 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
_SSLStatusUpdater = nil;
[self.UIHandler close];
[self.JSNavigationHandler close];
self.swipeRecognizerProvider = nil;
[self.legacyNativeController close];
......@@ -1605,7 +1610,8 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
// be reset when resonding to the hashchange message. Note that resetting the
// flag in the completion block below is too early, as that block is called
// before hashchange event listeners have a chance to fire.
_dispatchingSameDocumentHashChangeEvent = shouldDispatchHashchange;
self.JSNavigationHandler.dispatchingSameDocumentHashChangeEvent =
shouldDispatchHashchange;
// Inject the JavaScript to update the state on the browser side.
[self injectHTML5HistoryScriptWithHashChange:shouldDispatchHashchange
sameDocumentNavigation:sameDocumentNavigation];
......@@ -1831,8 +1837,6 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
(*handlers)["document.favicons"] =
@selector(handleDocumentFaviconsMessage:context:);
(*handlers)["window.error"] = @selector(handleWindowErrorMessage:context:);
(*handlers)["window.hashchange"] =
@selector(handleWindowHashChangeMessage:context:);
(*handlers)["window.history.back"] =
@selector(handleWindowHistoryBackMessage:context:);
(*handlers)["window.history.willChangeState"] =
......@@ -2034,25 +2038,6 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
return YES;
}
// Handles 'window.hashchange' message.
- (BOOL)handleWindowHashChangeMessage:(base::DictionaryValue*)message
context:(NSDictionary*)context {
if (![context[kIsMainFrame] boolValue])
return NO;
// Record that the current NavigationItem was created by a hash change, but
// ignore hashchange events that are manually dispatched for same-document
// navigations.
if (_dispatchingSameDocumentHashChangeEvent) {
_dispatchingSameDocumentHashChangeEvent = NO;
} else {
web::NavigationItemImpl* item = self.currentNavItem;
DCHECK(item);
item->SetIsCreatedFromHashChange(true);
}
return YES;
}
// Handles 'window.history.back' message.
- (BOOL)handleWindowHistoryBackMessage:(base::DictionaryValue*)message
context:(NSDictionary*)context {
......@@ -3225,6 +3210,13 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
}
}
#pragma mark - CRWJSNavigationHandlerDelegate
- (web::WebStateImpl*)webStateImplForJSNavigationHandler:
(CRWJSNavigationHandler*)navigationHandler {
return self.webStateImpl;
}
#pragma mark - Testing-Only Methods
- (void)injectWebViewContentView:(CRWWebViewContentView*)webViewContentView {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment