0

Localize drive suggestion strings

BUG=b:316180378

Change-Id: I8f2c59c32d8d1e86ce6e1f2108200a73a79a0bb8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5221140
Reviewed-by: Matthew Mourgos <mmourgos@chromium.org>
Commit-Queue: Toni Barzic <tbarzic@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1251574}
This commit is contained in:
Toni Barzic
2024-01-24 19:18:10 +00:00
committed by Chromium LUCI CQ
parent 7c62da2c23
commit 25f7bee7cc
15 changed files with 370 additions and 185 deletions

@ -6756,6 +6756,30 @@ New install
<message name="IDS_APP_LIST_KEYBOARD_SHORTCUT_OR" desc="Joiner text for several keyboard shortcuts that all do the same thing. Eg: 'Ctrl-A or Ctrl-B or Ctrl-C'">
Or
</message>
<message name="IDS_FILE_SUGGESTION_JUSTIFICATION" desc="Format for text within a file suggestion chip shown as part of the Chrome OS launcher UI. The suggestion chip provides users suggestions for files they may open on the recent activity. This text is shown under the file name and provides justification for why the file is shown. The text has two parts - the user action that caused the file to be shown, and the time when that action was performed, separate by a separator.">
<ph name="action_description">$1<ex>You edited</ex></ph> · <ph name="time">$2<ex>Dec 5</ex></ph>
</message>
<message name="IDS_FILE_SUGGESTION_JUSTIFICATION_YOU_VIEWED_ACTION" desc="Part of the file suggestion chip UI in Chrome OS launcher. The suggestion chip provides users suggestions for files they may want to open based on the recent activity. The suggestion contains the file name, and a justification describing why the file was suggested (which contains the user action that prompted suggestion, followed by the time the action was taken). The justification is displayed under the file name. This string is the justification action text shown when the file is suggested because the user recently viewed/opened the file.">
You viewed
</message>
<message name="IDS_FILE_SUGGESTION_JUSTIFICATION_GENERIC_MODIFIED_ACTION" desc="Part of the file suggestion chip UI in Chrome OS launcher. The suggestion chip provides users suggestions for files they may want to open based on the recent activity. The suggestion contains the file name, and a justification describing why the file was suggested (which contains the user action that prompted suggestion, followed by the time the action was taken). The justification is displayed under the file name. This string is the justification action text shown when the file is suggested because the file was recently modified. This justification is shown when the user that modified the file is not know (file suggestions may be shown for Google Drive files, which may be modified my multiple users).">
Modified
</message>
<message name="IDS_FILE_SUGGESTION_JUSTIFICATION_YOU_MODIFIED_ACTION" desc="Part of the file suggestion chip UI in Chrome OS launcher. The suggestion chip provides users suggestions for files they may want to open based on the recent activity. The suggestion contains the file name, and a justification describing why the file was suggested (which contains the user action that prompted suggestion, followed by the time the action was taken). The justification is displayed under the file name. This string is the justification action text shown when the file is suggested because the user recently modified the file.">
You modified
</message>
<message name="IDS_FILE_SUGGESTION_JUSTIFICATION_USER_MODIFIED_ACTION" desc="Part of the file suggestion chip UI in Chrome OS launcher. The suggestion chip provides users suggestions for files they may want to open based on the recent activity. The suggestion contains the file name, and a justification describing why the file was suggested (which contains the user action that prompted suggestion, followed by the time the action was taken). The justification is displayed under the file name. This string is the justification action text shown when the file is suggested because the file was recently modified by a user other than the current user (file suggestions may be shown for Google Drive files, which may be modified my multiple users). The string has a placeholder that will be replaced by the name of the user that last modified the file.">
<ph name="user">$1<ex>John Doe</ex></ph> modified
</message>
<message name="IDS_FILE_SUGGESTION_JUSTIFICATION_GENERIC_SHARED_ACTION" desc="Part of the file suggestion chip UI in Chrome OS launcher. The suggestion chip provides users suggestions for files they may want to open based on the recent activity. The suggestion contains the file name, and a justification describing why the file was suggested (which contains the user action that prompted suggestion, followed by the time the action was taken). The justification is displayed under the file name. This string is the justification action text shown when the file is suggested because another user recently shared the file with the user (file suggestions may be shown for Google Drive files).">
Shared
</message>
<message name="IDS_FILE_SUGGESTION_JUSTIFICATION_USER_SHARED_ACTION" desc="Part of the file suggestion chip UI in Chrome OS launcher. The suggestion chip provides users suggestions for files they may want to open based on the recent activity. The suggestion contains the file name, and a justification describing why the file was suggested (which contains the user action that prompted suggestion, followed by the time the action was taken). The justification is displayed under the file name. This string is the justification action text shown when the file is suggested because another user recently shared the file with the user (file suggestions may be shown for Google Drive files). The string has a placeholder that will be replaced by the name of the user that shared the file with the user seeing the suggestion.">
<ph name="user">$1<ex>John Doe</ex></ph> shared
</message>
<message name="IDS_FILE_SUGGESTION_JUSTIFICATION_TIME_NOW" desc="Part of the file suggestion chip UI in Chrome OS launcher. The suggestion chip provides users suggestions for files they may want to open based on the recent activity. The suggestion contains the file name, and a justification describing why the file was suggested (which contains the user action that prompted suggestion, followed by the time the action was taken). The justification is displayed under the file name. This string is used to describe the time when the action was taken in the case the action happened very recently.">
just now
</message>
<message name="IDS_APP_LIST_CONTINUE_EDITED_JUST_NOW" desc="Text displayed under a file suggestion in the launcher, describing why it is being shown. 'Just now' should apply to any time within the last few minutes.">
Edited just now
</message>

@ -0,0 +1 @@
c0d42758751d61e575c06ab403ae808c6b3e9860

@ -0,0 +1 @@
a600ee589bfe547eb9277f6ea97916b961a4c91e

@ -0,0 +1 @@
7b8e27ec10ec30a55acb0cf13532b4f3efbc4f5c

@ -0,0 +1 @@
6ccbef8c98317b22bb4bf0e0ca2f5b817481125b

@ -0,0 +1 @@
c0d42758751d61e575c06ab403ae808c6b3e9860

@ -0,0 +1 @@
7cac7d7706da135184d5de974ffd09fbb1033601

@ -0,0 +1 @@
c0d42758751d61e575c06ab403ae808c6b3e9860

@ -0,0 +1 @@
c0d42758751d61e575c06ab403ae808c6b3e9860

@ -4,9 +4,10 @@
#include "chrome/browser/ash/app_list/search/files/justifications.h"
#include "ash/constants/ash_features.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/i18n/time_formatting.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "ui/base/l10n/l10n_util.h"
@ -21,6 +22,21 @@ constexpr base::TimeDelta kYesterday = base::Days(2);
constexpr base::TimeDelta kPastWeek = base::Days(7);
constexpr base::TimeDelta kPastMonth = base::Days(31);
std::u16string GetTimeString(const base::Time& timestamp) {
const base::Time now = base::Time::Now();
const base::Time midnight = now.LocalMidnight();
if ((now - timestamp).magnitude() <= kJustNow) {
return l10n_util::GetStringUTF16(
IDS_FILE_SUGGESTION_JUSTIFICATION_TIME_NOW);
}
if (timestamp >= midnight && timestamp < midnight + base::Days(1)) {
return base::TimeFormatTimeOfDay(timestamp);
}
return base::LocalizedTimeFormatWithPattern(timestamp, "MMMd");
}
std::optional<std::u16string> GetEditStringFromTime(const base::Time& time) {
const auto& delta = base::Time::Now() - time;
if (delta <= kJustNow) {
@ -55,16 +71,57 @@ std::optional<std::u16string> GetOpenStringFromTime(const base::Time& time) {
}
}
std::u16string GetActionString(JustificationType type,
const std::string& user_name) {
switch (type) {
case JustificationType::kViewed: {
return l10n_util::GetStringUTF16(
IDS_FILE_SUGGESTION_JUSTIFICATION_YOU_VIEWED_ACTION);
}
case JustificationType::kModified: {
if (user_name.empty()) {
return l10n_util::GetStringUTF16(
IDS_FILE_SUGGESTION_JUSTIFICATION_GENERIC_MODIFIED_ACTION);
}
return l10n_util::GetStringFUTF16(
IDS_FILE_SUGGESTION_JUSTIFICATION_USER_MODIFIED_ACTION,
base::UTF8ToUTF16(user_name));
}
case JustificationType::kModifiedByCurrentUser: {
return l10n_util::GetStringUTF16(
IDS_FILE_SUGGESTION_JUSTIFICATION_YOU_MODIFIED_ACTION);
}
case JustificationType::kShared: {
if (user_name.empty()) {
return l10n_util::GetStringUTF16(
IDS_FILE_SUGGESTION_JUSTIFICATION_GENERIC_SHARED_ACTION);
}
return l10n_util::GetStringFUTF16(
IDS_FILE_SUGGESTION_JUSTIFICATION_USER_SHARED_ACTION,
base::UTF8ToUTF16(user_name));
}
}
}
} // namespace
std::optional<std::u16string> GetJustificationString(
const base::Time& last_accessed,
const base::Time& last_modified) {
// t1 > t2 means t1 is more recent. When there's a tie, choose modified.
if (last_modified >= last_accessed) {
return GetEditStringFromTime(last_modified);
} else {
return GetOpenStringFromTime(last_accessed);
JustificationType type,
const base::Time& timestamp,
const std::string& user_name) {
if (ash::features::IsLauncherContinueSectionWithRecentsEnabled()) {
return l10n_util::GetStringFUTF16(IDS_FILE_SUGGESTION_JUSTIFICATION,
GetActionString(type, user_name),
GetTimeString(timestamp));
}
switch (type) {
case JustificationType::kViewed:
return GetOpenStringFromTime(timestamp);
case JustificationType::kModified:
case JustificationType::kModifiedByCurrentUser:
return GetEditStringFromTime(timestamp);
case JustificationType::kShared:
return std::nullopt;
}
}

@ -12,13 +12,26 @@
namespace app_list {
// Returns an appropriate justification string for the given times, for example
// "Opened yesterday". There are different messages for times within the last
// few minutes, day, two days, week, and month. If the time is longer than a
// month ago, nullopt is returned.
enum class JustificationType {
kViewed,
kModified,
kModifiedByCurrentUser,
kShared,
};
// Returns a justification string for file suggestions. The justification string
// describes the action that prompted the file to be suggested to the user.
// `type` is the type of action that prompted the suggestion.
// `timestamp` is the time the action occurred.
// `user_name` is the name of the user that performed the action. The user name
// is only relevant for `kModified` and `kShared` actions (otherwise the action
// is presumed to be performed by the current user). It can be an empty string
// if the user name is not relevant for the action, or not known (in which case
// the justification will show a fallback string without user name).
std::optional<std::u16string> GetJustificationString(
const base::Time& last_accessed,
const base::Time& last_modified);
JustificationType type,
const base::Time& timestamp,
const std::string& user_name);
} // namespace app_list

@ -4,7 +4,9 @@
#include "chrome/browser/ash/app_list/search/files/justifications.h"
#include "ash/constants/ash_features.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -12,80 +14,90 @@
namespace app_list::test {
class JustificationsTest : public ::testing::Test {
public:
JustificationsTest() {
scoped_features_.InitAndDisableFeature(
ash::features::kLauncherContinueSectionWithRecents);
}
private:
base::test::ScopedFeatureList scoped_features_;
};
TEST(JustificationsTest, OpenedOrEdited) {
base::Time now = base::Time::Now();
// Opened more recently than edited.
EXPECT_EQ(
GetJustificationString(now - base::Seconds(10), now - base::Seconds(30)),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_OPENED_JUST_NOW));
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kViewed,
now - base::Seconds(10), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_OPENED_JUST_NOW));
// Edited more recently than opened.
EXPECT_EQ(
GetJustificationString(now - base::Seconds(30), now - base::Seconds(10)),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_JUST_NOW));
// When tied, should be edited.
EXPECT_EQ(
GetJustificationString(now - base::Seconds(30), now - base::Seconds(30)),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_JUST_NOW));
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kModified,
now - base::Seconds(10), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_JUST_NOW));
}
TEST(JustificationsTest, EditTimes) {
base::Time now = base::Time::Now();
// Just now.
EXPECT_EQ(
GetJustificationString(now - base::Minutes(5), now - base::Minutes(5)),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_JUST_NOW));
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kModified,
now - base::Minutes(5), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_JUST_NOW));
// Today.
EXPECT_EQ(
GetJustificationString(now - base::Hours(23), now - base::Hours(23)),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_TODAY));
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kModified,
now - base::Hours(23), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_TODAY));
// Yesterday.
EXPECT_EQ(
GetJustificationString(now - base::Hours(47), now - base::Hours(47)),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_YESTERDAY));
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kModified,
now - base::Hours(47), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_YESTERDAY));
// Past week.
EXPECT_EQ(GetJustificationString(now - base::Days(6), now - base::Days(6)),
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kModified,
now - base::Days(6), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_PAST_WEEK));
// Past month.
EXPECT_EQ(GetJustificationString(now - base::Days(30), now - base::Days(30)),
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kModified,
now - base::Days(30), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_EDITED_PAST_MONTH));
// No string, file too old.
EXPECT_FALSE(
GetJustificationString(now - base::Days(32), now - base::Days(32)));
EXPECT_FALSE(GetJustificationString(app_list::JustificationType::kModified,
now - base::Days(32), /*user_name=*/""));
}
TEST(JustificationsTest, OpenTimes) {
base::Time now = base::Time::Now();
// Just now.
EXPECT_EQ(
GetJustificationString(now - base::Minutes(5), now - base::Days(100)),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_OPENED_JUST_NOW));
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kViewed,
now - base::Minutes(5), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_OPENED_JUST_NOW));
// Today.
EXPECT_EQ(
GetJustificationString(now - base::Hours(23), now - base::Days(100)),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_OPENED_TODAY));
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kViewed,
now - base::Hours(23), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_OPENED_TODAY));
// Yesterday.
EXPECT_EQ(
GetJustificationString(now - base::Hours(47), now - base::Days(100)),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_OPENED_YESTERDAY));
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kViewed,
now - base::Hours(47), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_OPENED_YESTERDAY));
// Past week.
EXPECT_EQ(GetJustificationString(now - base::Days(6), now - base::Days(100)),
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kViewed,
now - base::Days(6), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_OPENED_PAST_WEEK));
// Past month.
EXPECT_EQ(GetJustificationString(now - base::Days(30), now - base::Days(100)),
EXPECT_EQ(GetJustificationString(app_list::JustificationType::kViewed,
now - base::Days(30), /*user_name=*/""),
l10n_util::GetStringUTF16(IDS_APP_LIST_CONTINUE_OPENED_PAST_MONTH));
}

@ -15,8 +15,8 @@
#include "base/i18n/time_formatting.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/ash/app_list/search/files/justifications.h"
#include "chrome/browser/ash/drive/drive_integration_service.h"
#include "chrome/browser/ash/file_suggest/file_suggest_util.h"
#include "chromeos/ash/components/drivefs/drivefs_host.h"
@ -24,7 +24,6 @@
#include "components/drive/file_errors.h"
#include "components/prefs/pref_service.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "ui/base/l10n/time_format.h"
namespace ash {
namespace {
@ -60,13 +59,17 @@ drivefs::mojom::QueryParametersPtr CreateRecentlyViewedQuery() {
return query;
}
std::u16string GetDateString(const base::Time& timestamp) {
const std::u16string relative_date =
ui::TimeFormat::RelativeDate(timestamp, nullptr);
if (!relative_date.empty()) {
return base::ToLowerASCII(relative_date);
}
return base::TimeFormatShortDate(timestamp);
FileSuggestData CreateFileSuggestionWithJustification(
const base::FilePath& path,
app_list::JustificationType justification_type,
const base::Time& timestamp,
const drivefs::mojom::UserInfo* user_info) {
return FileSuggestData(
FileSuggestionType::kDriveFile, path,
app_list::GetJustificationString(
justification_type, timestamp,
user_info ? user_info->display_name : base::EmptyString()),
timestamp, /*new_score=*/std::nullopt);
}
FileSuggestData CreateFileSuggestion(
@ -80,62 +83,34 @@ FileSuggestData CreateFileSuggestion(
if (const absl::optional<base::Time>& shared_time =
file_metadata.shared_with_me_time;
shared_time && !shared_time->is_null() && viewed_time.is_null()) {
if (file_metadata.sharing_user &&
features::IsShowSharingUserInLauncherContinueSectionEnabled()) {
return FileSuggestData(
FileSuggestionType::kDriveFile, path,
base::JoinString(
{u"[Needs i18n]",
base::UTF8ToUTF16(file_metadata.sharing_user->display_name),
u"shared with you", GetDateString(*shared_time)},
u" "),
shared_time, /*new_score=*/absl::nullopt);
}
return FileSuggestData(FileSuggestionType::kDriveFile, path,
base::JoinString({u"[Needs i18n] Shared with you",
GetDateString(*shared_time)},
u" "),
*shared_time, /*new_score=*/absl::nullopt);
return CreateFileSuggestionWithJustification(
path, app_list::JustificationType::kShared, *shared_time,
features::IsShowSharingUserInLauncherContinueSectionEnabled()
? file_metadata.sharing_user.get()
: nullptr);
}
// Viewed by the user more recently than the last modification.
if (viewed_time > modified_time) {
return FileSuggestData(
FileSuggestionType::kDriveFile, path,
base::JoinString(
{u"[Needs i18n] You viewed", GetDateString(viewed_time)}, u" "),
viewed_time, /*new_score=*/absl::nullopt);
return CreateFileSuggestionWithJustification(
path, app_list::JustificationType::kViewed, viewed_time,
/*user_info=*/nullptr);
}
// Last modification was by the user.
if (file_metadata.modified_by_me_time >= modified_time) {
return FileSuggestData(
FileSuggestionType::kDriveFile, path,
base::JoinString({u"[Needs i18n] You modified",
GetDateString(*file_metadata.modified_by_me_time)},
u" "),
*file_metadata.modified_by_me_time, /*new_score=*/absl::nullopt);
if (file_metadata.modified_by_me_time &&
!file_metadata.modified_by_me_time->is_null() &&
file_metadata.modified_by_me_time >= modified_time) {
return CreateFileSuggestionWithJustification(
path, app_list::JustificationType::kModifiedByCurrentUser,
*file_metadata.modified_by_me_time, /*user_info=*/nullptr);
}
// Last modification was by another user - surface the last momdifying user
// name.
if (file_metadata.last_modifying_user) {
return FileSuggestData(
FileSuggestionType::kDriveFile, path,
base::JoinString(
{u"[Needs i18n]",
base::UTF8ToUTF16(file_metadata.last_modifying_user->display_name),
u"modified", GetDateString(modified_time)},
u" "),
modified_time, /*new_score=*/absl::nullopt);
}
// Fallback string when the last modifying user is unknown.
return FileSuggestData(
FileSuggestionType::kDriveFile, path,
base::JoinString({u"[Needs i18n] Modified", GetDateString(modified_time)},
u" "),
modified_time, /*new_score=*/absl::nullopt);
// Last modification was by either by another user, or the last modifying user
// information is not available.
return CreateFileSuggestionWithJustification(
path, app_list::JustificationType::kModified, modified_time,
file_metadata.last_modifying_user.get());
}
} // namespace

@ -110,7 +110,7 @@ std::vector<drivefs::mojom::QueryItemPtr> CreateQueryItems(
base::Time GetReferenceTime() {
base::Time time;
EXPECT_TRUE(base::Time::FromString("Tue, 5 Dec 2023 11:00:00", &time));
EXPECT_TRUE(base::Time::FromString("Tue, 5 Dec 2023 13:30:00", &time));
return time;
}
@ -363,10 +363,10 @@ TEST_F(DriveRecentFileSuggestionProviderTest,
auto search_query = std::make_unique<FakeSearchQuery>(CreateQueryItems(
{{.path = base::FilePath("/Viewed last item 1"),
.last_modified_time = GetReferenceTime() - base::Days(1),
.last_viewed_by_me_time = GetReferenceTime() - base::Hours(12)},
.last_viewed_by_me_time = GetReferenceTime() - base::Hours(6)},
{.path = base::FilePath("/Modified and viewed last item"),
.last_modified_time = GetReferenceTime() - base::Days(1),
.last_viewed_by_me_time = GetReferenceTime() - base::Days(1)},
.last_modified_time = GetReferenceTime() - base::Hours(12),
.last_viewed_by_me_time = GetReferenceTime() - base::Hours(12)},
{.path = base::FilePath("/Viewed last item 2"),
.last_modified_time = GetReferenceTime() - base::Days(4),
.last_viewed_by_me_time =
@ -394,16 +394,16 @@ TEST_F(DriveRecentFileSuggestionProviderTest,
actual_suggestions,
ElementsAre(
SuggestionInfo(root.Append("Modified last item 1"),
u"[Needs i18n] Modified today"),
u"Modified · just now"),
SuggestionInfo(root.Append("Viewed last item 1"),
u"[Needs i18n] You viewed yesterday"),
u"You viewed · 7:30AM"),
SuggestionInfo(
root.Append("Modified and viewed last item"),
u"[Needs i18n] Modified yesterday"),
u"Modified · Dec 4"),
SuggestionInfo(root.Append("Viewed last item 2"),
u"[Needs i18n] You viewed Dec 2, 2023"),
u"You viewed · Dec 3"),
SuggestionInfo(root.Append("Modified last item 2"),
u"[Needs i18n] Modified Dec 2, 2023")));
u"Modified · Dec 2")));
result_waiter.Quit();
})));
@ -435,7 +435,7 @@ TEST_F(DriveRecentFileSuggestionProviderTest, ModifyingUserInfo) {
.last_modified_time = GetReferenceTime(),
.modified_by_me_time = GetReferenceTime(),
.last_modifying_user = "Test User",
.last_viewed_by_me_time = GetReferenceTime() - base::Days(1)},
.last_viewed_by_me_time = GetReferenceTime() - base::Hours(1)},
{.path = base::FilePath("/Modified last by someone else"),
.last_modified_time = GetReferenceTime() - base::Days(1),
.modified_by_me_time = GetReferenceTime() - base::Days(2),
@ -467,8 +467,7 @@ TEST_F(DriveRecentFileSuggestionProviderTest, ModifyingUserInfo) {
.last_modified_time = GetReferenceTime() - base::Days(1),
.modified_by_me_time = GetReferenceTime() - base::Days(1),
.last_modifying_user = "Test User",
.last_viewed_by_me_time =
GetReferenceTime() - base::Hours(12)}}));
.last_viewed_by_me_time = GetReferenceTime() - base::Hours(1)}}));
mojo::MakeSelfOwnedReceiver(std::move(search_query),
std::move(receiver));
});
@ -492,18 +491,17 @@ TEST_F(DriveRecentFileSuggestionProviderTest, ModifyingUserInfo) {
actual_suggestions,
ElementsAre(
SuggestionInfo(root.Append("Modified last by user"),
u"[Needs i18n] You modified today"),
u"You modified · just now"),
SuggestionInfo(root.Append("Viewed last item"),
u"[Needs i18n] You viewed yesterday"),
u"You viewed · 12:30PM"),
SuggestionInfo(
root.Append("Modified last by someone else"),
u"[Needs i18n] Test User modified yesterday"),
SuggestionInfo(
root.Append("No modified by me time"),
u"[Needs i18n] Test User modified yesterday"),
u"Test User modified · Dec 4"),
SuggestionInfo(root.Append("No modified by me time"),
u"Test User modified · Dec 4"),
SuggestionInfo(
root.Append("No last modifying user info"),
u"[Needs i18n] Modified Dec 2, 2023")));
u"Modified · Dec 2")));
result_waiter.Quit();
})));
@ -539,15 +537,15 @@ TEST_F(DriveRecentFileSuggestionProviderTest, SharedItems) {
.last_viewed_by_me_time = GetReferenceTime() - base::Days(1),
.shared_with_me_time = GetReferenceTime() - base::Days(2)},
{.path = base::FilePath("/Modified last by user"),
.last_modified_time = GetReferenceTime() - base::Hours(2),
.modified_by_me_time = GetReferenceTime() - base::Hours(2),
.last_modified_time = GetReferenceTime() - base::Minutes(2),
.modified_by_me_time = GetReferenceTime() - base::Minutes(2),
.last_modifying_user = "Test User",
.last_viewed_by_me_time = GetReferenceTime() - base::Days(1),
.shared_with_me_time = GetReferenceTime() - base::Days(2)},
{.path = base::FilePath("/Modified last, not viewed by user"),
.last_modified_time = GetReferenceTime() - base::Days(1),
.last_modified_time = GetReferenceTime() - base::Minutes(3),
.last_modifying_user = "Test User",
.shared_with_me_time = GetReferenceTime() - base::Days(2)},
.shared_with_me_time = GetReferenceTime() - base::Minutes(5)},
{.path = base::FilePath("/Shared with sharing user info"),
.last_modified_time = GetReferenceTime() - base::Hours(26),
.last_modifying_user = "Test User 1",
@ -573,7 +571,7 @@ TEST_F(DriveRecentFileSuggestionProviderTest, SharedItems) {
.last_modified_time = GetReferenceTime() - base::Days(1),
.modified_by_me_time = GetReferenceTime() - base::Days(1),
.last_modifying_user = "Test User",
.last_viewed_by_me_time = GetReferenceTime() - base::Hours(12),
.last_viewed_by_me_time = GetReferenceTime() - base::Minutes(5),
.shared_with_me_time = GetReferenceTime() - base::Days(2)}}));
mojo::MakeSelfOwnedReceiver(std::move(search_query),
std::move(receiver));
@ -599,17 +597,17 @@ TEST_F(DriveRecentFileSuggestionProviderTest, SharedItems) {
ElementsAre(
SuggestionInfo(
root.Append("Modified last, viewed by user"),
u"[Needs i18n] Test User modified today"),
u"Test User modified · just now"),
SuggestionInfo(root.Append("Modified last by user"),
u"[Needs i18n] You modified today"),
SuggestionInfo(root.Append("Viewed last item"),
u"[Needs i18n] You viewed yesterday"),
u"You modified · just now"),
SuggestionInfo(
root.Append("Modified last, not viewed by user"),
u"[Needs i18n] Shared with you Dec 3, 2023"),
u"Shared · just now"),
SuggestionInfo(root.Append("Viewed last item"),
u"You viewed · just now"),
SuggestionInfo(
root.Append("Shared with sharing user info"),
u"[Needs i18n] Shared with you Dec 2, 2023")));
u"Shared · Dec 2")));
result_waiter.Quit();
})));
@ -651,9 +649,9 @@ TEST_F(DriveRecentFileSuggestionProviderWithSharingUserTest, SharedItems) {
.last_viewed_by_me_time = GetReferenceTime() - base::Days(1),
.shared_with_me_time = GetReferenceTime() - base::Days(2)},
{.path = base::FilePath("/Modified last, not viewed by user"),
.last_modified_time = GetReferenceTime() - base::Days(1),
.last_modified_time = GetReferenceTime() - base::Hours(2),
.last_modifying_user = "Test User",
.shared_with_me_time = GetReferenceTime() - base::Days(2)},
.shared_with_me_time = GetReferenceTime() - base::Hours(3)},
{.path = base::FilePath("/Shared with sharing user info"),
.last_modified_time = GetReferenceTime() - base::Hours(26),
.last_modifying_user = "Test User 1",
@ -705,18 +703,17 @@ TEST_F(DriveRecentFileSuggestionProviderWithSharingUserTest, SharedItems) {
ElementsAre(
SuggestionInfo(
root.Append("Modified last, viewed by user"),
u"[Needs i18n] Test User modified today"),
u"Test User modified · just now"),
SuggestionInfo(root.Append("Modified last by user"),
u"[Needs i18n] You modified today"),
SuggestionInfo(root.Append("Viewed last item"),
u"[Needs i18n] You viewed yesterday"),
u"You modified · 11:30AM"),
SuggestionInfo(
root.Append("Modified last, not viewed by user"),
u"[Needs i18n] Shared with you Dec 3, 2023"),
u"Shared · 10:30AM"),
SuggestionInfo(root.Append("Viewed last item"),
u"You viewed · 1:30AM"),
SuggestionInfo(
root.Append("Shared with sharing user info"),
u"[Needs i18n] Test User 2 shared with you "
u"Dec 2, 2023")));
u"Test User 2 shared · Dec 2")));
result_waiter.Quit();
})));
@ -770,7 +767,7 @@ TEST_F(DriveRecentFileSuggestionProviderTest,
auto search_query = std::make_unique<FakeSearchQuery>(CreateQueryItems(
{{.path = base::FilePath("/Viewed last item 1"),
.last_viewed_by_me_time = GetReferenceTime() - base::Hours(12)},
.last_viewed_by_me_time = GetReferenceTime() - base::Hours(16)},
{.path = base::FilePath("/Modified and viewed last item"),
.last_modified_time = GetReferenceTime() - base::Days(1),
.last_viewed_by_me_time = GetReferenceTime() - base::Days(1)},
@ -801,21 +798,116 @@ TEST_F(DriveRecentFileSuggestionProviderTest,
actual_suggestions,
ElementsAre(
SuggestionInfo(root.Append("Modified last item 1"),
u"[Needs i18n] Modified today"),
u"Modified · just now"),
SuggestionInfo(root.Append("Viewed last item 1"),
u"[Needs i18n] You viewed yesterday"),
u"You viewed · Dec 4"),
SuggestionInfo(
root.Append("Modified and viewed last item"),
u"[Needs i18n] Modified yesterday"),
SuggestionInfo(
root.Append("Viewed last item 2"),
u"[Needs i18n] You viewed Dec 2, 2023")));
u"Modified · Dec 4"),
SuggestionInfo(root.Append("Viewed last item 2"),
u"You viewed · Dec 3")));
result_waiter.Quit();
})));
result_waiter.Run();
}
// Verifies that file suggest service can handle recent drive files with
// modification/view timestamps from the future.
TEST_F(DriveRecentFileSuggestionProviderTest, TimestampsInFuture) {
base::subtle::ScopedTimeClockOverrides time_override(
&GetReferenceTime,
/*time_ticks_override=*/nullptr, /*thread_ticks_override=*/nullptr);
EnableDriveAndWaitForMountPoint();
EXPECT_CALL(*fake_drivefs(),
StartSearchQuery(
_, Pointee(Field(&QueryParameters::sort_field,
QueryParameters::SortField::kLastModified))))
.WillOnce([&](mojo::PendingReceiver<drivefs::mojom::SearchQuery> receiver,
drivefs::mojom::QueryParametersPtr query_params) {
EXPECT_EQ(drivefs::mojom::QueryParameters::QuerySource::kLocalOnly,
query_params->query_source);
EXPECT_EQ(drivefs::mojom::QueryParameters::SortDirection::kDescending,
query_params->sort_direction);
auto search_query = std::make_unique<FakeSearchQuery>(CreateQueryItems(
{{.path = base::FilePath("/Modified last by user"),
.last_modified_time = GetReferenceTime() + base::Minutes(1),
.modified_by_me_time = GetReferenceTime() + base::Minutes(1),
.last_modifying_user = "Test User",
.last_viewed_by_me_time = GetReferenceTime() + base::Hours(1)},
{.path = base::FilePath("/Modified last by someone else"),
.last_modified_time = GetReferenceTime() + base::Days(2),
.modified_by_me_time = GetReferenceTime() + base::Days(1),
.last_modifying_user = "Test User",
.last_viewed_by_me_time = GetReferenceTime() + base::Days(2)},
{.path = base::FilePath("/No modified by me time"),
.last_modified_time = GetReferenceTime() + base::Minutes(1),
.last_modifying_user = "Test User",
.last_viewed_by_me_time = GetReferenceTime() + base::Minutes(2)},
{.path = base::FilePath("/No last modifying user info"),
.last_modified_time = GetReferenceTime() + base::Days(3),
.last_viewed_by_me_time = GetReferenceTime() + base::Days(3)}}));
mojo::MakeSelfOwnedReceiver(std::move(search_query),
std::move(receiver));
});
EXPECT_CALL(
*fake_drivefs(),
StartSearchQuery(
_, Pointee(Field(&QueryParameters::sort_field,
QueryParameters::SortField::kLastViewedByMe))))
.WillOnce([&](mojo::PendingReceiver<drivefs::mojom::SearchQuery> receiver,
drivefs::mojom::QueryParametersPtr query_params) {
EXPECT_EQ(drivefs::mojom::QueryParameters::QuerySource::kLocalOnly,
query_params->query_source);
EXPECT_EQ(drivefs::mojom::QueryParameters::SortDirection::kDescending,
query_params->sort_direction);
auto search_query = std::make_unique<FakeSearchQuery>(CreateQueryItems(
{{.path = base::FilePath("/Viewed last item"),
.last_modified_time = GetReferenceTime() + base::Days(1),
.modified_by_me_time = GetReferenceTime() + base::Days(1),
.last_modifying_user = "Test User",
.last_viewed_by_me_time = GetReferenceTime() + base::Days(2)}}));
mojo::MakeSelfOwnedReceiver(std::move(search_query),
std::move(receiver));
});
base::RunLoop result_waiter;
FileSuggestKeyedServiceFactory::GetInstance()
->GetService(profile())
->GetSuggestFileData(
FileSuggestionType::kDriveFile,
base::BindOnce(base::BindLambdaForTesting(
[&](const std::optional<std::vector<FileSuggestData>>& data) {
ASSERT_TRUE(data);
std::vector<SuggestionInfo> actual_suggestions;
for (const auto& suggestion : data.value()) {
actual_suggestions.emplace_back(suggestion);
}
const base::FilePath root = GetDriveRoot();
EXPECT_THAT(
actual_suggestions,
ElementsAre(
SuggestionInfo(
root.Append("No last modifying user info"),
u"Modified · Dec 8"),
SuggestionInfo(
root.Append("Modified last by someone else"),
u"Test User modified · Dec 7"),
SuggestionInfo(root.Append("Viewed last item"),
u"You viewed · Dec 7"),
SuggestionInfo(root.Append("Modified last by user"),
u"You viewed · 2:30PM"),
SuggestionInfo(root.Append("No modified by me time"),
u"You viewed · just now")));
result_waiter.Quit();
})));
result_waiter.Run();
}
// Verifies that file suggest service returns empty suggestions if drive search
// requests fail.
TEST_F(DriveRecentFileSuggestionProviderTest, DriveFailedSearch) {
@ -926,12 +1018,12 @@ TEST_F(DriveRecentFileSuggestionProviderTest, LastViewedSearchFailed) {
actual_suggestions,
ElementsAre(
SuggestionInfo(root.Append("Modified last item 1"),
u"[Needs i18n] Modified today"),
u"Modified · just now"),
SuggestionInfo(
root.Append("Modified and viewed last item"),
u"[Needs i18n] Modified yesterday"),
u"Modified · Dec 4"),
SuggestionInfo(root.Append("Modified last item 2"),
u"[Needs i18n] Modified Dec 2, 2023")));
u"Modified · Dec 2")));
result_waiter.Quit();
})));
@ -1011,13 +1103,12 @@ TEST_F(DriveRecentFileSuggestionProviderTest, ModifiedTimeSearchFailed) {
actual_suggestions,
ElementsAre(
SuggestionInfo(root.Append("Viewed last item 1"),
u"[Needs i18n] You viewed yesterday"),
u"You viewed · 1:30AM"),
SuggestionInfo(
root.Append("Modified and viewed last item"),
u"[Needs i18n] Modified yesterday"),
SuggestionInfo(
root.Append("Viewed last item 2"),
u"[Needs i18n] You viewed Dec 2, 2023")));
u"Modified · Dec 4"),
SuggestionInfo(root.Append("Viewed last item 2"),
u"You viewed · Dec 3")));
result_waiter.Quit();
})));
@ -1121,11 +1212,10 @@ TEST_F(DriveRecentFileSuggestionProviderTest, SequentialSearches) {
const base::FilePath root = GetDriveRoot();
EXPECT_THAT(
actual_suggestions,
ElementsAre(
SuggestionInfo(root.Append("Viewed last item 1"),
u"[Needs i18n] You viewed today"),
SuggestionInfo(root.Append("Modified last item 1"),
u"[Needs i18n] Modified yesterday")));
ElementsAre(SuggestionInfo(root.Append("Viewed last item 1"),
u"You viewed · just now"),
SuggestionInfo(root.Append("Modified last item 1"),
u"Modified · Dec 4")));
result_waiter_1.Quit();
})));
@ -1146,11 +1236,10 @@ TEST_F(DriveRecentFileSuggestionProviderTest, SequentialSearches) {
const base::FilePath root = GetDriveRoot();
EXPECT_THAT(
actual_suggestions,
ElementsAre(
SuggestionInfo(root.Append("Viewed last item 2"),
u"[Needs i18n] You viewed today"),
SuggestionInfo(root.Append("Modified last item 2"),
u"[Needs i18n] Modified Dec 3, 2023")));
ElementsAre(SuggestionInfo(root.Append("Viewed last item 2"),
u"You viewed · just now"),
SuggestionInfo(root.Append("Modified last item 2"),
u"Modified · Dec 3")));
result_waiter_2.Quit();
})));
@ -1224,11 +1313,10 @@ TEST_F(DriveRecentFileSuggestionProviderTest, ConcurrentRequests) {
const base::FilePath root = GetDriveRoot();
EXPECT_THAT(
actual_suggestions,
ElementsAre(
SuggestionInfo(root.Append("Viewed last item"),
u"[Needs i18n] You viewed today"),
SuggestionInfo(root.Append("Modified last item"),
u"[Needs i18n] Modified yesterday")));
ElementsAre(SuggestionInfo(root.Append("Viewed last item"),
u"You viewed · just now"),
SuggestionInfo(root.Append("Modified last item"),
u"Modified · Dec 4")));
result_waiter_1.Quit();
})));
@ -1248,11 +1336,10 @@ TEST_F(DriveRecentFileSuggestionProviderTest, ConcurrentRequests) {
const base::FilePath root = GetDriveRoot();
EXPECT_THAT(
actual_suggestions,
ElementsAre(
SuggestionInfo(root.Append("Viewed last item"),
u"[Needs i18n] You viewed today"),
SuggestionInfo(root.Append("Modified last item"),
u"[Needs i18n] Modified yesterday")));
ElementsAre(SuggestionInfo(root.Append("Viewed last item"),
u"You viewed · just now"),
SuggestionInfo(root.Append("Modified last item"),
u"Modified · Dec 4")));
result_waiter_2.Quit();
})));

@ -204,11 +204,20 @@ void LocalFileSuggestionProvider::OnValidationComplete(
std::vector<FileSuggestData> final_results;
for (auto& result : results.first) {
final_results.emplace_back(
FileSuggestionType::kLocalFile, result.path,
app_list::GetJustificationString(result.info.last_accessed,
result.info.last_modified),
/*timestamp=*/std::nullopt, result.score);
absl::optional<std::u16string> justification_string =
result.info.last_accessed > result.info.last_modified
? app_list::GetJustificationString(
app_list::JustificationType::kViewed,
result.info.last_accessed,
/*user_name=*/"")
: app_list::GetJustificationString(
app_list::JustificationType::kModifiedByCurrentUser,
result.info.last_modified,
/*user_name=*/"");
;
final_results.emplace_back(FileSuggestionType::kLocalFile, result.path,
justification_string,
/*timestamp=*/std::nullopt, result.score);
}
// Sort valid results high-to-low by score.