diff --git a/app/brave_generated_resources.grd b/app/brave_generated_resources.grd index cc9eb8a08eb7..491351b46a5d 100644 --- a/app/brave_generated_resources.grd +++ b/app/brave_generated_resources.grd @@ -764,6 +764,15 @@ By installing this extension, you are agreeing to the Google Widevine Terms of U View in Web Extensions Store + + Warning: Brave cannot prevent extensions from recording your browsing history. + + + If this extension makes network requests, they will not use Tor or private mode. + + + To disable this extension in private mode and Tor mode, unselect this option. + On exit diff --git a/browser/resources/extensions/BUILD.gn b/browser/resources/extensions/BUILD.gn index 006c092c042f..ac1968df8b27 100644 --- a/browser/resources/extensions/BUILD.gn +++ b/browser/resources/extensions/BUILD.gn @@ -6,6 +6,7 @@ import("//tools/polymer/polymer.gni") import("//ui/webui/resources/tools/generate_grd.gni") preprocess_folder = "preprocessed" +preprocess_manifest = "brave_preprocessed_manifest.json" preprocess_gen_manifest = "brave_preprocessed_gen_manifest.json" grit("resources") { @@ -19,8 +20,8 @@ grit("resources") { defines = chrome_grit_defines enable_input_discovery_for_gn_analyze = false - defines += [ "SHARED_INTERMEDIATE_DIR=" + - rebase_path(root_gen_dir, root_build_dir) ] + defines += + [ "SHARED_INTERMEDIATE_DIR=" + rebase_path(root_gen_dir, root_build_dir) ] extensions_gen_dir = "$root_gen_dir/brave/browser/resources/extensions" source = "$extensions_gen_dir/brave_extensions_resources.grd" deps = [ ":build_grd" ] @@ -42,14 +43,33 @@ generate_grd("build_grd") { input_files = [] input_files_base_dir = rebase_path(".", "//") - deps = [ ":preprocess_generated" ] - manifest_files = [ "$root_gen_dir/chrome/browser/resources/extensions/$preprocess_gen_manifest" ] + deps = [ + ":preprocess", + ":preprocess_generated", + ] + manifest_files = [ + "$root_gen_dir/chrome/browser/resources/extensions/$preprocess_manifest", + "$root_gen_dir/chrome/browser/resources/extensions/$preprocess_gen_manifest", + ] +} + +preprocess_grit("preprocess") { + in_folder = "./" + out_folder = + "$root_gen_dir/chrome/browser/resources/extensions/$preprocess_folder" + out_manifest = + "$root_gen_dir/chrome/browser/resources/extensions/$preprocess_manifest" + in_files = [ + "brave_overrides/extensions_detail_view.js", + "brave_overrides/index.js", + ] } preprocess_grit("preprocess_generated") { deps = [ ":brave_item_list_more_items_module" ] in_folder = target_gen_dir - out_folder = "$root_gen_dir/chrome/browser/resources/extensions/$preprocess_folder" + out_folder = + "$root_gen_dir/chrome/browser/resources/extensions/$preprocess_folder" out_manifest = "$root_gen_dir/chrome/browser/resources/extensions/$preprocess_gen_manifest" in_files = [ "brave_item_list_more_items.js" ] } diff --git a/browser/resources/extensions/brave_overrides/extensions_detail_view.js b/browser/resources/extensions/brave_overrides/extensions_detail_view.js new file mode 100644 index 000000000000..c02d32c20394 --- /dev/null +++ b/browser/resources/extensions/brave_overrides/extensions_detail_view.js @@ -0,0 +1,39 @@ +// 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/. + +import {RegisterPolymerTemplateModifications, RegisterPolymerComponentBehaviors} from 'chrome://brave-resources/polymer_overriding.js' +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js' + +RegisterPolymerTemplateModifications({ + 'extensions-detail-view': (templateContent) => { + let optionsTemplate = + templateContent.querySelector('template[is="dom-if"][if*="shouldShowOptionsSection_"]') + if (!optionsTemplate) { + console.error('[Brave Extensions Overrides] Could not find optionsTemplate') + return + } + let incognitoTemplate = + optionsTemplate.content.querySelector('template[is="dom-if"][if*="shouldShowIncognitoOption_"]') + if (!incognitoTemplate) { + console.error('[Brave Extensions Overrides] Could not find incognitoTemplate') + return + } + let incognitoWarningDiv = incognitoTemplate.content.querySelector('.section-content') + if (!incognitoWarningDiv) { + console.error('[Brave Extensions Overrides] Could not find incognitoWarningDiv') + return + } + incognitoWarningDiv.innerText = I18nBehavior.i18n('privateInfoWarning') + const spanningWarningSpan = document.createElement('span') + spanningWarningSpan.setAttribute('class', 'section-content') + spanningWarningSpan.setAttribute('hidden', '[[data.isSplitMode]]') + spanningWarningSpan.innerText = ' ' + I18nBehavior.i18n('spanningInfoWarning') + const privateAndTorWarningSpan = document.createElement('span') + privateAndTorWarningSpan.setAttribute('class', 'section-content') + privateAndTorWarningSpan.innerText = ' ' + I18nBehavior.i18n('privateAndTorInfoWarning') + incognitoWarningDiv.appendChild(spanningWarningSpan) + incognitoWarningDiv.appendChild(privateAndTorWarningSpan) + } +}) diff --git a/browser/resources/extensions/brave_overrides/index.js b/browser/resources/extensions/brave_overrides/index.js new file mode 100644 index 000000000000..27d7d6cacc2e --- /dev/null +++ b/browser/resources/extensions/brave_overrides/index.js @@ -0,0 +1,6 @@ +// 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/. + +import './extensions_detail_view.js' diff --git a/browser/tor/tor_profile_manager_browsertest.cc b/browser/tor/tor_profile_manager_browsertest.cc index 65558f0bd5dd..b4c0c596c504 100644 --- a/browser/tor/tor_profile_manager_browsertest.cc +++ b/browser/tor/tor_profile_manager_browsertest.cc @@ -31,6 +31,7 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) #include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/extensions/extension_service.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_util.h" @@ -258,35 +259,35 @@ class TorProfileManagerExtensionTest : public extensions::ExtensionBrowserTest { // Override extension data dir. brave::RegisterPathProvider(); base::PathService::Get(brave::DIR_TEST_DATA, &test_data_dir_); + extension_path_ = test_data_dir_.AppendASCII("extensions") + .AppendASCII("trivial_extension"); + incognito_not_allowed_ext_path_ = + test_data_dir_.AppendASCII("extensions") + .AppendASCII("trivial_extension_incognito_not_allowed"); } - const extensions::Extension* GetExtension(Profile* profile) { - extensions::ExtensionRegistry* registry = - extensions::ExtensionRegistry::Get(profile); - for (const scoped_refptr& extension : - registry->enabled_extensions()) { - if (extension->name() == "Trivial Test Extension") - return extension.get(); - } - NOTREACHED(); - return NULL; + base::FilePath extension_path() const { return extension_path_; } + base::FilePath incognito_not_allowed_ext_path() const { + return incognito_not_allowed_ext_path_; } TorLauncherFactory* GetTorLauncherFactory() { return &MockTorLauncherFactory::GetInstance(); } + + private: + base::FilePath extension_path_; + base::FilePath incognito_not_allowed_ext_path_; }; IN_PROC_BROWSER_TEST_F(TorProfileManagerExtensionTest, - SwitchToTorProfileDisableExtensions) { - ProfileManager* profile_manager = g_browser_process->profile_manager(); - ASSERT_TRUE(profile_manager); + SwitchToTorProfileIncognitoEnabled) { Profile* parent_profile = ProfileManager::GetActiveUserProfile(); ASSERT_TRUE(parent_profile); // Install an extension in parent profile and enable in incognito. const extensions::Extension* extension = - InstallExtension(test_data_dir_.AppendASCII("trivial_extension"), 1); + InstallExtension(extension_path(), 1); const std::string id = extension->id(); extensions::ExtensionPrefs* parent_extension_prefs = extensions::ExtensionPrefs::Get(parent_profile); @@ -298,8 +299,8 @@ IN_PROC_BROWSER_TEST_F(TorProfileManagerExtensionTest, EXPECT_TRUE(tor_profile->IsOffTheRecord()); EXPECT_EQ(tor_profile->GetOriginalProfile(), parent_profile); - // The installed extension should not be accessible in Tor. - EXPECT_FALSE(extensions::util::IsIncognitoEnabled(id, tor_profile)); + // The installed extension should be accessible in Tor. + EXPECT_TRUE(extensions::util::IsIncognitoEnabled(id, tor_profile)); EXPECT_TRUE(extensions::util::IsIncognitoEnabled(id, parent_profile)); // Tor OTR and regular profile shares same registry extensions::ExtensionRegistry* parent_registry = @@ -309,5 +310,27 @@ IN_PROC_BROWSER_TEST_F(TorProfileManagerExtensionTest, EXPECT_EQ(parent_registry, tor_registry); EXPECT_TRUE(tor_registry->GetExtensionById( id, extensions::ExtensionRegistry::EVERYTHING)); + + // Component extension should always be allowed + extension_service()->UnloadExtension( + extension->id(), extensions::UnloadedExtensionReason::UNINSTALL); + const extensions::Extension* component_extension = + LoadExtensionAsComponent(extension_path()); + ASSERT_TRUE(component_extension); + parent_extension_prefs->SetIsIncognitoEnabled(component_extension->id(), + false); + EXPECT_TRUE(extensions::util::IsIncognitoEnabled(component_extension->id(), + tor_profile)); + + // "not_allowed" mode will also disable extension in Tor + const extensions::Extension* incognito_not_allowed_ext = + InstallExtension(incognito_not_allowed_ext_path(), 1); + const std::string incognito_not_allowed_id = incognito_not_allowed_ext->id(); + parent_extension_prefs->SetIsIncognitoEnabled(incognito_not_allowed_id, true); + Profile* primary_otr_profile = parent_profile->GetPrimaryOTRProfile(); + EXPECT_FALSE(extensions::util::IsIncognitoEnabled(incognito_not_allowed_id, + primary_otr_profile)); + EXPECT_FALSE(extensions::util::IsIncognitoEnabled(incognito_not_allowed_id, + tor_profile)); } #endif diff --git a/chromium_src/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chromium_src/chrome/browser/extensions/api/developer_private/extension_info_generator.cc new file mode 100644 index 000000000000..ae34821276b7 --- /dev/null +++ b/chromium_src/chrome/browser/extensions/api/developer_private/extension_info_generator.cc @@ -0,0 +1,11 @@ +/* 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 "extensions/common/manifest_handlers/incognito_info.h" + +#define BRAVE_CREATE_EXTENSION_INFO_HELPER \ + info->is_split_mode = IncognitoInfo::IsSplitMode(&extension); +#include "../../../../../../../chrome/browser/extensions/api/developer_private/extension_info_generator.cc" +#undef BRAVE_CREATE_EXTENSION_INFO_HELPER diff --git a/chromium_src/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chromium_src/chrome/browser/ui/webui/extensions/extensions_ui.cc index 1549b768dfa1..c2cd57633fb9 100644 --- a/chromium_src/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chromium_src/chrome/browser/ui/webui/extensions/extensions_ui.cc @@ -33,6 +33,12 @@ void BraveAddExtensionsResources(content::WebUIDataSource* source) { } #endif NavigationBarDataProvider::Initialize(source); + source->AddLocalizedString("privateInfoWarning", + IDS_EXTENSIONS_BRAVE_PRIVATE_WARNING); + source->AddLocalizedString("spanningInfoWarning", + IDS_EXTENSIONS_BRAVE_SPANNING_WARNING); + source->AddLocalizedString("privateAndTorInfoWarning", + IDS_EXTENSIONS_BRAVE_PRIVATE_AND_TOR_WARNING); } } // namespace diff --git a/chromium_src/extensions/browser/extension_util.cc b/chromium_src/extensions/browser/extension_util.cc deleted file mode 100644 index 424e48c9a861..000000000000 --- a/chromium_src/extensions/browser/extension_util.cc +++ /dev/null @@ -1,13 +0,0 @@ -/* 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/. */ - -// Disable non-component extensions for tor OTR profile -#define BRAVE_IS_INCOGNITO_ENABLED \ - if (context->IsTor() && \ - !Manifest::IsComponentLocation(extension->location())) { \ - return false; \ - } -#include "../../../../extensions/browser/extension_util.cc" -#undef BRAVE_IS_INCOGNITO_ENABLED diff --git a/patches/chrome-browser-extensions-api-developer_private-extension_info_generator.cc.patch b/patches/chrome-browser-extensions-api-developer_private-extension_info_generator.cc.patch new file mode 100644 index 000000000000..6b8522c9a954 --- /dev/null +++ b/patches/chrome-browser-extensions-api-developer_private-extension_info_generator.cc.patch @@ -0,0 +1,12 @@ +diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc +index 1fb464bfae78ce8dc622f0edd5792665ca5af7f1..cd900ccc6f8571ec0f52ca58b14f1fa75d7b2be5 100644 +--- a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc ++++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc +@@ -606,6 +606,7 @@ void ExtensionInfoGenerator::CreateExtensionInfoHelper( + info->incognito_access.is_enabled = util::CanBeIncognitoEnabled(&extension); + info->incognito_access.is_active = + util::IsIncognitoEnabled(extension.id(), browser_context_); ++ BRAVE_CREATE_EXTENSION_INFO_HELPER + + // Install warnings, but only if unpacked, the error console isn't enabled + // (otherwise it shows these), and we're in developer mode (normal users don't diff --git a/patches/chrome-browser-resources-extensions-extensions.js.patch b/patches/chrome-browser-resources-extensions-extensions.js.patch new file mode 100644 index 000000000000..8d59eceb44cf --- /dev/null +++ b/patches/chrome-browser-resources-extensions-extensions.js.patch @@ -0,0 +1,12 @@ +diff --git a/chrome/browser/resources/extensions/extensions.js b/chrome/browser/resources/extensions/extensions.js +index 5836804c9e488bb23869d05881bd55cd7ccd9f52..928974d8d5dc367276527ae521b26fc3bb7cb226 100644 +--- a/chrome/browser/resources/extensions/extensions.js ++++ b/chrome/browser/resources/extensions/extensions.js +@@ -2,6 +2,7 @@ + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. + ++import './brave_overrides/index.js'; + import './manager.js'; + + export {getToastManager} from 'chrome://resources/cr_elements/cr_toast/cr_toast_manager.m.js'; diff --git a/patches/chrome-common-extensions-api-developer_private.idl.patch b/patches/chrome-common-extensions-api-developer_private.idl.patch new file mode 100644 index 000000000000..2169fd086c55 --- /dev/null +++ b/patches/chrome-common-extensions-api-developer_private.idl.patch @@ -0,0 +1,12 @@ +diff --git a/chrome/common/extensions/api/developer_private.idl b/chrome/common/extensions/api/developer_private.idl +index 5b425b0cbb7da4335619acc7743f26050ca472a1..5254b875452702e18c3caaded8841b78cd08c62d 100644 +--- a/chrome/common/extensions/api/developer_private.idl ++++ b/chrome/common/extensions/api/developer_private.idl +@@ -231,6 +231,7 @@ namespace developerPrivate { + DOMString iconUrl; + DOMString id; + AccessModifier incognitoAccess; ++ boolean isSplitMode; + DOMString[] installWarnings; + DOMString? launchUrl; + Location location; diff --git a/patches/extensions-browser-extension_util.cc.patch b/patches/extensions-browser-extension_util.cc.patch deleted file mode 100644 index cb009ec43c07..000000000000 --- a/patches/extensions-browser-extension_util.cc.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/extensions/browser/extension_util.cc b/extensions/browser/extension_util.cc -index af63beaf829691d02a4139adb9eebb0ee941ccb9..d4f914dc323647c8d3c8115c70b2653466e82631 100644 ---- a/extensions/browser/extension_util.cc -+++ b/extensions/browser/extension_util.cc -@@ -53,6 +53,7 @@ bool IsIncognitoEnabled(const std::string& extension_id, - ExtensionRegistry::Get(context)->GetExtensionById( - extension_id, ExtensionRegistry::ENABLED); - if (extension) { -+ BRAVE_IS_INCOGNITO_ENABLED - if (!CanBeIncognitoEnabled(extension)) - return false; - // If this is an existing component extension we always allow it to diff --git a/test/data/extensions/trivial_extension/manifest.json b/test/data/extensions/trivial_extension/manifest.json new file mode 100644 index 000000000000..74a177783e59 --- /dev/null +++ b/test/data/extensions/trivial_extension/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "Trivial Test Extension", + "version": "1.0", + "manifest_version": 2, + "description": "A minimal extension for testing purposes.", + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjzv7dI7Ygyh67VHE1DdidudpYf8PFfv8iucWvzO+3xpF/Dm5xNo7aQhPNiEaNfHwJQ7lsp4gc+C+4bbaVewBFspTruoSJhZc5uEfqxwovJwN+v1/SUFXTXQmQBv6gs0qZB4gBbl4caNQBlqrFwAMNisnu1V6UROna8rOJQ90D7Nv7TCwoVPKBfVshpFjdDOTeBg4iLctO3S/06QYqaTDrwVceSyHkVkvzBY6tc6mnYX0RZu78J9iL8bdqwfllOhs69cqoHHgrLdI6JdOyiuh6pBP6vxMlzSKWJ3YTNjaQTPwfOYaLMuzdl0v+YdzafIzV9zwe4Xiskk+5JNGt8b2rQIDAQAB" +} diff --git a/test/data/extensions/trivial_extension_incognito_not_allowed/manifest.json b/test/data/extensions/trivial_extension_incognito_not_allowed/manifest.json new file mode 100644 index 000000000000..8d091a8c1e72 --- /dev/null +++ b/test/data/extensions/trivial_extension_incognito_not_allowed/manifest.json @@ -0,0 +1,8 @@ +{ + "name": "Trivial Test Extension Not Allow Incognito", + "version": "1.0", + "manifest_version": 2, + "description": "A minimal extension for testing purposes.", + "incognito": "not_allowed", + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjzv7dI7Ygyh67VHE1DdidudpYf8PFfv8iucWvzO+3xpF/Dm5xNo7aQhPNiEaNfHwJQ7lsp4gc+C+4bbaVewBFspTruoSJhZc5uEfqxwovJwN+v1/SUFXTXQmQBv6gs0qZB4gBbl4caNQBlqrFwAMNisnu1V6UROna8rOJQ90D7Nv7TCwoVPKBfVshpFjdDOTeBg4iLctO3S/06QYqaTDrwVceSyHkVkvzBY6tc6mnYX0RZu78J9iL8bdqwfllOhs69cqoHHgrLdI6JdOyiuh6pBP6vxMlzSKWJ3YTNjaQTPwfOYaLMuzdl0v+YdzafIzV9zwe4Xiskk+5JNGt8b2rQIDAQAB" +} diff --git a/test/data/trivial_extension/manifest.json b/test/data/trivial_extension/manifest.json deleted file mode 100644 index 5cac7064e794..000000000000 --- a/test/data/trivial_extension/manifest.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Trivial Test Extension", - "version": "1.0", - "manifest_version": 2, - "description": "A minimal extension for testing purposes." -}