Commit 0f73b636 authored by Yi Su's avatar Yi Su Committed by Commit Bot

Create WindowErrorManager to handle window.error

This CL moves the hanler method for window.error Js message from
CRWWebController into WindowErrorManager. All unused and unnecessary
methods in CRWWebController for Js message handling are also removed.

Bug: 956516
Change-Id: If0823bc3cdab1042538ce314626681bcd28ad56e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1674014
Commit-Queue: Yi Su <mrsuyi@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#671996}
parent 84cded1d
......@@ -61,6 +61,8 @@ source_set("ui") {
"crw_wk_ui_handler.h",
"crw_wk_ui_handler.mm",
"crw_wk_ui_handler_delegate.h",
"js_window_error_manager.h",
"js_window_error_manager.mm",
"wk_security_origin_util.h",
"wk_security_origin_util.mm",
]
......
......@@ -55,6 +55,7 @@
#import "ios/web/web_state/ui/crw_web_view_proxy_impl.h"
#import "ios/web/web_state/ui/crw_wk_ui_handler.h"
#import "ios/web/web_state/ui/crw_wk_ui_handler_delegate.h"
#import "ios/web/web_state/ui/js_window_error_manager.h"
#import "ios/web/web_state/ui/wk_security_origin_util.h"
#import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
#import "ios/web/web_state/user_interaction_state.h"
......@@ -153,6 +154,9 @@ NSString* const kFrameBecameUnavailableMessageName = @"FrameBecameUnavailable";
// Manager for favicon JavaScript messages.
std::unique_ptr<web::FaviconManager> _faviconManager;
// Manager for window.error message.
std::unique_ptr<web::JsWindowErrorManager> _jsWindowErrorManager;
}
// The WKNavigationDelegate handler class.
......@@ -245,13 +249,6 @@ NSString* const kFrameBecameUnavailableMessageName = @"FrameBecameUnavailable";
// may be called multiple times and thus must be idempotent.
- (void)loadCompleteWithSuccess:(BOOL)loadSuccess
forContext:(web::NavigationContextImpl*)context;
// Acts on a single message from the JS object, parsed from JSON into a
// DictionaryValue. Returns NO if the format for the message was invalid.
- (BOOL)respondToMessage:(base::DictionaryValue*)crwMessage
userIsInteracting:(BOOL)userIsInteracting
originURL:(const GURL&)originURL
isMainFrame:(BOOL)isMainFrame
senderFrame:(web::WebFrame*)senderFrame;
// Called when web controller receives a new message from the web page.
- (void)didReceiveScriptMessage:(WKScriptMessage*)message;
// Attempts to handle a script message. Returns YES on success, NO otherwise.
......@@ -333,6 +330,8 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
web::WebFramesManagerImpl::CreateForWebState(_webStateImpl);
web::FindInPageManagerImpl::CreateForWebState(_webStateImpl);
_faviconManager = std::make_unique<web::FaviconManager>(_webStateImpl);
_jsWindowErrorManager =
std::make_unique<web::JsWindowErrorManager>(_webStateImpl);
_legacyNativeController =
[[CRWLegacyNativeContentController alloc] initWithWebState:webState];
_legacyNativeController.delegate = self;
......@@ -624,7 +623,7 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
[self.UIHandler close];
[self.JSNavigationHandler close];
_faviconManager.reset();
_jsWindowErrorManager.reset();
self.swipeRecognizerProvider = nil;
[self.legacyNativeController close];
......@@ -1385,56 +1384,6 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
#pragma mark - JavaScript message Helpers (Private)
- (BOOL)respondToMessage:(base::DictionaryValue*)message
userIsInteracting:(BOOL)userIsInteracting
originURL:(const GURL&)originURL
isMainFrame:(BOOL)isMainFrame
senderFrame:(web::WebFrame*)senderFrame {
std::string command;
if (!message->GetString("command", &command)) {
DLOG(WARNING) << "JS message parameter not found: command";
return NO;
}
SEL handler = [self selectorToHandleJavaScriptCommand:command];
if (!handler) {
if (self.webStateImpl->OnScriptCommandReceived(command, *message, originURL,
userIsInteracting,
isMainFrame, senderFrame)) {
return YES;
}
// Message was either unexpected or not correctly handled.
// Page is reset as a precaution.
DLOG(WARNING) << "Unexpected message received: " << command;
return NO;
}
typedef BOOL (*HandlerType)(id, SEL, base::DictionaryValue*, NSDictionary*);
HandlerType handlerImplementation =
reinterpret_cast<HandlerType>([self methodForSelector:handler]);
DCHECK(handlerImplementation);
NSMutableDictionary* context =
[NSMutableDictionary dictionaryWithObject:@(userIsInteracting)
forKey:kUserIsInteractingKey];
NSURL* originNSURL = net::NSURLWithGURL(originURL);
if (originNSURL)
context[kOriginURLKey] = originNSURL;
context[kIsMainFrame] = @(isMainFrame);
return handlerImplementation(self, handler, message, context);
}
- (SEL)selectorToHandleJavaScriptCommand:(const std::string&)command {
static std::map<std::string, SEL>* handlers = nullptr;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
handlers = new std::map<std::string, SEL>();
(*handlers)["window.error"] = @selector(handleWindowErrorMessage:context:);
});
DCHECK(handlers);
auto iter = handlers->find(command);
return iter != handlers->end() ? iter->second : nullptr;
}
- (void)didReceiveScriptMessage:(WKScriptMessage*)message {
// Broken out into separate method to catch errors.
if (![self respondToWKScriptMessage:message]) {
......@@ -1464,16 +1413,27 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
return NO;
}
base::DictionaryValue* command = nullptr;
if (!message->GetDictionary("crwCommand", &command)) {
base::DictionaryValue* crwCommand = nullptr;
if (!message->GetDictionary("crwCommand", &crwCommand)) {
return NO;
}
return [self
respondToMessage:command
userIsInteracting:_userInteractionState.IsUserInteracting(self.webView)
originURL:net::GURLWithNSURL(self.webView.URL)
isMainFrame:scriptMessage.frameInfo.mainFrame
senderFrame:senderFrame];
std::string command;
if (!crwCommand->GetString("command", &command)) {
DLOG(WARNING) << "JS message parameter not found: command";
return NO;
}
if (self.webStateImpl->OnScriptCommandReceived(
command, *crwCommand, net::GURLWithNSURL(self.webView.URL),
_userInteractionState.IsUserInteracting(self.webView),
scriptMessage.frameInfo.mainFrame, senderFrame)) {
return YES;
}
// Message was either unexpected or not correctly handled.
// Page is reset as a precaution.
DLOG(WARNING) << "Unexpected message received: " << command;
return NO;
}
#pragma mark - Web frames management
......@@ -1542,24 +1502,6 @@ typedef void (^ViewportStateCompletion)(const web::PageViewportState*);
}
}
#pragma mark - JavaScript message handlers
// Handlers for JavaScript messages. |message| contains a JavaScript command and
// data relevant to the message, and |context| contains contextual information
// about web view state needed for some handlers.
// Handles 'window.error' message.
- (BOOL)handleWindowErrorMessage:(base::DictionaryValue*)message
context:(NSDictionary*)context {
std::string errorMessage;
if (!message->GetString("message", &errorMessage)) {
DLOG(WARNING) << "JS message parameter not found: message";
return NO;
}
DLOG(ERROR) << "JavaScript error: " << errorMessage
<< " URL:" << [self currentURL].spec();
return YES;
}
#pragma mark - WebUI
// Sets up WebUI for URL.
......
// 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_WEB_STATE_UI_JS_WINDOW_ERROR_MANAGER_H_
#define IOS_WEB_WEB_STATE_UI_JS_WINDOW_ERROR_MANAGER_H_
#include "base/macros.h"
namespace base {
class DictionaryValue;
}
class GURL;
namespace web {
class WebState;
class WebFrame;
// Handles "window.error" message from injected JavaScript and DLOG it.
class JsWindowErrorManager final {
public:
explicit JsWindowErrorManager(WebState* web_state);
~JsWindowErrorManager();
private:
bool OnJsMessage(const base::DictionaryValue& message,
const GURL& page_url,
bool has_user_gesture,
bool in_main_frame,
WebFrame* sender_frame);
WebState* web_state_impl_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(JsWindowErrorManager);
};
} // namespace web
#endif // IOS_WEB_WEB_STATE_UI_JS_WINDOW_ERROR_MANAGER_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/web_state/ui/js_window_error_manager.h"
#import "base/values.h"
#import "ios/web/public/js_messaging/web_frame.h"
#import "ios/web/public/web_state/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
const char kCommandPrefix[] = "window";
}
namespace web {
JsWindowErrorManager::JsWindowErrorManager(WebState* web_state)
: web_state_impl_(web_state) {
web_state_impl_->AddScriptCommandCallback(
base::BindRepeating(&JsWindowErrorManager::OnJsMessage,
base::Unretained(this)),
kCommandPrefix);
}
JsWindowErrorManager::~JsWindowErrorManager() {
web_state_impl_->RemoveScriptCommandCallback(kCommandPrefix);
}
bool JsWindowErrorManager::OnJsMessage(const base::DictionaryValue& message,
const GURL& page_url,
bool has_user_gesture,
bool form_in_main_frame,
WebFrame* sender_frame) {
DCHECK(sender_frame->IsMainFrame());
std::string error_message;
if (!message.GetString("message", &error_message)) {
DLOG(WARNING) << "JS message parameter not found: message";
return NO;
}
web::URLVerificationTrustLevel trust_level =
web::URLVerificationTrustLevel::kNone;
const GURL current_url = web_state_impl_->GetCurrentURL(&trust_level);
DLOG(ERROR) << "JavaScript error: " << error_message
<< " URL:" << current_url.spec();
return true;
}
} // namespace web
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