diff --git a/ios/browser/web/BUILD.gn b/ios/browser/web/BUILD.gn index 7fb199f6cf7..1142cfd3cba 100644 --- a/ios/browser/web/BUILD.gn +++ b/ios/browser/web/BUILD.gn @@ -34,6 +34,7 @@ source_set("web") { "//brave/ios/browser/web/document_fetch", "//brave/ios/browser/web/force_paste", "//brave/ios/browser/web/logins", + "//brave/ios/browser/web/navigator", "//brave/ios/browser/web/night_mode", "//brave/ios/browser/web/page_metadata", "//brave/ios/browser/web/reader_mode", diff --git a/ios/browser/web/brave_web_client.mm b/ios/browser/web/brave_web_client.mm index 1a1209f9a3a..99711cc4037 100644 --- a/ios/browser/web/brave_web_client.mm +++ b/ios/browser/web/brave_web_client.mm @@ -26,6 +26,7 @@ #include "brave/ios/browser/web/document_fetch/document_fetch_javascript_feature.h" #include "brave/ios/browser/web/force_paste/force_paste_javascript_feature.h" #include "brave/ios/browser/web/logins/logins_javascript_feature.h" +#include "brave/ios/browser/web/navigator/brave_navigator_javascript_feature.h" #include "brave/ios/browser/web/night_mode/night_mode_javascript_feature.h" #include "brave/ios/browser/web/page_metadata/page_metadata_javascript_feature.h" #include "brave/ios/browser/web/reader_mode/reader_mode_javascript_feature.h" @@ -136,6 +137,7 @@ std::vector BraveWebClient::GetJavaScriptFeatures( features.push_back( brave_ads::AdsMediaReportingJavaScriptFeature::GetInstance()); features.push_back(AIChatDistillerJavaScriptFeature::GetInstance()); + features.push_back(BraveNavigatorJavaScriptFeature::GetInstance()); features.push_back(BraveSearchAdResultsJavaScriptFeature::GetInstance()); #if BUILDFLAG(ENABLE_BRAVE_TALK) features.push_back(BraveTalkLauncherJavaScriptFeature::GetInstance()); diff --git a/ios/browser/web/navigator/BUILD.gn b/ios/browser/web/navigator/BUILD.gn new file mode 100644 index 00000000000..7b9e6b8fabb --- /dev/null +++ b/ios/browser/web/navigator/BUILD.gn @@ -0,0 +1,24 @@ +# Copyright (c) 2026 The Brave Authors. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at https://mozilla.org/MPL/2.0/. + +import("//ios/web/public/js_messaging/optimize_ts.gni") + +source_set("navigator") { + sources = [ + "brave_navigator_javascript_feature.h", + "brave_navigator_javascript_feature.mm", + ] + deps = [ ":brave_navigator_js" ] + public_deps = [ + "//base", + "//ios/web/public/js_messaging", + ] +} + +optimize_ts("brave_navigator_js") { + visibility = [ ":navigator" ] + + sources = [ "resources/brave_navigator.ts" ] +} diff --git a/ios/browser/web/navigator/brave_navigator_javascript_feature.h b/ios/browser/web/navigator/brave_navigator_javascript_feature.h new file mode 100644 index 00000000000..8bc0d76cd56 --- /dev/null +++ b/ios/browser/web/navigator/brave_navigator_javascript_feature.h @@ -0,0 +1,25 @@ +// Copyright (c) 2026 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#ifndef BRAVE_IOS_BROWSER_WEB_NAVIGATOR_BRAVE_NAVIGATOR_JAVASCRIPT_FEATURE_H_ +#define BRAVE_IOS_BROWSER_WEB_NAVIGATOR_BRAVE_NAVIGATOR_JAVASCRIPT_FEATURE_H_ + +#include "base/no_destructor.h" +#include "ios/web/public/js_messaging/java_script_feature.h" + +class BraveNavigatorJavaScriptFeature : public web::JavaScriptFeature { + public: + // This feature holds no state, so only a single static instance is ever + // needed. + static BraveNavigatorJavaScriptFeature* GetInstance(); + + private: + friend class base::NoDestructor; + + BraveNavigatorJavaScriptFeature(); + ~BraveNavigatorJavaScriptFeature() override; +}; + +#endif // BRAVE_IOS_BROWSER_WEB_NAVIGATOR_BRAVE_NAVIGATOR_JAVASCRIPT_FEATURE_H_ diff --git a/ios/browser/web/navigator/brave_navigator_javascript_feature.mm b/ios/browser/web/navigator/brave_navigator_javascript_feature.mm new file mode 100644 index 00000000000..f24e3ed0d09 --- /dev/null +++ b/ios/browser/web/navigator/brave_navigator_javascript_feature.mm @@ -0,0 +1,28 @@ +// Copyright (c) 2026 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "brave/ios/browser/web/navigator/brave_navigator_javascript_feature.h" + +namespace { +constexpr char kScriptName[] = "brave_navigator"; +} // namespace + +BraveNavigatorJavaScriptFeature::BraveNavigatorJavaScriptFeature() + : JavaScriptFeature( + web::ContentWorld::kPageContentWorld, + {FeatureScript::CreateWithFilename( + kScriptName, + FeatureScript::InjectionTime::kDocumentStart, + FeatureScript::TargetFrames::kAllFrames, + FeatureScript::ReinjectionBehavior::kInjectOncePerWindow)}) {} + +BraveNavigatorJavaScriptFeature::~BraveNavigatorJavaScriptFeature() = default; + +// static +BraveNavigatorJavaScriptFeature* +BraveNavigatorJavaScriptFeature::GetInstance() { + static base::NoDestructor instance; + return instance.get(); +} diff --git a/ios/browser/web/navigator/resources/brave_navigator.ts b/ios/browser/web/navigator/resources/brave_navigator.ts new file mode 100644 index 00000000000..d5143c34b28 --- /dev/null +++ b/ios/browser/web/navigator/resources/brave_navigator.ts @@ -0,0 +1,13 @@ +// Copyright (c) 2026 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +Object.defineProperty(navigator, 'brave', { + enumerable: false, + configurable: true, + writable: false, + value: Object.freeze({ + isBrave: (): Promise => Promise.resolve(true) + }) +});