-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[Tree Tabs] Draft #31914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
[Tree Tabs] Draft #31914
Conversation
| tree_tabs_enabled_.Init( | ||
| brave_tabs::kTreeTabsEnabled, prefs, | ||
| base::BindRepeating(&BraveTabContainer::UpdateLayoutOrientation, | ||
| base::Unretained(this))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reported by reviewdog 🐶
[semgrep] base::Unretained is most of the time unrequited, and a weak reference is better suited for secure coding.
Consider swapping Unretained for a weak reference.
base::Unretained usage may be acceptable when a callback owner is guaranteed
to be destroyed with the object base::Unretained is pointing to, for example:
- PrefChangeRegistrar
- base::*Timer
- mojo::Receiver
- any other class member destroyed when the class is deallocated
Source: https://github.com/brave/security-action/blob/main/assets/semgrep_rules/client/chromium-uaf.yaml
Cc @thypon @goodov
| // Returns tree height that the `tab` at the given index belongs to. | ||
| int GetTreeHeightOfTab(int index) const; | ||
|
|
||
| // Returns tree node level of the `tab` at the given index. | ||
| int GetTreeNodeLevel(int index) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merge these into TreeTabVisual(int index) ?
| void BraveTabStripModel::BuildTreeTabs() { | ||
| CHECK(base::FeatureList::IsEnabled(tabs::features::kBraveTreeTab)); | ||
| CHECK(!in_tree_mode_); | ||
| CHECK(!contents_data()->in_tree_tab_mode()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we need TreeTabModel
| void set_use_vertical_tabs(bool vertical) { \ | ||
| use_vertical_tabs_ = vertical; \ | ||
| } \ | ||
| void set_tab_strip(TabStrip* tab_strip) { \ | ||
| tab_strip_ = tab_strip; \ | ||
| } \ | ||
| void set_use_tree_tabs(bool tree) { \ | ||
| use_tree_tabs_ = tree; \ | ||
| } \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a good ideal - having many conditionals would be painful
| void set_in_tree_tab_mode(bool in_tree_tab_mode) { | ||
| in_tree_tab_mode_ = in_tree_tab_mode; | ||
| } | ||
| bool in_tree_tab_mode() const { return in_tree_tab_mode_; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a good idea to have these here.
| void AddTabRecursive(std::unique_ptr<TabInterface> tab, | ||
| size_t index, | ||
| std::optional<tab_groups::TabGroupId> new_group_id, | ||
| bool new_pinned_state, | ||
| TabInterface* opener) override; | ||
| void MoveTabRecursive(size_t initial_index, | ||
| size_t final_index, | ||
| std::optional<tab_groups::TabGroupId> new_group_id, | ||
| bool new_pinned_state) override; | ||
| void MoveTabsRecursive( | ||
| const std::vector<int>& tab_indices, | ||
| size_t destination_index, | ||
| std::optional<tab_groups::TabGroupId> new_group_id, | ||
| bool new_pinned_state, | ||
| const std::set<TabCollection::Type>& retain_collection_types) override; | ||
| std::unique_ptr<TabInterface> RemoveTabAtIndexRecursive( | ||
| size_t index) override; | ||
| std::unique_ptr<TabInterface> RemoveTabRecursive( | ||
| TabInterface* tab, | ||
| bool close_empty_group_collection) override; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These only should route events to delegate or some other classes.
| // and insert it into target collection. The target collection can be another | ||
| // TreeTabNode in case new tab has opener relationship with the previous tab. | ||
| // Otherwise, the target collection can be anything but pinned collection. | ||
| class BraveTabStripCollection : public TabStripCollection { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, the responsibility of this class is to make a room for doing some actions in a certain evetns.
| if (delegate->IsNormalWindow()) { | ||
| tree_tabs_enabled_.Init( | ||
| brave_tabs::kTreeTabsEnabled, profile->GetPrefs(), | ||
| base::BindRepeating(&BraveTabStripModel::OnTreeTabRelatedPrefChanged, | ||
| base::Unretained(this))); | ||
| vertical_tabs_enabled_.Init( | ||
| brave_tabs::kVerticalTabsEnabled, profile->GetPrefs(), | ||
| base::BindRepeating(&BraveTabStripModel::OnTreeTabRelatedPrefChanged, | ||
| base::Unretained(this))); | ||
| OnTreeTabRelatedPrefChanged(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These also should be responsibility of other class.
This commit introduces core functionality for the Tree Tabs feature, enabling
tab creation and node wrapping capabilities when adding new tabs.
Key changes:
- Added tab creation logic with proper node wrapping in tree structure
- When adding a new tab with a opener tab and the opener tab is the
previous tab, the new tab's node will be set as a child of the opener
tab's node.
- In this way, we'll have a tree structure like below when we open
multiple tabs with the previous tab as opener sequentially:
```
- Tab 1
- Tab 2
- Tab 3
- Tab 4
```
This node will hold metadata about tree tab's node such as level and height.
860f6c6 to
c1bdd07
Compare
| base::BindRepeating(&TreeTabNode::OnWillDetach, base::Unretained(this))); | ||
| will_detach_tab_subscription_ = | ||
| current_tab_->RegisterWillDetach(base::BindRepeating( | ||
| &TreeTabNodeTabCollection::OnWillDetach, base::Unretained(this))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reported by reviewdog 🐶
[semgrep] base::Unretained is most of the time unrequited, and a weak reference is better suited for secure coding.
Consider swapping Unretained for a weak reference.
base::Unretained usage may be acceptable when a callback owner is guaranteed
to be destroyed with the object base::Unretained is pointing to, for example:
- PrefChangeRegistrar
- base::*Timer
- mojo::Receiver
- any other class member destroyed when the class is deallocated
Source: https://github.com/brave/security-action/blob/main/assets/semgrep_rules/client/chromium-uaf.yaml
Cc @thypon @goodov
|
|
||
| const TreeTabNodeTabCollection* TreeTabNodeTabCollection::GetTopLevelAncestor() | ||
| const { | ||
| return const_cast<TreeTabNodeTabCollection*>(this)->GetTopLevelAncestor(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reported by reviewdog 🐶
[semgrep] Avoid const_cast to remove const, except when implementing non-const getters in terms of const getters.
Source: https://github.com/brave/security-action/blob/main/assets/semgrep_rules/client/const_cast.yaml
Cc @bridiver @cdesouza-chromium
c1bdd07 to
22ce69c
Compare
Resolves