Merge pull request #24620 from brave/sko/file-chooser

Show site origin in file select dialog
This commit is contained in:
Sangwoo Ko
2024-07-19 21:58:56 +09:00
committed by GitHub
10 changed files with 708 additions and 1 deletions
+26
View File
@@ -1299,6 +1299,32 @@ Or change later at <ph name="SETTINGS_EXTENIONS_LINK">$2<ex>brave://settings/ext
Brave Player
</message>
</if> <!-- enable_brave_player -->
<!-- File select -->
<message name="IDS_BRAVE_FILE_SELECT_OPEN_TITLE" desc="">
<ph name="SITE">$1<ex>http://foo.com</ex></ph> wants to open
</message>
<message name="IDS_BRAVE_FILE_SELECT_OPEN_TITLE_IFRAME" desc="">
An embedded page on <ph name="SITE">$1<ex>http://foo.com</ex></ph> wants to open
</message>
<message name="IDS_BRAVE_FILE_SELECT_OPEN_TITLE_NONSTANDARD_URL" desc="">
This page wants to open
</message>
<message name="IDS_BRAVE_FILE_SELECT_OPEN_TITLE_NONSTANDARD_URL_IFRAME" desc="">
An embedded page on this page wants to open
</message>
<message name="IDS_BRAVE_FILE_SELECT_SAVE_TITLE" desc="">
<ph name="SITE">$1<ex>http://foo.com</ex></ph> wants to save
</message>
<message name="IDS_BRAVE_FILE_SELECT_SAVE_TITLE_IFRAME" desc="">
An embedded page on <ph name="SITE">$1<ex>http://foo.com</ex></ph> wants to save
</message>
<message name="IDS_BRAVE_FILE_SELECT_SAVE_TITLE_NONSTANDARD_URL" desc="">
This page wants to save
</message>
<message name="IDS_BRAVE_FILE_SELECT_SAVE_TITLE_NONSTANDARD_URL_IFRAME" desc="">
An embedded page on this page wants to save
</message>
<!--Add new items to the appropriate sections above -->
</messages>
</release>
+8 -1
View File
@@ -150,6 +150,8 @@ source_set("ui") {
"brave_browser_content_setting_bubble_model_delegate.h",
"brave_browser_window.cc",
"brave_browser_window.h",
"brave_file_select_utils.cc",
"brave_file_select_utils.h",
"brave_icon_with_badge_image_source.cc",
"brave_icon_with_badge_image_source.h",
"brave_layout_constants.cc",
@@ -1335,9 +1337,14 @@ source_set("ui") {
source_set("unit_tests") {
if (!is_android) {
testonly = true
sources = [ "brave_layout_constants_unittest.cc" ]
sources = [
"brave_file_select_utils_unittest.cc",
"brave_layout_constants_unittest.cc",
]
deps = [
"//brave/components/l10n/common:test_support",
"//chrome/browser/ui",
"//components/javascript_dialogs",
"//testing/gtest",
"//ui/base:test_support",
"//ui/gfx",
+30
View File
@@ -14,6 +14,7 @@
#include "base/functional/callback_helpers.h"
#include "brave/browser/brave_browser_features.h"
#include "brave/browser/ui/brave_browser_window.h"
#include "brave/browser/ui/brave_file_select_utils.h"
#include "brave/browser/ui/tabs/brave_tab_prefs.h"
#include "brave/browser/ui/tabs/features.h"
#include "brave/components/constants/pref_names.h"
@@ -27,7 +28,9 @@
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "chrome/common/webui_url_constants.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/common/url_constants.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "url/gurl.h"
#if defined(TOOLKIT_VIEWS)
@@ -128,6 +131,33 @@ void BraveBrowser::TabStripEmpty() {
true, std::nullopt));
}
void BraveBrowser::RunFileChooser(
content::RenderFrameHost* render_frame_host,
scoped_refptr<content::FileSelectListener> listener,
const blink::mojom::FileChooserParams& params) {
#if BUILDFLAG(IS_ANDROID)
Browser::RunFileChooser(render_frame_host, listener, params);
#else
auto new_params = params.Clone();
if (new_params->title.empty()) {
// Fill title of file chooser with origin of the frame.
// Note that save mode param is for PPAPI. 'Save As...' or downloading
// something doesn't reach here. They show 'select file dialog' from
// DownloadFilePicker::DownloadFilePicker directly.
// https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/choosers/file_chooser.mojom;l=27;drc=047c7dc4ee1ce908d7fea38ca063fa2f80f92c77
new_params->title = brave::GetFileSelectTitle(
content::WebContents::FromRenderFrameHost(render_frame_host),
render_frame_host->GetLastCommittedOrigin(),
params.mode == blink::mojom::FileChooserParams::Mode::kSave
? brave::FileSelectTitleType::kSave
: brave::FileSelectTitleType::kOpen);
}
Browser::RunFileChooser(render_frame_host, listener, *new_params);
#endif
}
bool BraveBrowser::ShouldDisplayFavicon(
content::WebContents* web_contents) const {
// Override to not show favicon for NTP in tab.
+4
View File
@@ -54,6 +54,10 @@ class BraveBrowser : public Browser {
void OnTabClosing(content::WebContents* contents) override;
void TabStripEmpty() override;
void RunFileChooser(content::RenderFrameHost* render_frame_host,
scoped_refptr<content::FileSelectListener> listener,
const blink::mojom::FileChooserParams& params) override;
// Returns true when we should ask browser closing to users before handling
// any warning/onbeforeunload handlers.
bool ShouldAskForBrowserClosingBeforeHandlers();
+151
View File
@@ -0,0 +1,151 @@
/* Copyright (c) 2024 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/browser/ui/brave_file_select_utils.h"
#include <unordered_map>
#include "base/i18n/rtl.h"
#include "base/no_destructor.h"
#include "brave/grit/brave_generated_resources.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/url_identity.h"
#include "components/strings/grit/components_strings.h"
#include "components/url_formatter/elide_url.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace brave {
namespace {
// If an origin is opaque but has a precursor, then returns the precursor
// origin. If the origin is not opaque, returns it unchanged. Unwrapping origins
// allows the dialog code to provide the user with a clearer picture of which
// page is actually showing the dialog.
url::Origin UnwrapOriginIfOpaque(const url::Origin& origin) {
if (!origin.opaque()) {
return origin;
}
const url::SchemeHostPort& precursor =
origin.GetTupleOrPrecursorTupleIfOpaque();
if (!precursor.IsValid()) {
return origin;
}
return url::Origin::CreateFromNormalizedTuple(
precursor.scheme(), precursor.host(), precursor.port());
}
} // namespace
std::u16string GetFileSelectTitle(content::WebContents* web_contents,
const url::Origin& alerting_frame_origin,
FileSelectTitleType file_select_type) {
// This implementation partially mirrors
// ChromeAppModalDialogManagerDelegate::GetTitle().
// TODO(sko) It's hard to test this behavior is in sync at this moment. Even
// upstream tests aren't covering this. Need to figure out how we can test
// extension and isolated web app case.
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
UrlIdentity url_identity = UrlIdentity::CreateFromUrl(
profile, alerting_frame_origin.GetURL(),
/*allowed_types*/
{UrlIdentity::Type::kDefault, UrlIdentity::Type::kFile,
UrlIdentity::Type::kIsolatedWebApp, UrlIdentity::Type::kChromeExtension},
/*default_options*/ {.default_options = {}});
if (url_identity.type == UrlIdentity::Type::kChromeExtension) {
return url_identity.name;
}
if (url_identity.type == UrlIdentity::Type::kIsolatedWebApp) {
return url_identity.name;
}
const auto main_frame_origin =
web_contents->GetPrimaryMainFrame()->GetLastCommittedOrigin();
return GetSiteFrameTitleForFileSelect(
GetSiteFrameTitleType(main_frame_origin, alerting_frame_origin),
alerting_frame_origin, file_select_type);
}
std::u16string GetSiteFrameTitleForFileSelect(
SiteFrameTitleType frame_type,
const url::Origin& alerting_frame_origin,
FileSelectTitleType file_select_type) {
constexpr std::array<
std::array<int, static_cast<size_t>(SiteFrameTitleType::kSize)>,
static_cast<size_t>(FileSelectTitleType::kSize)>
kResourceIDs = {
{/*FileSelectTitleType::kOpen,*/
{
IDS_BRAVE_FILE_SELECT_OPEN_TITLE, // brave::SiteFrameTitleType::kStandardSameOrigin
IDS_BRAVE_FILE_SELECT_OPEN_TITLE_IFRAME, // brave::SiteFrameTitleType::kStandardDifferentOrigin
IDS_BRAVE_FILE_SELECT_OPEN_TITLE_NONSTANDARD_URL, // brave::SiteFrameTitleType::kNonStandardSameOrigin
IDS_BRAVE_FILE_SELECT_OPEN_TITLE_NONSTANDARD_URL_IFRAME // brave::SiteFrameTitleType::kNonStandardDifferentOrigin
},
/*FileSelectTitleType::kSave,*/
{
IDS_BRAVE_FILE_SELECT_SAVE_TITLE, // brave::SiteFrameTitleType::kStandardSameOrigin
IDS_BRAVE_FILE_SELECT_SAVE_TITLE_IFRAME, // brave::SiteFrameTitleType::kStandardDifferentOrigin
IDS_BRAVE_FILE_SELECT_SAVE_TITLE_NONSTANDARD_URL, // brave::SiteFrameTitleType::kNonStandardSameOrigin
IDS_BRAVE_FILE_SELECT_SAVE_TITLE_NONSTANDARD_URL_IFRAME // brave::SiteFrameTitleType::kNonStandardDifferentOrigin
},
/*FileSelectTitleType::kChromiumDefault*/
{
IDS_JAVASCRIPT_MESSAGEBOX_TITLE, // brave::SiteFrameTitleType::kStandardSameOrigin
IDS_JAVASCRIPT_MESSAGEBOX_TITLE_IFRAME, // brave::SiteFrameTitleType::kStandardDifferentOrigin,
IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL, // brave::SiteFrameTitleType::kNonStandardSameOrigin
IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL_IFRAME, // brave::SiteFrameTitleType::kNonStandardDifferentOrigin,
}}};
if (frame_type == SiteFrameTitleType::kStandardSameOrigin ||
frame_type == SiteFrameTitleType::kStandardDifferentOrigin) {
std::u16string origin_string =
url_formatter::FormatOriginForSecurityDisplay(
UnwrapOriginIfOpaque(alerting_frame_origin),
url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
return l10n_util::GetStringFUTF16(
kResourceIDs[static_cast<size_t>(file_select_type)]
[static_cast<size_t>(frame_type)],
base::i18n::GetDisplayStringInLTRDirectionality(origin_string));
}
return l10n_util::GetStringUTF16(kResourceIDs[static_cast<size_t>(
file_select_type)][static_cast<size_t>(frame_type)]);
}
SiteFrameTitleType GetSiteFrameTitleType(
const url::Origin& main_frame_origin,
const url::Origin& alerting_frame_origin) {
// This implementation mirrors `AppModalDialogManager::GetSiteFrameTitle()`.
// We have a test to check if the two implementations are in sync.
// - BraveFileSelectHelperUnitTest.GetSiteFrameTitleType_InSyncWithUpstream.
const url::Origin unwrapped_main_frame_origin =
UnwrapOriginIfOpaque(main_frame_origin);
const url::Origin unwrapped_alerting_frame_origin =
UnwrapOriginIfOpaque(alerting_frame_origin);
const bool is_same_origin_as_main_frame =
unwrapped_alerting_frame_origin.IsSameOriginWith(
unwrapped_main_frame_origin);
if (unwrapped_alerting_frame_origin.GetURL().IsStandard() &&
!unwrapped_alerting_frame_origin.GetURL().SchemeIsFile()) {
return is_same_origin_as_main_frame
? SiteFrameTitleType::kStandardSameOrigin
: SiteFrameTitleType::kStandardDifferentOrigin;
}
return is_same_origin_as_main_frame
? SiteFrameTitleType::kNonStandardSameOrigin
: SiteFrameTitleType::kNonStandardDifferentOrigin;
}
} // namespace brave
+63
View File
@@ -0,0 +1,63 @@
/* Copyright (c) 2024 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_BROWSER_UI_BRAVE_FILE_SELECT_UTILS_H_
#define BRAVE_BROWSER_UI_BRAVE_FILE_SELECT_UTILS_H_
#include <string>
#include "base/containers/flat_map.h"
namespace content {
class WebContents;
} // namespace content
namespace url {
class Origin;
} // namespace url
namespace brave {
// This enum values are used to determine the title of the file select dialog.
// Basically it mirrors std::u16string
// AppModalDialogManager::GetSiteFrameTitle() implementation.
enum class SiteFrameTitleType {
kStandardSameOrigin, // alerting frame has http(s) scheme and has the same
// origin with main frame
kStandardDifferentOrigin, // alerting frame http(s) scheme and has a
// different origin with main frame
kNonStandardSameOrigin, // alerting frame has other schemes (e.g. file,
// data, javascript) and has the same origin with
// main frame
kNonStandardDifferentOrigin, // alerting frame has other schemes (e.g. file,
// data, javascript) and has a different origin
// with main frame
kSize
};
enum class FileSelectTitleType {
kOpen,
kSave,
kChromiumDefault, // used for comparing with the default title of the file
// select dialog in Chromium
kSize
};
std::u16string GetFileSelectTitle(content::WebContents* contents,
const url::Origin& alerting_frame_origin,
FileSelectTitleType file_select_type);
std::u16string GetSiteFrameTitleForFileSelect(
SiteFrameTitleType frame_type,
const url::Origin& alerting_frame_origin,
FileSelectTitleType select_type);
SiteFrameTitleType GetSiteFrameTitleType(
const url::Origin& main_frame_origin,
const url::Origin& alerting_frame_origin);
} // namespace brave
#endif // BRAVE_BROWSER_UI_BRAVE_FILE_SELECT_UTILS_H_
@@ -0,0 +1,309 @@
/* Copyright (c) 2024 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/browser/ui/brave_file_select_utils.h"
#include "base/strings/utf_string_conversions.h"
#include "brave/components/l10n/common/test/scoped_default_locale.h"
#include "components/javascript_dialogs/app_modal_dialog_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
TEST(BraveFileSelectUtilsUnitTest, GetSiteFrameTitle_InSyncWithUpstream) {
constexpr struct Case {
// The name of the test case.
const char* case_name;
// The URL of the main frame of the page.
const char* main_frame_url;
// Whether the main frame is alerting.
bool is_main_frame;
// If `is_main_frame` is false, the URL of the alerting frame of the page.
const char* alerting_frame_url;
} kCases[] = {
// Standard main frame alert.
{"standard", "http://foo.com/", true, ""},
// Subframe alert from the same origin.
{"subframe same origin", "http://foo.com/1", false, "http://foo.com/2"},
// Subframe alert from a different origin.
{"subframe different origin", "http://foo.com/", false,
"http://bar.com/"},
// file:
// - main frame:
{"file main frame", "file:///path/to/page.html", true, ""},
// - subframe:
{"file subframe", "http://foo.com/", false, "file:///path/to/page.html"},
// data:
// /!\ NOTE that this is for data URLs entered directly in the omnibox.
// For pages that generate frames with data URLs, see the browsertest.
// - main frame:
{"data main frame", "data:blahblah", true, ""},
// - subframe:
{"data subframe", "http://foo.com/", false, "data:blahblah"},
// javascript:
// /!\ NOTE that this is for javascript URLs entered directly in the
// omnibox. For pages that generate frames with javascript URLs, see the
// browsertest.
// - main frame:
{"javascript main frame", "javascript:abc", true, ""},
// - subframe:
{"javascript subframe", "http://foo.com/", false, "javascript:abc"},
// about:
// /!\ NOTE that this is for about:blank URLs entered directly in the
// omnibox. For pages that generate frames with about:blank URLs, see the
// browsertest.
// - main frame:
{"about main frame", "about:blank", true, ""},
// - subframe:
{"about subframe", "http://foo.com/", false, "about:blank"},
// blob:
// - main frame:
{"blob main frame",
"blob:http://foo.com/66666666-6666-6666-6666-666666666666", true, ""},
// - subframe:
{"blob subframe", "http://bar.com/", false,
"blob:http://foo.com/66666666-6666-6666-6666-666666666666"},
// filesystem:
// - main frame:
{"filesystem main frame", "filesystem:http://foo.com/bar.html", true, ""},
// - subframe:
{"filesystem subframe", "http://bar.com/", false,
"filesystem:http://foo.com/bar.html"},
};
// Checks if our implementation is in sync with upstream.
for (const auto& test_case : kCases) {
SCOPED_TRACE(test_case.case_name);
url::Origin main_frame_origin =
url::Origin::Create(GURL(test_case.main_frame_url));
url::Origin alerting_frame_origin =
test_case.is_main_frame
? main_frame_origin
: url::Origin::Create(GURL(test_case.alerting_frame_url));
EXPECT_EQ(javascript_dialogs::AppModalDialogManager::GetSiteFrameTitle(
main_frame_origin, alerting_frame_origin),
brave::GetSiteFrameTitleForFileSelect(
brave::GetSiteFrameTitleType(main_frame_origin,
alerting_frame_origin),
alerting_frame_origin,
brave::FileSelectTitleType::kChromiumDefault));
}
}
TEST(BraveFileSelectUtilsUnitTest, GetSiteFrameTitleForFileSelect_Open) {
constexpr struct Case {
// The name of the test case.
const char* case_name;
// The URL of the main frame of the page.
const char* main_frame_url;
// Whether the main frame is alerting.
bool is_main_frame;
// If `is_main_frame` is false, the URL of the alerting frame of the page.
const char* alerting_frame_url;
// The expected title for the alert.
const char* expected;
} kCases[] = {
// Standard main frame alert.
{"standard", "http://foo.com/", true, "", "foo.com wants to open"},
// Subframe alert from the same origin.
{"subframe same origin", "http://foo.com/1", false, "http://foo.com/2",
"foo.com wants to open"},
// Subframe alert from a different origin.
{"subframe different origin", "http://foo.com/", false, "http://bar.com/",
"An embedded page on bar.com wants to open"},
// file:
// - main frame:
{"file main frame", "file:///path/to/page.html", true, "",
"This page wants to open"},
// - subframe:
{"file subframe", "http://foo.com/", false, "file:///path/to/page.html",
"An embedded page on this page wants to open"},
// data:
// /!\ NOTE that this is for data URLs entered directly in the omnibox.
// For pages that generate frames with data URLs, see the browsertest.
// - main frame:
{"data main frame", "data:blahblah", true, "", "This page wants to open"},
// - subframe:
{"data subframe", "http://foo.com/", false, "data:blahblah",
"An embedded page on this page wants to open"},
// javascript:
// /!\ NOTE that this is for javascript URLs entered directly in the
// omnibox. For pages that generate frames with javascript URLs, see the
// browsertest.
// - main frame:
{"javascript main frame", "javascript:abc", true, "",
"This page wants to open"},
// - subframe:
{"javascript subframe", "http://foo.com/", false, "javascript:abc",
"An embedded page on this page wants to open"},
// about:
// /!\ NOTE that this is for about:blank URLs entered directly in the
// omnibox. For pages that generate frames with about:blank URLs, see the
// browsertest.
// - main frame:
{"about main frame", "about:blank", true, "", "This page wants to open"},
// - subframe:
{"about subframe", "http://foo.com/", false, "about:blank",
"An embedded page on this page wants to open"},
// blob:
// - main frame:
{"blob main frame",
"blob:http://foo.com/66666666-6666-6666-6666-666666666666", true, "",
"foo.com wants to open"},
// - subframe:
{"blob subframe", "http://bar.com/", false,
"blob:http://foo.com/66666666-6666-6666-6666-666666666666",
"An embedded page on foo.com wants to open"},
// filesystem:
// - main frame:
{"filesystem main frame", "filesystem:http://foo.com/bar.html", true, "",
"foo.com wants to open"},
// - subframe:
{"filesystem subframe", "http://bar.com/", false,
"filesystem:http://foo.com/bar.html",
"An embedded page on foo.com wants to open"},
};
brave_l10n::test::ScopedDefaultLocale scoped_locale("en-US");
for (const auto& test_case : kCases) {
SCOPED_TRACE(test_case.case_name);
url::Origin main_frame_origin =
url::Origin::Create(GURL(test_case.main_frame_url));
url::Origin alerting_frame_origin =
test_case.is_main_frame
? main_frame_origin
: url::Origin::Create(GURL(test_case.alerting_frame_url));
EXPECT_EQ(base::UTF8ToUTF16(test_case.expected),
brave::GetSiteFrameTitleForFileSelect(
brave::GetSiteFrameTitleType(main_frame_origin,
alerting_frame_origin),
alerting_frame_origin, brave::FileSelectTitleType::kOpen));
}
}
TEST(BraveFileSelectUtilsUnitTest, GetSiteFrameTitleForFileSelect_Save) {
constexpr struct Case {
// The name of the test case.
const char* case_name;
// The URL of the main frame of the page.
const char* main_frame_url;
// Whether the main frame is alerting.
bool is_main_frame;
// If `is_main_frame` is false, the URL of the alerting frame of the page.
const char* alerting_frame_url;
// The expected title for the alert.
const char* expected;
} kCases[] = {
// Standard main frame alert.
{"standard", "http://foo.com/", true, "", "foo.com wants to save"},
// Subframe alert from the same origin.
{"subframe same origin", "http://foo.com/1", false, "http://foo.com/2",
"foo.com wants to save"},
// Subframe alert from a different origin.
{"subframe different origin", "http://foo.com/", false, "http://bar.com/",
"An embedded page on bar.com wants to save"},
// file:
// - main frame:
{"file main frame", "file:///path/to/page.html", true, "",
"This page wants to save"},
// - subframe:
{"file subframe", "http://foo.com/", false, "file:///path/to/page.html",
"An embedded page on this page wants to save"},
// data:
// /!\ NOTE that this is for data URLs entered directly in the omnibox.
// For pages that generate frames with data URLs, see the browsertest.
// - main frame:
{"data main frame", "data:blahblah", true, "", "This page wants to save"},
// - subframe:
{"data subframe", "http://foo.com/", false, "data:blahblah",
"An embedded page on this page wants to save"},
// javascript:
// /!\ NOTE that this is for javascript URLs entered directly in the
// omnibox. For pages that generate frames with javascript URLs, see the
// browsertest.
// - main frame:
{"javascript main frame", "javascript:abc", true, "",
"This page wants to save"},
// - subframe:
{"javascript subframe", "http://foo.com/", false, "javascript:abc",
"An embedded page on this page wants to save"},
// about:
// /!\ NOTE that this is for about:blank URLs entered directly in the
// omnibox. For pages that generate frames with about:blank URLs, see the
// browsertest.
// - main frame:
{"about main frame", "about:blank", true, "", "This page wants to save"},
// - subframe:
{"about subframe", "http://foo.com/", false, "about:blank",
"An embedded page on this page wants to save"},
// blob:
// - main frame:
{"blob main frame",
"blob:http://foo.com/66666666-6666-6666-6666-666666666666", true, "",
"foo.com wants to save"},
// - subframe:
{"blob subframe", "http://bar.com/", false,
"blob:http://foo.com/66666666-6666-6666-6666-666666666666",
"An embedded page on foo.com wants to save"},
// filesystem:
// - main frame:
{"filesystem main frame", "filesystem:http://foo.com/bar.html", true, "",
"foo.com wants to save"},
// - subframe:
{"filesystem subframe", "http://bar.com/", false,
"filesystem:http://foo.com/bar.html",
"An embedded page on foo.com wants to save"},
};
brave_l10n::test::ScopedDefaultLocale scoped_locale("en-US");
for (const auto& test_case : kCases) {
SCOPED_TRACE(test_case.case_name);
url::Origin main_frame_origin =
url::Origin::Create(GURL(test_case.main_frame_url));
url::Origin alerting_frame_origin =
test_case.is_main_frame
? main_frame_origin
: url::Origin::Create(GURL(test_case.alerting_frame_url));
EXPECT_EQ(base::UTF8ToUTF16(test_case.expected),
brave::GetSiteFrameTitleForFileSelect(
brave::GetSiteFrameTitleType(main_frame_origin,
alerting_frame_origin),
alerting_frame_origin, brave::FileSelectTitleType::kSave));
}
}
@@ -0,0 +1,42 @@
/* Copyright (c) 2024 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 <string>
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#if !BUILDFLAG(IS_ANDROID)
#include "brave/browser/ui/brave_file_select_utils.h"
#endif
namespace {
std::u16string GetTitle(content::RenderFrameHost* render_frame_host,
const std::u16string& original_title) {
#if BUILDFLAG(IS_ANDROID)
return original_title;
#else
return brave::GetFileSelectTitle(
content::WebContents::FromRenderFrameHost(render_frame_host),
render_frame_host->GetLastCommittedOrigin(),
brave::FileSelectTitleType::kSave);
#endif
}
} // namespace
// Override title of the file select dialog for downloads.
#define SelectFile(type, title, default_path, file_types, file_type_index, \
default_extension, owning_window, params, caller) \
SelectFile(type, GetTitle(render_frame_host, title), default_path, \
file_types, file_type_index, default_extension, owning_window, \
params, caller)
#include "src/chrome/browser/download/download_file_picker.cc"
#undef SelectFile
@@ -0,0 +1,31 @@
/* Copyright (c) 2024 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/. */
// Can be removed once
// https://chromium-review.googlesource.com/c/chromium/src/+/5711152 arrives in
// Brave.
#define BRAVE_EXECUTE_SELECT_SINGLE_FILE \
return RunOpenFileDialog(owner, title, std::u16string(), default_path, \
filter, 0, filter_index, paths);
// Can be removed once
// https://chromium-review.googlesource.com/c/chromium/src/+/5711152 arrives in
// Brave.
#define BRAVE_EXECUTE_SELECT_MULTIPLE_FILE \
return RunOpenFileDialog(owner, title, std::u16string(), default_path, \
filter, dialog_options, filter_index, paths);
// Can be removed once
// https://chromium-review.googlesource.com/c/chromium/src/+/5711152 arrives in
// Brave.
#define BRAVE_EXECUTE_SAVE_FILE \
return RunSaveFileDialog(owner, title, default_path, filter, dialog_options, \
def_ext, filter_index, path);
#include "src/ui/shell_dialogs/execute_select_file_win.cc"
#undef BRAVE_EXECUTE_SAVE_FILE
#undef BRAVE_EXECUTE_SELECT_MULTIPLE_FILE
#undef BRAVE_EXECUTE_SELECT_SINGLE_FILE
@@ -0,0 +1,44 @@
diff --git a/ui/shell_dialogs/execute_select_file_win.cc b/ui/shell_dialogs/execute_select_file_win.cc
index 5ef377bcbd69f2f2160aeed6ec4aa9fe3f20275c..ef56ddbe38b42410d7d6571796e025f3059c9c1a 100644
--- a/ui/shell_dialogs/execute_select_file_win.cc
+++ b/ui/shell_dialogs/execute_select_file_win.cc
@@ -362,6 +362,7 @@ bool ExecuteSelectSingleFile(HWND owner,
std::vector<base::FilePath>* paths) {
// Note: The title is not passed down for historical reasons.
// TODO(pmonette): Figure out if it's a worthwhile improvement.
+ BRAVE_EXECUTE_SELECT_SINGLE_FILE
return RunOpenFileDialog(owner, std::u16string(), std::u16string(),
default_path, filter, 0, filter_index, paths);
}
@@ -376,12 +377,14 @@ bool ExecuteSelectMultipleFile(HWND owner,
// Note: The title is not passed down for historical reasons.
// TODO(pmonette): Figure out if it's a worthwhile improvement.
+ BRAVE_EXECUTE_SELECT_MULTIPLE_FILE
return RunOpenFileDialog(owner, std::u16string(), std::u16string(),
default_path, filter, dialog_options, filter_index,
paths);
}
bool ExecuteSaveFile(HWND owner,
+ const std::u16string& title,
const base::FilePath& default_path,
const std::vector<FileFilterSpec>& filter,
const std::wstring& def_ext,
@@ -396,6 +399,7 @@ bool ExecuteSaveFile(HWND owner,
// Note: The title is not passed down for historical reasons.
// TODO(pmonette): Figure out if it's a worthwhile improvement.
+ BRAVE_EXECUTE_SAVE_FILE
return RunSaveFileDialog(owner, std::u16string(), default_path, filter,
dialog_options, def_ext, filter_index, path);
}
@@ -421,7 +425,7 @@ void ExecuteSelectFile(
break;
case SelectFileDialog::SELECT_SAVEAS_FILE: {
base::FilePath path;
- if (ExecuteSaveFile(owner, default_path, filter, default_extension,
+ if (ExecuteSaveFile(owner, title, default_path, filter, default_extension,
&file_type_index, &path)) {
paths.push_back(std::move(path));
}