// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/web/js_messaging/java_script_feature_util_impl.h"
#import <Foundation/Foundation.h>
#import "base/ios/ios_util.h"
#import "base/logging.h"
#import "base/no_destructor.h"
#import "base/strings/sys_string_conversions.h"
#import "ios/web/annotations/annotations_java_script_feature.h"
#import "ios/web/common/annotations_utils.h"
#import "ios/web/common/features.h"
#import "ios/web/favicon/favicon_java_script_feature.h"
#import "ios/web/find_in_page/find_in_page_java_script_feature.h"
#import "ios/web/js_features/context_menu/context_menu_java_script_feature.h"
#import "ios/web/js_features/error_page/error_page_java_script_feature.h"
#import "ios/web/js_features/fullscreen/fullscreen_java_script_feature.h"
#import "ios/web/js_features/scroll_helper/scroll_helper_java_script_feature.h"
#import "ios/web/js_features/window_error/window_error_java_script_feature.h"
#import "ios/web/js_messaging/web_frames_manager_java_script_feature.h"
#import "ios/web/navigation/navigation_java_script_feature.h"
#import "ios/web/navigation/session_restore_java_script_feature.h"
#import "ios/web/public/js_messaging/content_world.h"
#import "ios/web/public/js_messaging/java_script_feature.h"
#import "ios/web/public/web_client.h"
#import "ios/web/text_fragments/text_fragments_java_script_feature.h"
#import "ios/web/webui/web_ui_messaging_java_script_feature.h"
namespace web {
namespace {
const char kBaseScriptName[] = "gcrweb";
const char kCommonScriptName[] = "common";
const char kMessageScriptName[] = "message";
const char kMainFrameDescription[] = "Main frame";
const char kIframeDescription[] = "Iframe";
FaviconJavaScriptFeature* GetFaviconJavaScriptFeature() {
// Static storage is ok for `favicon_feature` as it holds no state.
static base::NoDestructor<FaviconJavaScriptFeature> favicon_feature;
return favicon_feature.get();
}
WindowErrorJavaScriptFeature* GetWindowErrorJavaScriptFeature() {
// Static storage is ok for `window_error_feature` as it holds no state.
static base::NoDestructor<WindowErrorJavaScriptFeature> window_error_feature(
base::BindRepeating(^(
WindowErrorJavaScriptFeature::ErrorDetails error_details) {
// Displays the JavaScript error details in the following format:
// _________ JavaScript error: _________
// {error_message}
// {url} | {filename}:{line_number}
// {kMainFrameDescription|kIframeDescription}
const char* frame_description = error_details.is_main_frame
? kMainFrameDescription
: kIframeDescription;
DLOG(ERROR) << "\n_________ JavaScript error: _________"
<< "\n " << base::SysNSStringToUTF8(error_details.message)
<< "\n " << error_details.url.spec() << " | "
<< base::SysNSStringToUTF8(error_details.filename) << ":"
<< error_details.line_number << "\n " << frame_description;
}));
return window_error_feature.get();
}
} // namespace
namespace java_script_features {
std::vector<JavaScriptFeature*> GetBuiltInJavaScriptFeatures(
BrowserState* browser_state) {
std::vector<JavaScriptFeature*> features = {
GetBaseJavaScriptFeature(),
GetCommonJavaScriptFeature(),
GetMessageJavaScriptFeature(),
ContextMenuJavaScriptFeature::FromBrowserState(browser_state),
ErrorPageJavaScriptFeature::GetInstance(),
FindInPageJavaScriptFeature::GetInstance(),
FullscreenJavaScriptFeature::GetInstance(),
GetFaviconJavaScriptFeature(),
GetScrollHelperJavaScriptFeature(),
GetWindowErrorJavaScriptFeature(),
NavigationJavaScriptFeature::GetInstance(),
SessionRestoreJavaScriptFeature::FromBrowserState(browser_state),
TextFragmentsJavaScriptFeature::GetInstance(),
WebUIMessagingJavaScriptFeature::GetInstance(),
AnnotationsJavaScriptFeature::GetInstance()};
auto frames_manager_features = WebFramesManagerJavaScriptFeature::
AllContentWorldFeaturesFromBrowserState(browser_state);
features.insert(features.end(), frames_manager_features.begin(),
frames_manager_features.end());
return features;
}
ScrollHelperJavaScriptFeature* GetScrollHelperJavaScriptFeature() {
// Static storage is ok for `scroll_helper_feature` as it holds no state.
static base::NoDestructor<ScrollHelperJavaScriptFeature>
scroll_helper_feature;
return scroll_helper_feature.get();
}
JavaScriptFeature* GetBaseJavaScriptFeature() {
// Static storage is ok for `base_feature` as it holds no state.
static base::NoDestructor<JavaScriptFeature> base_feature(
ContentWorld::kAllContentWorlds,
std::vector<JavaScriptFeature::FeatureScript>(
{JavaScriptFeature::FeatureScript::CreateWithFilename(
kBaseScriptName,
JavaScriptFeature::FeatureScript::InjectionTime::kDocumentStart,
JavaScriptFeature::FeatureScript::TargetFrames::kAllFrames)}));
return base_feature.get();
}
JavaScriptFeature* GetCommonJavaScriptFeature() {
// Static storage is ok for `common_feature` as it holds no state.
static base::NoDestructor<JavaScriptFeature> common_feature(
ContentWorld::kAllContentWorlds,
std::vector<JavaScriptFeature::FeatureScript>(
{JavaScriptFeature::FeatureScript::CreateWithFilename(
kCommonScriptName,
JavaScriptFeature::FeatureScript::InjectionTime::kDocumentStart,
JavaScriptFeature::FeatureScript::TargetFrames::kAllFrames)}),
std::vector<const JavaScriptFeature*>({GetBaseJavaScriptFeature()}));
return common_feature.get();
}
JavaScriptFeature* GetMessageJavaScriptFeature() {
// Static storage is ok for `message_feature` as it holds no state.
static base::NoDestructor<JavaScriptFeature> message_feature(
ContentWorld::kAllContentWorlds,
std::vector<JavaScriptFeature::FeatureScript>(
{JavaScriptFeature::FeatureScript::CreateWithFilename(
kMessageScriptName,
JavaScriptFeature::FeatureScript::InjectionTime::kDocumentStart,
JavaScriptFeature::FeatureScript::TargetFrames::kAllFrames)}),
std::vector<const JavaScriptFeature*>({GetCommonJavaScriptFeature()}));
return message_feature.get();
}
} // namespace java_script_features
} // namespace web