1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
// Copyright 2024 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_ANDROID_TAB_MODEL_TAB_MODEL_TEST_HELPER_H_
#define CHROME_BROWSER_UI_ANDROID_TAB_MODEL_TAB_MODEL_TEST_HELPER_H_
#include <memory>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/sequence_checker.h"
#include "chrome/browser/android/tab_android.h"
#include "chrome/browser/flags/android/chrome_session_state.h"
#include "chrome/browser/ui/android/tab_model/tab_model.h"
#include "content/public/test/browser_test_utils.h"
#include "url/gurl.h"
namespace content {
class WebContents;
}
class TabModelObserver;
// TestTabModel is a thin TabModel that can be used for testing Android tab
// behavior. It holds pointers to WebContents that are owned elsewhere. Many
// functions are unimplemented. Use OwningTestTabModel for a more complete
// TabModel implementation.
// TODO(crbug.com/415309796): Convert tests using this to OwningTestTabModel and
// remove it.
class TestTabModel : public TabModel {
public:
explicit TestTabModel(Profile* profile,
chrome::android::ActivityType activity_type =
chrome::android::ActivityType::kTabbed);
~TestTabModel() override;
// TabModel:
// Returns tab_count_ if not 0. Otherwise, returns size of web_contents_list_.
int GetTabCount() const override;
int GetActiveIndex() const override;
content::WebContents* GetWebContentsAt(int index) const override;
base::android::ScopedJavaLocalRef<jobject> GetJavaObject() const override;
void CreateTab(TabAndroid* parent,
content::WebContents* web_contents,
bool select) override;
void HandlePopupNavigation(TabAndroid* parent,
NavigateParams* params) override;
content::WebContents* CreateNewTabForDevTools(const GURL& url,
bool new_window) override;
bool IsSessionRestoreInProgress() const override;
bool IsActiveModel() const override;
void SetIsActiveModel(bool is_active);
TabAndroid* GetTabAt(int index) const override;
void SetActiveIndex(int index) override;
void ForceCloseAllTabs() override;
void CloseTabAt(int index) override;
void AddObserver(TabModelObserver* observer) override;
void RemoveObserver(TabModelObserver* observer) override;
TabModelObserver* GetObserver();
void SetTabCount(int tab_count);
void SetWebContentsList(
const std::vector<raw_ptr<content::WebContents>>& web_contents_list);
int GetTabCountNavigatedInTimeWindow(
const base::Time& begin_time,
const base::Time& end_time) const override;
void CloseTabsNavigatedInTimeWindow(const base::Time& begin_time,
const base::Time& end_time) override;
// TODO(crbug.com/415351293): Implement these.
// TabListInterface implementation.
void OpenTab(const GURL& url, int index) override;
void DiscardTab(int index) override;
void DuplicateTab(int index) override;
tabs::TabInterface* GetTab(int index) override;
void HighlightTabs(std::set<int> indicies) override;
void MoveTab(int from_index, int to_index) override;
void CloseTab(int index) override;
std::vector<tabs::TabInterface*> GetAllTabs() override;
void PinTab(int index) override;
void UnpinTab(int index) override;
std::optional<tab_groups::TabGroupId> CreateGroup(
std::set<int> indicies) override;
void MoveGroupTo(tab_groups::TabGroupId group_id, int index) override;
private:
// A fake value for the current number of tabs.
int tab_count_ = 0;
bool is_active_ = false;
raw_ptr<TabModelObserver> observer_ = nullptr;
std::vector<raw_ptr<content::WebContents>> web_contents_list_;
};
// A TabModel that owns the WebContents for each tab and simulates many of the
// operations that are provided by the JNI bridge in the production TabModel.
class OwningTestTabModel : public TabModel {
public:
// Creates a TabModel that starts empty. The model will automatically be added
// to the TabModelList, and removed when it's destroyed.
explicit OwningTestTabModel(Profile* profile,
chrome::android::ActivityType activity_type =
chrome::android::ActivityType::kTabbed);
~OwningTestTabModel() override;
OwningTestTabModel(const OwningTestTabModel&) = delete;
OwningTestTabModel& operator=(const OwningTestTabModel&) = delete;
// TabModel:
int GetTabCount() const override;
int GetActiveIndex() const override;
content::WebContents* GetWebContentsAt(int index) const override;
TabAndroid* GetTabAt(int index) const override;
void SetActiveIndex(int index) override;
void ForceCloseAllTabs() override;
void CloseTabAt(int index) override;
void CreateTab(TabAndroid* parent,
content::WebContents* web_contents,
bool select) override;
bool IsActiveModel() const override;
void AddObserver(TabModelObserver* observer) override;
void RemoveObserver(TabModelObserver* observer) override;
// Unimplemented methods.
base::android::ScopedJavaLocalRef<jobject> GetJavaObject() const override;
void HandlePopupNavigation(TabAndroid* parent,
NavigateParams* params) override;
content::WebContents* CreateNewTabForDevTools(const GURL& url,
bool new_window) override;
bool IsSessionRestoreInProgress() const override;
int GetTabCountNavigatedInTimeWindow(
const base::Time& begin_time,
const base::Time& end_time) const override;
void CloseTabsNavigatedInTimeWindow(const base::Time& begin_time,
const base::Time& end_time) override;
// Test accessors:
// Adds a new tab containing an empty `web_contents` at `index`. If `select`
// is true the new tab will become active.
TabAndroid* AddEmptyTab(size_t index,
bool select = false,
TabModel::TabLaunchType launch_type =
TabModel::TabLaunchType::FROM_CHROME_UI);
// Adds a new tab containing `web_contents` at `index`. If `select` is true
// the new tab will become active.
TabAndroid* AddTabFromWebContents(
std::unique_ptr<content::WebContents> web_contents,
size_t index,
bool select = false,
TabModel::TabLaunchType launch_type =
TabModel::TabLaunchType::FROM_CHROME_UI);
void SetIsActiveModel(bool is_active);
// TODO(crbug.com/415351293): Implement these.
// TabListInterface implementation.
void OpenTab(const GURL& url, int index) override;
void DiscardTab(int index) override;
void DuplicateTab(int index) override;
tabs::TabInterface* GetTab(int index) override;
void HighlightTabs(std::set<int> indicies) override;
void MoveTab(int from_index, int to_index) override;
void CloseTab(int index) override;
std::vector<tabs::TabInterface*> GetAllTabs() override;
void PinTab(int index) override;
void UnpinTab(int index) override;
std::optional<tab_groups::TabGroupId> CreateGroup(
std::set<int> indicies) override;
void MoveGroupTo(tab_groups::TabGroupId group_id, int index) override;
private:
void SelectTab(TabAndroid* tab, TabModel::TabSelectionType selection_type);
SEQUENCE_CHECKER(sequence_checker_);
base::ObserverList<TabModelObserver>::Unchecked observer_list_
GUARDED_BY_CONTEXT(sequence_checker_);
std::vector<std::unique_ptr<TabAndroid>> owned_tabs_
GUARDED_BY_CONTEXT(sequence_checker_);
raw_ptr<TabAndroid> active_tab_ GUARDED_BY_CONTEXT(sequence_checker_) =
nullptr;
bool is_active_model_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
int next_tab_id_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
};
// Waits until a TabAndroid has a WebContents assigned that's finished loading.
class TabAndroidLoadedWaiter final : public TabAndroid::Observer {
public:
explicit TabAndroidLoadedWaiter(TabAndroid* tab);
~TabAndroidLoadedWaiter() final;
TabAndroidLoadedWaiter(const TabAndroidLoadedWaiter&) = delete;
TabAndroidLoadedWaiter& operator=(const TabAndroidLoadedWaiter&) = delete;
bool Wait();
// TabAndroid::Observer:
void OnInitWebContents(TabAndroid* tab) final;
private:
content::WaiterHelper waiter_helper_;
bool load_succeeded_ = false;
base::ScopedObservation<TabAndroid, TabAndroid::Observer> tab_observation_{
this};
};
#endif // CHROME_BROWSER_UI_ANDROID_TAB_MODEL_TAB_MODEL_TEST_HELPER_H_
|