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 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
|
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module tabs_api.mojom;
import "chrome/browser/ui/webui/tabs/tabs.mojom";
import "components/tab_groups/public/mojom/tab_group_types.mojom";
import "mojo/public/mojom/base/empty.mojom";
import "mojo/public/mojom/base/error.mojom";
import "url/mojom/url.mojom";
// References a node in the tab tree. (id, type) uniquely identifies a node in
// the tree.
struct NodeId {
// The type of object referenced by the id.
enum Type {
// An unknown type. This will never be returned by the service and usually
// indicates an invalid argument from the client.
kUnknown,
// A content tab.
kContent,
// A collection of tabs.
kCollection,
};
// An opaque string that uniquely identifies the underlying resource. This
// id will be unique across all resource types. Users should not try to
// extrapolate any sort of pattern from this string.
string id;
// The type of resource referenced by this id.
Type type;
};
struct Tab {
NodeId id;
string title;
url.mojom.Url url;
// TODO(crbug.com/414630734). The favicon should be typemapped to ImageModel
// in c++. Leave this as a data uri for now.
url.mojom.Url favicon_url;
array<tabs.mojom.TabAlertState> alert_states;
tabs.mojom.TabNetworkState network_state;
};
// Position is an ephemeral object that should not be saved nor act as an
// identifier. It is purely used in this API to determine the position within
// the TabstripModel.
struct Position {
// The parent of the tab. This is only set if the tab is a child of a
// collection.
// TODO(crbug.com/412935315): make this a required field. All nodes should
// have a parent, except for the TabStripCollection which is the root. The
// root should never need to be moved, doing so should trigger a CHECK error.
NodeId? parent_id;
// The index of the tab within the parent.
uint32 index;
};
// A snapshot of the current tabs in the tab strip.
struct TabsSnapshot {
TabCollectionContainer tab_strip;
// Updates to tabs would be sent through this update stream. Clients may
// subscribe to this stream to receive update events.
// The interface is associated with the interface used to retrieve this
// stream. This means that the ordering of the message between the remote
// and the observation stream is preserved.
pending_associated_receiver<TabsObserver> stream;
};
// References the TabCollection object. A TabCollection can be of various
// `collection_types`. The `id` is used to uniquely identify the TabCollection
// with the tree.
struct TabCollection {
enum CollectionType {
kUnknown,
kTabStrip,
kPinned,
kUnpinned,
kTabGroup,
kSplitTab,
};
// Unique id for the specific TabCollection. The id type would be a
// kCollection.
NodeId id;
CollectionType collection_type;
};
// TODO(crbug.com/425652802): This should be merged with struct
// TabGroupVisualData in
// //chrome/browser/ui/webui/tab_strip/tab_strip.mojom and moved to
// //components/tab_groups/public/mojom/tab_group_types.mojom
struct TabGroupVisualData {
string title;
tab_groups.mojom.Color color;
bool is_collapsed;
};
// The TabCollection tree has child nodes that can be a Tab or a
// TabCollection. This container is used to represents the child nodes of the
// tab strip tree.
union Container {
TabContainer tab_container;
TabCollectionContainer tab_collection_container;
};
// TabCollectionContainer represents a TabCollection's position within the tree.
// It contains an array of elements that can be either a TabContainer or a
// TabCollectionContainer.
struct TabCollectionContainer {
TabCollection collection;
array<Container> elements;
};
// TabContainer represents the tab's position within the tree.
struct TabContainer {
Tab tab;
};
// The TabStripService is an object that lives alongside the
// TabstripModel. It acts as the bridge between the model and any UI Dialog
// or client.
interface TabStripService {
// Gets the current state of the tab tree. This also returns a stream of
// future update events. Clients can implement the |TabsObserver| interface
// and receive all future updates from the snapshot. Note that all messages
// since the snapshot will be present in the stream, even if the client
// does not immediately register to the update stream.
[Sync]
GetTabs() => result<TabsSnapshot, mojo_base.mojom.Error>;
// Get a single tab.
[Sync]
GetTab(NodeId id) => result<Tab, mojo_base.mojom.Error>;
// Creates a new tab.
// Position specifies the location of the Tab after creation. If position is
// empty, the new tab will be appended to the end of the Tabstrip.
// Url specifies what is loaded in the Tab. If url is empty, then the new
// tab-page is loaded instead.
// The newly created tab is immediately activated.
[Sync]
CreateTabAt(Position? pos, url.mojom.Url? url)
=> result<Tab, mojo_base.mojom.Error>;
// Closes a list of tabs. The accepted tab types are content and collection
// types. All the provided IDs must exist. If an ID could not be found, the
// invocation will be rejected with a |Code.kNotFound| error.
// If the method call succeeds, all of the tabs will have been closed.
[Sync]
CloseTabs(array<NodeId> id)
=> result<mojo_base.mojom.Empty, mojo_base.mojom.Error>;
// Activates a tab. The only accepted id type for this method are |kContent|
// ids.
[Sync]
ActivateTab(NodeId id)
=> result<mojo_base.mojom.Empty, mojo_base.mojom.Error>;
// Moves a tab identified by id to a specified position.
[Sync]
MoveTab(NodeId id, Position position)
=> result<mojo_base.mojom.Empty, mojo_base.mojom.Error>;
};
// When a Tab is created, it also needs to know the position.
// Use this container to hold tab data as well as the position the tab was
// created in.
struct TabCreatedContainer {
Tab tab;
Position position;
};
struct OnTabsCreatedEvent {
// Tab ids of the newly created tabs.
array<TabCreatedContainer> tabs;
};
struct OnTabsClosedEvent {
// Tab ids of the closed tabs.
array<NodeId> tabs;
};
struct OnTabDataChangedEvent {
// Tab data of the updated tab. For now just apply a broad update rather than
// granular tab data.
Tab tab;
};
struct OnTabGroupCreatedEvent {
// The ID of the newly created group.
NodeId group_id;
// The visual data of the newly created group.
TabGroupVisualData visual_data;
// Position of the group in the tab strip.
Position position;
};
struct OnTabGroupVisualsChangedEvent {
// The ID of the group whose visuals have changed.
NodeId group_id;
// The new visual data of the group.
TabGroupVisualData visual_data;
};
struct OnTabMovedEvent {
// The id of the tab that moved.
NodeId id;
// The original position.
Position from;
// The new position.
Position to;
};
// TODO (crbug.com/412955607)
// TabsObserver is not a CheckedObserver. There is a potential UaF if the
// observer list attempts to call a destroyed TabsObserver that hasn't removed
// itself from the list.
interface TabsObserver {
// When new tabs have been created on the tab strip.
OnTabsCreated(OnTabsCreatedEvent event);
// When tabs have been closed on the tab strip.
OnTabsClosed(OnTabsClosedEvent event);
// When a tab has been moved.
OnTabMoved(OnTabMovedEvent event);
// When tab data has been updated.
OnTabDataChanged(OnTabDataChangedEvent tab);
// When a new tab group has been created.
OnTabGroupCreated(OnTabGroupCreatedEvent event);
// When a tab group's visuals have been changed.
OnTabGroupVisualsChanged(OnTabGroupVisualsChangedEvent event);
};
|