blob: 40e0dc39d16258c14c9fd5d51ed1d02240482f66 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_TABS_ORGANIZATION_TAB_ORGANIZATION_H_
#define CHROME_BROWSER_UI_TABS_ORGANIZATION_TAB_ORGANIZATION_H_
#include <memory>
#include <optional>
#include <string>
#include <variant>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "chrome/browser/ui/tabs/organization/tab_data.h"
#include "components/optimization_guide/proto/features/common_quality_data.pb.h"
#include "components/tab_groups/tab_group_id.h"
class TabOrganization : public TabData::Observer {
public:
using ID = int;
using TabDatas = std::vector<std::unique_ptr<TabData>>;
// Used to display the current name of the organization by either indexing
// into the names_ list (the size_t) or providing a custom name |u16string|.
using CurrentName = std::variant<size_t, std::u16string>;
class Observer {
public:
virtual ~Observer() = default;
virtual void OnTabOrganizationUpdated(const TabOrganization* organization) {
}
virtual void OnTabOrganizationDestroyed(
TabOrganization::ID organization_id) {}
};
// These values are logged to UMA. Entries should not be renumbered and
// numeric values should never be reused. Please keep in sync with
// "TabOrganizationUserChoice" in src/tools/metrics/histograms/enums.xml.
enum class UserChoice {
kNoChoice = 0,
kAccepted = 1,
kRejected = 2,
kMaxValue = kRejected,
};
TabOrganization(TabDatas tab_datas,
std::vector<std::u16string> names,
int first_new_tab_index = 0,
CurrentName current_name = 0u,
UserChoice choice = UserChoice::kNoChoice);
~TabOrganization() override;
const TabDatas& tab_datas() const { return tab_datas_; }
int first_new_tab_index() const { return first_new_tab_index_; }
const std::vector<std::u16string>& names() const { return names_; }
const CurrentName& current_name() const { return current_name_; }
UserChoice choice() const { return choice_; }
// TODO(b/331852814): Remove along with the multi tab organization flag
optimization_guide::proto::UserFeedback feedback() const { return feedback_; }
std::optional<tab_groups::TabGroupId> group_id() const { return group_id_; }
ID organization_id() const { return organization_id_; }
const std::u16string GetDisplayName() const;
const std::vector<TabData::TabID>& user_removed_tab_ids() const {
return user_removed_tab_ids_;
}
bool IsValidForOrganizing() const;
void AddObserver(Observer* new_observer);
void RemoveObserver(Observer* new_observer);
void AddTabData(std::unique_ptr<TabData> tab_data);
void RemoveTabData(TabData::TabID id);
void SetCurrentName(CurrentName new_current_name);
// TODO(b/331852814): Remove along with the multi tab organization flag
void SetFeedback(optimization_guide::proto::UserFeedback feedback) {
feedback_ = feedback;
}
void SetTabGroupId(std::optional<tab_groups::TabGroupId> id) {
group_id_ = id;
}
void Accept();
void Reject();
// TabData::Observer
void OnTabDataUpdated(const TabData* tab_data) override;
void OnTabDataDestroyed(TabData::TabID tab_id) override;
private:
// Notifies observers of the tab data that it has been updated.
void NotifyObserversOfUpdate();
// The tabs that are currently included in the organization. When accepted,
// they will be organized in the tabstrip.
TabDatas tab_datas_;
// The index of the first tab in the organization that is not already part of
// the corresponding tab group, if any. Will be 0 if this does not correspond
// to an existing tab group.
int first_new_tab_index_ = 0;
// The tab ids that have been removed by the user after the organization was
// instantiated.
std::vector<TabData::TabID> user_removed_tab_ids_;
// The list of suggested names for the organization. If the |current_name_| is
// a size_t then it refers to an index in the |names_| vector.
std::vector<std::u16string> names_;
// The currently set name for the organization. defaults to the first name in
// the list of names, but if the user changes to a custom name, it will be
// represented as a u16string.
CurrentName current_name_ = 0u;
// What the user has decided to do with the Organization. If a user doesnt
// Interact with the organization then this will have the value kNoChoice.
// Once the user has interacted this will become either kAccepted or
// kRejected. Set only via the Accept() and Reject() methods.
UserChoice choice_ = UserChoice::kNoChoice;
// A separate feedback mechanism, represents whether the user has provided
// feedback via the thumbs UI.
// TODO(b/331852814): Remove along with the multi tab organization flag
optimization_guide::proto::UserFeedback feedback_ =
optimization_guide::proto::UserFeedback::USER_FEEDBACK_UNSPECIFIED;
// The id for the existing tab group this organization refers to, if any.
std::optional<tab_groups::TabGroupId> group_id_ = std::nullopt;
// a monotonically increasing ID to refer to the organization in the
// TabOrganizationSession.
ID organization_id_;
// A flag that forces the tab organization to be marked as invalid.
bool invalidated_by_tab_change_ = false;
base::ObserverList<Observer>::Unchecked observers_;
base::WeakPtrFactory<TabOrganization> weak_ptr_factory_{this};
};
#endif // CHROME_BROWSER_UI_TABS_ORGANIZATION_TAB_ORGANIZATION_H_