diff --git a/build/config/brave_build.gni b/build/config/brave_build.gni
index e32e2cef519b..0afbaa413120 100644
--- a/build/config/brave_build.gni
+++ b/build/config/brave_build.gni
@@ -4,3 +4,4 @@
import("//brave/brave_repack_locales.gni")
import("//brave/build/features.gni")
import("//brave/net/sources.gni")
+import("//brave/third_party/blink/renderer/includes.gni")
diff --git a/patches/third_party-blink-renderer-core-BUILD.gn.patch b/patches/third_party-blink-renderer-core-BUILD.gn.patch
index 98a0df0fb999..95a3ccdbb440 100644
--- a/patches/third_party-blink-renderer-core-BUILD.gn.patch
+++ b/patches/third_party-blink-renderer-core-BUILD.gn.patch
@@ -1,12 +1,20 @@
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
-index 1c2e3e6e2872729dace5c1582ffe596aadcf1e52..5711edbdac5549f94e184b74ae97d9d2f968cea8 100644
+index 1c2e3e6e2872729dace5c1582ffe596aadcf1e52..a1bca85a0fa514dd6a17d7717cec72e4bbc5ca71 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
-@@ -214,6 +214,7 @@ component("core") {
+@@ -143,6 +143,7 @@ component("core") {
+
+ visibility = [] # Allow re-assignment of list.
+ visibility = [ "//third_party/blink/*" ]
++ visibility += brave_blink_renderer_core_visibility
+
+ # If you create a new subdirectory, make a new BUILD file for that directory
+ # and reference it in the deps below rather than adding the sources here.
+@@ -214,6 +215,7 @@ component("core") {
"//url",
"//v8",
]
-+ public_deps += [ "//brave/third_party/blink/renderer" ]
++ public_deps += brave_blink_renderer_core_public_deps
deps = [
"//third_party/blink/public/common",
"//third_party/blink/renderer/platform",
diff --git a/patches/third_party-blink-renderer-modules-BUILD.gn.patch b/patches/third_party-blink-renderer-modules-BUILD.gn.patch
new file mode 100644
index 000000000000..565aee998c8a
--- /dev/null
+++ b/patches/third_party-blink-renderer-modules-BUILD.gn.patch
@@ -0,0 +1,20 @@
+diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
+index 0f0b26ea466715b40326179e5b1f57005e00a3f9..a53b72af790baa64cf7c18783af7296a837db490 100644
+--- a/third_party/blink/renderer/modules/BUILD.gn
++++ b/third_party/blink/renderer/modules/BUILD.gn
+@@ -16,6 +16,7 @@ if (is_android) {
+ }
+
+ visibility = [ "//third_party/blink/renderer/*" ]
++visibility += brave_blink_renderer_modules_visibility
+
+ config("modules_implementation") {
+ defines = [ "BLINK_MODULES_IMPLEMENTATION=1" ]
+@@ -155,6 +156,7 @@ jumbo_component("modules") {
+ "//third_party/blink/renderer/modules/xr",
+ ]
+
++ sub_modules += brave_blink_sub_modules
+ deps = [
+ ":make_modules_generated",
+ ":module_names",
diff --git a/patches/third_party-blink-renderer-modules-modules_idl_files.gni.patch b/patches/third_party-blink-renderer-modules-modules_idl_files.gni.patch
new file mode 100644
index 000000000000..8e62e3db0cd0
--- /dev/null
+++ b/patches/third_party-blink-renderer-modules-modules_idl_files.gni.patch
@@ -0,0 +1,20 @@
+diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
+index 1bb5f1a07397e4f5c2cac8388a96976c12e21787..81919dea27f8c21e45285f1911407a0ee6228445 100644
+--- a/third_party/blink/renderer/modules/modules_idl_files.gni
++++ b/third_party/blink/renderer/modules/modules_idl_files.gni
+@@ -543,6 +543,7 @@ modules_idl_files =
+ ],
+ "abspath")
+
++modules_idl_files += brave_modules_idl_files
+ if (!is_android) {
+ modules_idl_files += get_path_info([
+ "serial/serial.idl",
+@@ -1030,6 +1031,7 @@ modules_dependency_idl_files =
+ "xr/navigator_xr.idl",
+ ],
+ "abspath")
++modules_dependency_idl_files += brave_modules_dependency_idl_files
+
+ if (!is_android) {
+ modules_dependency_idl_files +=
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 0dd1f14310a8..17d3351edadc 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -586,6 +586,7 @@ test("brave_browser_tests") {
"//brave/renderer/brave_content_settings_agent_impl_autoplay_browsertest.cc",
"//brave/renderer/brave_content_settings_agent_impl_browsertest.cc",
"//brave/renderer/brave_content_settings_agent_impl_flash_browsertest.cc",
+ "//brave/third_party/blink/renderer/modules/brave/navigator_browsertest.cc",
"//chrome/browser/extensions/browsertest_util.cc",
"//chrome/browser/extensions/browsertest_util.h",
"//chrome/browser/extensions/extension_browsertest.cc",
diff --git a/test/data/detect_brave.html b/test/data/detect_brave.html
new file mode 100644
index 000000000000..b1e3e99182fb
--- /dev/null
+++ b/test/data/detect_brave.html
@@ -0,0 +1,11 @@
+
diff --git a/third_party/blink/renderer/includes.gni b/third_party/blink/renderer/includes.gni
new file mode 100644
index 000000000000..1ccaae2cd9e4
--- /dev/null
+++ b/third_party/blink/renderer/includes.gni
@@ -0,0 +1,29 @@
+# common includes which can help minimize patches for
+# src/third_party/blink/renderer/core/BUILD.gn
+brave_blink_renderer_core_visibility = [
+ "//brave/third_party/blink/renderer/*"
+]
+
+brave_blink_renderer_core_public_deps = [
+ "//brave/third_party/blink/renderer"
+]
+
+# common includes which can help minimize patches for
+# src/third_party/blink/renderer/modules/BUILD.gn
+brave_blink_renderer_modules_visibility = [
+ "//brave/third_party/blink/renderer/*"
+]
+
+brave_blink_sub_modules = [
+ "//brave/third_party/blink/renderer/modules/brave"
+]
+
+# common includes which can help minimize patches for
+# src/third_party/blink/renderer/modules/modules_idl_files.gni
+brave_modules_idl_files = get_path_info([
+ "//brave/third_party/blink/renderer/modules/brave/brave.idl",
+], "abspath")
+
+brave_modules_dependency_idl_files = get_path_info([
+ "//brave/third_party/blink/renderer/modules/brave/navigator_brave.idl",
+], "abspath")
diff --git a/third_party/blink/renderer/modules/brave/BUILD.gn b/third_party/blink/renderer/modules/brave/BUILD.gn
new file mode 100644
index 000000000000..6bcdfe8997c0
--- /dev/null
+++ b/third_party/blink/renderer/modules/brave/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright (c) 2019 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 http://mozilla.org/MPL/2.0/.
+
+import("//third_party/blink/renderer/modules/modules.gni")
+
+blink_modules_sources("brave") {
+ sources = [
+ "brave.cc",
+ "brave.h",
+ "navigator_brave.cc",
+ "navigator_brave.h",
+ ]
+}
diff --git a/third_party/blink/renderer/modules/brave/brave.cc b/third_party/blink/renderer/modules/brave/brave.cc
new file mode 100644
index 000000000000..031cc2a000df
--- /dev/null
+++ b/third_party/blink/renderer/modules/brave/brave.cc
@@ -0,0 +1,20 @@
+/* Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/. */
+
+#include "brave/third_party/blink/renderer/modules/brave/brave.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+
+namespace blink {
+
+ScriptPromise Brave::isBrave(ScriptState* script_state) {
+ auto* resolver = MakeGarbageCollected(script_state);
+ ScriptPromise promise = resolver->Promise();
+ resolver->Resolve(true);
+ return promise;
+}
+
+} // namespace blink
diff --git a/third_party/blink/renderer/modules/brave/brave.h b/third_party/blink/renderer/modules/brave/brave.h
new file mode 100644
index 000000000000..d7482056dada
--- /dev/null
+++ b/third_party/blink/renderer/modules/brave/brave.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/.
+
+#ifndef BRAVE_THIRD_PARTY_BLINK_RENDERER_MODULES_BRAVE_BRAVE_H_
+#define BRAVE_THIRD_PARTY_BLINK_RENDERER_MODULES_BRAVE_BRAVE_H_
+
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class ScriptPromise;
+class ScriptState;
+
+class MODULES_EXPORT Brave final
+ : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ Brave() = default;
+ ScriptPromise isBrave(ScriptState*);
+};
+
+} // namespace blink
+
+#endif // BRAVE_THIRD_PARTY_BLINK_RENDERER_MODULES_BRAVE_BRAVE_H_
diff --git a/third_party/blink/renderer/modules/brave/brave.idl b/third_party/blink/renderer/modules/brave/brave.idl
new file mode 100644
index 000000000000..333fd5e298d9
--- /dev/null
+++ b/third_party/blink/renderer/modules/brave/brave.idl
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/. */
+interface Brave {
+ [CallWith=ScriptState] Promise isBrave();
+};
diff --git a/third_party/blink/renderer/modules/brave/navigator_brave.cc b/third_party/blink/renderer/modules/brave/navigator_brave.cc
new file mode 100644
index 000000000000..0b15aa6e5de5
--- /dev/null
+++ b/third_party/blink/renderer/modules/brave/navigator_brave.cc
@@ -0,0 +1,45 @@
+/* Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/. */
+
+#include "brave/third_party/blink/renderer/modules/brave/navigator_brave.h"
+
+#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "brave/third_party/blink/renderer/modules/brave/brave.h"
+
+namespace blink {
+
+NavigatorBrave::NavigatorBrave(Navigator& navigator)
+ : Supplement(navigator) {}
+
+// static
+const char NavigatorBrave::kSupplementName[] = "NavigatorBrave";
+
+NavigatorBrave& NavigatorBrave::From(Navigator& navigator) {
+ NavigatorBrave* supplement =
+ Supplement::From(navigator);
+ if (!supplement) {
+ supplement = MakeGarbageCollected(navigator);
+ ProvideTo(navigator, supplement);
+ }
+ return *supplement;
+}
+
+Brave* NavigatorBrave::brave(Navigator& navigator) {
+ return NavigatorBrave::From(navigator).brave();
+}
+
+Brave* NavigatorBrave::brave() {
+ if (!brave_) {
+ brave_ = MakeGarbageCollected();
+ }
+ return brave_;
+}
+
+void NavigatorBrave::Trace(blink::Visitor* visitor) {
+ visitor->Trace(brave_);
+ Supplement::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/third_party/blink/renderer/modules/brave/navigator_brave.h b/third_party/blink/renderer/modules/brave/navigator_brave.h
new file mode 100644
index 000000000000..fc4b5a6658bd
--- /dev/null
+++ b/third_party/blink/renderer/modules/brave/navigator_brave.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/.
+
+#ifndef BRAVE_THIRD_PARTY_BLINK_RENDERER_MODULES_BRAVE_NAVIGATOR_BRAVE_H_
+#define BRAVE_THIRD_PARTY_BLINK_RENDERER_MODULES_BRAVE_NAVIGATOR_BRAVE_H_
+
+#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class Brave;
+class Navigator;
+
+class NavigatorBrave final
+ : public GarbageCollected,
+ public Supplement,
+ public NameClient {
+ USING_GARBAGE_COLLECTED_MIXIN(NavigatorBrave);
+
+ public:
+ static const char kSupplementName[];
+
+ static NavigatorBrave& From(Navigator&);
+ static Brave* brave(Navigator&);
+ Brave* brave();
+
+ explicit NavigatorBrave(Navigator&);
+
+ void Trace(blink::Visitor*) override;
+ const char* NameInHeapSnapshot() const override {
+ return "NavigatorBrave";
+ }
+
+ private:
+ Member brave_;
+};
+
+} // namespace blink
+
+#endif // BRAVE_THIRD_PARTY_BLINK_RENDERER_MODULES_BRAVE_NAVIGATOR_BRAVE_H_
diff --git a/third_party/blink/renderer/modules/brave/navigator_brave.idl b/third_party/blink/renderer/modules/brave/navigator_brave.idl
new file mode 100644
index 000000000000..4a6218dac1a6
--- /dev/null
+++ b/third_party/blink/renderer/modules/brave/navigator_brave.idl
@@ -0,0 +1,9 @@
+/* Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/. */
+[
+ ImplementedAs=NavigatorBrave
+] partial interface Navigator {
+ readonly attribute Brave brave;
+};
diff --git a/third_party/blink/renderer/modules/brave/navigator_browsertest.cc b/third_party/blink/renderer/modules/brave/navigator_browsertest.cc
new file mode 100644
index 000000000000..ca882832a8b4
--- /dev/null
+++ b/third_party/blink/renderer/modules/brave/navigator_browsertest.cc
@@ -0,0 +1,41 @@
+// Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/.
+
+#include "base/path_service.h"
+#include "brave/common/brave_paths.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/test/browser_test_utils.h"
+
+namespace {
+
+const char kDetectBraveTest[] = "/detect_brave.html";
+
+} // namespace
+
+class NavigatorGetBraveDetectedTest : public InProcessBrowserTest {
+ public:
+ void SetUpOnMainThread() override {
+ InProcessBrowserTest::SetUpOnMainThread();
+
+ content::SetupCrossSiteRedirector(embedded_test_server());
+
+ brave::RegisterPathProvider();
+ base::FilePath test_data_dir;
+ base::PathService::Get(brave::DIR_TEST_DATA, &test_data_dir);
+ embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(NavigatorGetBraveDetectedTest, IsDetected) {
+ GURL url = embedded_test_server()->GetURL(kDetectBraveTest);
+ ui_test_utils::NavigateToURL(browser(), url);
+ content::WebContents* contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ EXPECT_EQ(true, EvalJs(contents, "getBraveDetected()"));
+}