diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 937fd2422..d2a0e1a02 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -64,6 +64,7 @@ #include "chrome/browser/ssl/security_state_tab_helper.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h" #include "chrome/common/custom_handlers/protocol_handler.h" #include "components/autofill/content/browser/content_autofill_driver_factory.h" #include "components/autofill/core/browser/autofill_manager.h" @@ -1007,9 +1008,9 @@ void WebContents::TabPinnedStateChanged(TabStripModel* tab_strip_model, void WebContents::TabDetachedAt(content::WebContents* contents, int index) { if (contents != web_contents()) return; - if (owner_window() && owner_window()->browser()) owner_window()->browser()->tab_strip_model()->RemoveObserver(this); + Emit("tab-detached-at", index); } void WebContents::ActiveTabChanged(content::WebContents* old_contents, @@ -1024,6 +1025,49 @@ void WebContents::ActiveTabChanged(content::WebContents* old_contents, } } +void WebContents::TabInsertedAt(TabStripModel* tab_strip_model, + content::WebContents* contents, + int index, + bool foreground) { + if (contents != web_contents()) + return; + Emit("tab-inserted-at", index, foreground); +} + +void WebContents::TabMoved(content::WebContents* contents, + int from_index, + int to_index) { + if (contents != web_contents()) + return; + Emit("tab-moved", from_index, to_index); +} + +void WebContents::TabClosingAt(TabStripModel* tab_strip_model, + content::WebContents* contents, + int index) { + if (contents != web_contents()) + return; + Emit("tab-closing-at", index); +} + +void WebContents::TabChangedAt(content::WebContents* contents, + int index, + TabChangeType change_type) { + if (contents != web_contents()) + return; + Emit("tab-changed-at", index); +} + +void WebContents::TabStripEmpty() { + Emit("tab-strip-empty"); +} + +void WebContents::TabSelectionChanged(TabStripModel* tab_strip_model, + const ui::ListSelectionModel& old_model) { + Emit("tab-selection-changed"); +} + + bool WebContents::OnGoToEntryOffset(int offset) { GoToOffset(offset); return false; @@ -1344,11 +1388,9 @@ void WebContents::SetOwnerWindow(NativeWindow* new_owner_window) { if (owner_window() == new_owner_window) return; - if (IsGuest()) { - if (owner_window()) - owner_window()->browser()->tab_strip_model()->RemoveObserver(this); - new_owner_window->browser()->tab_strip_model()->AddObserver(this); - } + if (owner_window()) + owner_window()->browser()->tab_strip_model()->RemoveObserver(this); + new_owner_window->browser()->tab_strip_model()->AddObserver(this); SetOwnerWindow(web_contents(), new_owner_window); } @@ -2017,8 +2059,6 @@ void WebContents::SetTabIndex(int index) { if (tab_helper) tab_helper->SetTabIndex(index); #endif - - Emit("set-tab-index", index); } void WebContents::SetPinned(bool pinned) { @@ -2473,8 +2513,9 @@ void WebContents::OnRendererMessageSync(const base::string16& channel, EmitWithSender(base::UTF16ToUTF8(channel), web_contents(), message, args); } -void WebContents::OnRendererMessageShared(const base::string16& channel, - const base::SharedMemoryHandle& handle) { +void WebContents::OnRendererMessageShared( + const base::string16& channel, + const base::SharedMemoryHandle& handle) { std::vector> args = { mate::StringToV8(isolate(), channel), brave::SharedMemoryWrapper::CreateFrom(isolate(), handle).ToV8(), @@ -2565,25 +2606,35 @@ void WebContents::OnTabCreated(const mate::Dictionary& options, tab_helper->Discard(); } - int windowId = -1; - if (options.Get("windowId", &windowId) && windowId != -1) { + TabStripModel *tab_strip = nullptr; + int window_id = -1; + if (options.Get("windowId", &window_id) && window_id != -1) { auto api_window = - mate::TrackableObject::FromWeakMapID(isolate(), windowId); + mate::TrackableObject::FromWeakMapID(isolate(), window_id); if (api_window) { // TODO(bridiver) - combine these two methods - tab_helper->SetWindowId(windowId); + tab_helper->SetWindowId(window_id); tab_helper->SetBrowser(api_window->window()->browser()); + tab_strip = api_window->window()->browser()->tab_strip_model(); } } - int opener_tab_id = -1; + int opener_tab_id = TabStripModel::kNoTab; options.Get("openerTabId", &opener_tab_id); content::WebContents* source = nullptr; - if (opener_tab_id != -1) { + if (opener_tab_id != TabStripModel::kNoTab) { source = extensions::TabHelper::GetTabById(opener_tab_id); tab_helper->SetOpener(opener_tab_id); + if (!tab_strip) { + tab_strip = owner_window()->browser()->tab_strip_model(); + } + int index = tab_strip->order_controller()-> + DetermineInsertionIndex(ui::PAGE_TRANSITION_LINK, + active ? TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE); + tab_helper->SetTabIndex(index); } + if (!source) source = web_contents(); diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index ac881b605..1060068a1 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -340,6 +340,22 @@ class WebContents : public mate::TrackableObject, content::WebContents* new_contents, int index, int reason) override; + void TabInsertedAt(TabStripModel* tab_strip_model, + content::WebContents* contents, + int index, + bool foreground) override; + void TabMoved(content::WebContents* contents, + int from_index, + int to_index) override; + void TabClosingAt(TabStripModel* tab_strip_model, + content::WebContents* contents, + int index) override; + void TabChangedAt(content::WebContents* contents, + int index, + TabChangeType change_type) override; + void TabStripEmpty() override; + void TabSelectionChanged(TabStripModel* tab_strip_model, + const ui::ListSelectionModel& old_model) override; // content::WebContentsDelegate: void RegisterProtocolHandler(content::WebContents* web_contents, diff --git a/atom/browser/extensions/tab_helper.cc b/atom/browser/extensions/tab_helper.cc index fe32715fb..26e4aed28 100644 --- a/atom/browser/extensions/tab_helper.cc +++ b/atom/browser/extensions/tab_helper.cc @@ -158,7 +158,7 @@ int TabHelper::GetTabStripIndex(int window_id, int index) { if (tab_helper && tab_helper->get_index() == index && tab_helper->window_id() == window_id) - return tab_helper->get_tab_strip_index(); + return tab_helper->get_index(); } return TabStripModel::kNoTab; } @@ -187,7 +187,7 @@ content::WebContents* TabHelper::DetachGuest() { web_contents()->GetController()); auto null_helper = FromWebContents(null_contents); - null_helper->index_ = index_; + null_helper->index_ = get_index(); null_helper->pinned_ = pinned_; // transfer window closing state null_helper->window_closing_ = window_closing_; @@ -197,7 +197,7 @@ content::WebContents* TabHelper::DetachGuest() { // Replace the detached tab with the null placeholder browser_->tab_strip_model()->ReplaceWebContentsAt( - get_tab_strip_index(), null_contents); + get_index(), null_contents); return null_contents; } @@ -208,7 +208,7 @@ void TabHelper::DidAttach() { MaybeRequestWindowClose(); if (active_) { - browser_->tab_strip_model()->ActivateTabAt(get_tab_strip_index(), true); + browser_->tab_strip_model()->ActivateTabAt(get_index(), true); active_ = false; } if (is_placeholder()) { @@ -284,7 +284,7 @@ void TabHelper::MaybeAttachOrCreatePinnedTab() { // content::WebContents* pinned_web_contents = nullptr; // for (auto* browser : *BrowserList::GetInstance()) { // auto web_contents = - // browser->tab_strip_model()->GetWebContentsAt(get_tab_strip_index()); + // browser->tab_strip_model()->GetWebContentsAt(get_index()); // if (web_contents) { // auto tab_helper = FromWebContents(web_contents); // if (!tab_helper->is_placeholder()) { @@ -296,7 +296,7 @@ void TabHelper::MaybeAttachOrCreatePinnedTab() { // } // if (pinned_web_contents) { - // browser_->tab_strip_model()->ReplaceWebContentsAt(get_tab_strip_index(), + // browser_->tab_strip_model()->ReplaceWebContentsAt(get_index(), // pinned_web_contents); // } else { SetPlaceholder(false); @@ -318,8 +318,9 @@ void TabHelper::TabReplacedAt(TabStripModel* tab_strip_model, int guest_instance_id = old_guest->guest_instance_id(); auto new_helper = FromWebContents(new_contents); - new_helper->index_ = index_; + new_helper->index_ = get_index(); new_helper->pinned_ = pinned_; + new_helper->opener_tab_id_ = opener_tab_id_; OnBrowserRemoved(old_browser); new_helper->UpdateBrowser(old_browser); @@ -360,8 +361,8 @@ void TabHelper::SetActive(bool active) { SetAutoDiscardable(true); } - if (browser_ && index_ != TabStripModel::kNoTab) { - browser_->tab_strip_model()->ActivateTabAt(get_tab_strip_index(), true); + if (browser_) { + browser_->tab_strip_model()->ActivateTabAt(get_index(), true); if (!IsDiscarded()) { web_contents()->WasShown(); } @@ -401,15 +402,29 @@ void TabHelper::SetBrowser(Browser* browser) { return; if (browser_) { - if (get_tab_strip_index() != TabStripModel::kNoTab) - browser_->tab_strip_model()->DetachWebContentsAt(get_tab_strip_index()); + if (get_index() != TabStripModel::kNoTab) + browser_->tab_strip_model()->DetachWebContentsAt(get_index()); OnBrowserRemoved(browser_); } if (browser) { UpdateBrowser(browser); - browser_->tab_strip_model()->AppendWebContents(web_contents(), false); + if (opener_tab_id_ != TabStripModel::kNoTab && browser->tab_strip_model()) { + auto tab_strip = browser->tab_strip_model(); + } + + if (index_ == TabStripModel::kNoTab || + index_ > browser_->tab_strip_model()->count()) { + index_ = browser_->tab_strip_model()->count(); + } + + int add_types = TabStripModel::ADD_NONE; + add_types |= active_ ? TabStripModel::ADD_ACTIVE : 0; + add_types |= opener_tab_id_ != TabStripModel::kNoTab ? + TabStripModel::ADD_INHERIT_OPENER : 0; + browser_->tab_strip_model()->InsertWebContentsAt( + index_, web_contents(), add_types); } else { browser_ = nullptr; } @@ -461,7 +476,7 @@ void TabHelper::SetPinned(bool pinned) { pinned_ = pinned; if (browser()) { - browser()->tab_strip_model()->SetTabPinned(get_tab_strip_index(), pinned); + browser()->tab_strip_model()->SetTabPinned(get_index(), pinned); } if (pinned_) { @@ -477,12 +492,16 @@ bool TabHelper::IsPinned() const { void TabHelper::SetTabIndex(int index) { index_ = index; + if (browser()) { + browser()->tab_strip_model()->MoveWebContentsAt( + get_index(), index, false); + } } bool TabHelper::is_active() const { if (browser()) { - return browser()->tab_strip_model()-> - GetActiveWebContents() == web_contents(); + return browser()->tab_strip_model()->GetActiveWebContents()== + web_contents(); } else { return active_; } @@ -498,8 +517,8 @@ void TabHelper::SetTabValues(const base::DictionaryValue& values) { values_->MergeDictionary(&values); } -void TabHelper::SetOpener(int openerTabId) { - opener_tab_id_ = openerTabId; +void TabHelper::SetOpener(int opener_tab_id) { + opener_tab_id_ = opener_tab_id; } void TabHelper::RenderViewCreated(content::RenderViewHost* render_view_host) { @@ -680,11 +699,11 @@ void TabHelper::ExecuteScript( callback); } -int TabHelper::get_tab_strip_index() const { +int TabHelper::get_index() const { if (browser()) return browser()->tab_strip_model()->GetIndexOfWebContents(web_contents()); - return TabStripModel::kNoTab; + return index_; } // static diff --git a/atom/browser/extensions/tab_helper.h b/atom/browser/extensions/tab_helper.h index 6d1449ea9..fdf626a86 100644 --- a/atom/browser/extensions/tab_helper.h +++ b/atom/browser/extensions/tab_helper.h @@ -120,7 +120,7 @@ class TabHelper : public content::WebContentsObserver, brave::TabViewGuest* guest() const; - int get_index() const { return index_; } + int get_index() const; bool is_pinned() const { return pinned_; } bool is_active() const; @@ -157,7 +157,6 @@ class TabHelper : public content::WebContentsObserver, void TabPinnedStateChanged(TabStripModel* tab_strip_model, content::WebContents* contents, int index) override; - int get_tab_strip_index() const; void OnBrowserRemoved(Browser* browser) override; void OnBrowserSetLastActive(Browser* browser) override; diff --git a/brave/browser/BUILD.gn b/brave/browser/BUILD.gn index 3d70fdda2..817acbf11 100644 --- a/brave/browser/BUILD.gn +++ b/brave/browser/BUILD.gn @@ -149,6 +149,7 @@ source_set("apis") { "api/navigation_controller.h", "api/navigation_handle.cc", "api/navigation_handle.h", + "ui/brave_tab_strip_model_delegate.cc", ] deps = [ diff --git a/brave/browser/ui/brave_tab_strip_model_delegate.cc b/brave/browser/ui/brave_tab_strip_model_delegate.cc new file mode 100644 index 000000000..ee6eb656d --- /dev/null +++ b/brave/browser/ui/brave_tab_strip_model_delegate.cc @@ -0,0 +1,99 @@ +// Copyright (c) 2016 Brave Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "brave/browser/ui/brave_tab_strip_model_delegate.h" + +namespace brave { + +//////////////////////////////////////////////////////////////////////////////// +// BraveTabStripModelDelegate, public: + +BraveTabStripModelDelegate::BraveTabStripModelDelegate() { +} + +BraveTabStripModelDelegate::~BraveTabStripModelDelegate() { +} + +//////////////////////////////////////////////////////////////////////////////// +// BraveTabStripModelDelegate, TabStripModelDelegate implementation: + +void BraveTabStripModelDelegate::AddTabAt(const GURL& url, + int index, + bool foreground) { + // TODO(bbondy) +} + +Browser* BraveTabStripModelDelegate::CreateNewStripWithContents( + const std::vector& contentses, + const gfx::Rect& window_bounds, + bool maximize) { + // TODO(bbondy) + // This is only used from chrome/browser/ui/views/tabs/tab_drag_controller.cc + // which we don't use. + return nullptr; +} + +void BraveTabStripModelDelegate::WillAddWebContents( + content::WebContents* contents) { + // TODO(bbondy) +} + +int BraveTabStripModelDelegate::GetDragActions() const { + // TODO(bbondy) + return TabStripModelDelegate::TAB_MOVE_ACTION; +} + +bool BraveTabStripModelDelegate::CanDuplicateContentsAt(int index) { + // TODO(bbondy) + return false; +} + +void BraveTabStripModelDelegate::DuplicateContentsAt(int index) { + // TODO(bbondy) +} + +void BraveTabStripModelDelegate::CreateHistoricalTab( + content::WebContents* contents) { + // TODO(bbondy) +} + +bool BraveTabStripModelDelegate::RunUnloadListenerBeforeClosing( + content::WebContents* contents) { + // TODO(bbondy) + return false; +} + +bool BraveTabStripModelDelegate::ShouldRunUnloadListenerBeforeClosing( + content::WebContents* contents) { + // TODO(bbondy) + return false; +} + +bool BraveTabStripModelDelegate::CanBookmarkAllTabs() const { + // TODO(bbondy) + return false; +} + +void BraveTabStripModelDelegate::BookmarkAllTabs() { + // TODO(bbondy) +} + +TabStripModelDelegate::RestoreTabType +BraveTabStripModelDelegate::GetRestoreTabType() { + // TODO(bbondy) + return TabStripModelDelegate::RESTORE_NONE; +} + +void BraveTabStripModelDelegate::RestoreTab() { + // TODO(bbondy) +} + +//////////////////////////////////////////////////////////////////////////////// +// BraveTabStripModelDelegate, private: + +void BraveTabStripModelDelegate::CloseFrame() { + // TODO(bbondy) +} + +} // namespace brave diff --git a/brave/browser/ui/brave_tab_strip_model_delegate.h b/brave/browser/ui/brave_tab_strip_model_delegate.h new file mode 100644 index 000000000..00d6190e9 --- /dev/null +++ b/brave/browser/ui/brave_tab_strip_model_delegate.h @@ -0,0 +1,49 @@ +// Copyright (c) 2016 Brave Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BRAVE_BROWSER_UI_BRAVE_TAB_STRIP_MODEL_DELEGATE_H_ +#define BRAVE_BROWSER_UI_BRAVE_TAB_STRIP_MODEL_DELEGATE_H_ + +#include + +#include "base/macros.h" +#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" + +class GURL; + +namespace brave { + +class BraveTabStripModelDelegate : public TabStripModelDelegate { + public: + BraveTabStripModelDelegate(); + ~BraveTabStripModelDelegate() override; + + private: + // Overridden from TabStripModelDelegate: + void AddTabAt(const GURL& url, int index, bool foreground) override; + Browser* CreateNewStripWithContents( + const std::vector& contentses, + const gfx::Rect& window_bounds, + bool maximize) override; + void WillAddWebContents(content::WebContents* contents) override; + int GetDragActions() const override; + bool CanDuplicateContentsAt(int index) override; + void DuplicateContentsAt(int index) override; + void CreateHistoricalTab(content::WebContents* contents) override; + bool RunUnloadListenerBeforeClosing(content::WebContents* contents) override; + bool ShouldRunUnloadListenerBeforeClosing( + content::WebContents* contents) override; + bool CanBookmarkAllTabs() const override; + void BookmarkAllTabs() override; + RestoreTabType GetRestoreTabType() override; + void RestoreTab() override; + + void CloseFrame(); + + DISALLOW_COPY_AND_ASSIGN(BraveTabStripModelDelegate); +}; + +} // namespace brave + +#endif // BRAVE_BROWSER_UI_BRAVE_TAB_STRIP_MODEL_DELEGATE_H_ diff --git a/chromium_src/BUILD.gn b/chromium_src/BUILD.gn index bcc77e016..9554497ae 100644 --- a/chromium_src/BUILD.gn +++ b/chromium_src/BUILD.gn @@ -185,6 +185,8 @@ source_set("browser") { "chrome/browser/ui/profile_error_dialog.cc", + "//chrome/browser/ui/web_contents_sizer.cc", + "//chrome/browser/ui/web_contents_sizer.h", "chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc", "//chrome/browser/ui/webui/chrome_web_ui_controller_factory.h", @@ -788,9 +790,13 @@ source_set("tab_manager") { "//chrome/browser/memory_details_win.cc", "//chrome/browser/ui/browser_tab_strip_tracker.cc", "//chrome/browser/ui/browser_tab_strip_tracker.h", - "chrome/browser/ui/tabs/tab_strip_model.cc", + "//chrome/browser/ui/tabs/tab_strip_model.cc", + "//chrome/browser/ui/tabs/tab_strip_model.h", + "//chrome/browser/ui/tabs/tab_strip_model_delegate.h", "//chrome/browser/ui/tabs/tab_strip_model_observer.cc", "//chrome/browser/ui/tabs/tab_strip_model_observer.h", + "//chrome/browser/ui/tabs/tab_strip_model_order_controller.cc", + "//chrome/browser/ui/tabs/tab_strip_model_order_controller.h", "//chrome/browser/ui/tab_contents/tab_contents_iterator.cc", "//chrome/browser/ui/tab_contents/tab_contents_iterator.h", ] diff --git a/chromium_src/chrome/browser/extensions/extension_tab_util.cc b/chromium_src/chrome/browser/extensions/extension_tab_util.cc index 98ff6d62f..21c884ce2 100644 --- a/chromium_src/chrome/browser/extensions/extension_tab_util.cc +++ b/chromium_src/chrome/browser/extensions/extension_tab_util.cc @@ -162,7 +162,7 @@ std::unique_ptr ExtensionTabUtil::CreateTabObject( tab_object->window_id = GetWindowIdOfTab(contents); tab_object->status.reset(new std::string(GetTabStatusText(is_loading))); tab_object->active = tab_helper->is_active(); - tab_object->selected = tab_helper->is_active(); + tab_object->selected = tab_object->active; tab_object->highlighted = tab_strip && tab_strip->IsTabSelected(tab_index); tab_object->pinned = tab_helper->is_pinned(); tab_object->audible.reset(new bool(contents->WasRecentlyAudible())); diff --git a/chromium_src/chrome/browser/ui/browser.cc b/chromium_src/chrome/browser/ui/browser.cc index ccca19dfa..20cbaf013 100644 --- a/chromium_src/chrome/browser/ui/browser.cc +++ b/chromium_src/chrome/browser/ui/browser.cc @@ -11,6 +11,7 @@ #include #include "atom/browser/native_window.h" +#include "brave/browser/ui/brave_tab_strip_model_delegate.h" #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/devtools/devtools_window.h" @@ -43,8 +44,10 @@ Browser::Browser(const CreateParams& params) : type_(params.type), profile_(params.profile), window_(params.window), + tab_strip_model_delegate_(new brave::BraveTabStripModelDelegate()), tab_strip_model_( - new TabStripModel(nullptr, params.profile)), + new TabStripModel(tab_strip_model_delegate_.get(), + params.profile)), app_name_(params.app_name), is_trusted_source_(params.trusted_source), initial_show_state_(params.initial_show_state), diff --git a/chromium_src/chrome/browser/ui/browser.h b/chromium_src/chrome/browser/ui/browser.h index abde8cd04..9876aa081 100644 --- a/chromium_src/chrome/browser/ui/browser.h +++ b/chromium_src/chrome/browser/ui/browser.h @@ -213,7 +213,7 @@ class Browser : public content::WebContentsDelegate { // This Browser's window. BrowserWindow* window_; - // std::unique_ptr tab_strip_model_delegate_; + std::unique_ptr tab_strip_model_delegate_; std::unique_ptr tab_strip_model_; // The application name that is also the name of the window to the shell. diff --git a/chromium_src/chrome/browser/ui/tabs/tab_strip_model.cc b/chromium_src/chrome/browser/ui/tabs/tab_strip_model.cc deleted file mode 100644 index 82e0296c0..000000000 --- a/chromium_src/chrome/browser/ui/tabs/tab_strip_model.cc +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include "chrome/browser/ui/tabs/tab_strip_model.h" - -#include "atom/browser/extensions/tab_helper.h" -#include "base/memory/ptr_util.h" -#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" -#include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" -#include "ui/base/models/list_selection_model.h" - -using content::WebContents; -using extensions::TabHelper; - -/////////////////////////////////////////////////////////////////////////////// -// WebContentsData - -// An object to hold a reference to a WebContents that is in a tabstrip, as -// well as other various properties it has. -class TabStripModel::WebContentsData : public content::WebContentsObserver { - public: - WebContentsData(WebContents* a_contents); - - // Changes the WebContents that this WebContentsData tracks. - void SetWebContents(WebContents* contents); - - WebContents* opener() const { return opener_; } - void set_opener(WebContents* value) { opener_ = value; } - - private: - WebContents* opener_; - - DISALLOW_COPY_AND_ASSIGN(WebContentsData); -}; - -TabStripModel::WebContentsData::WebContentsData(WebContents* contents) - : content::WebContentsObserver(contents), - opener_(nullptr) {} - -void TabStripModel::WebContentsData::SetWebContents(WebContents* contents) { - Observe(contents); -} - -/////////////////////////////////////////////////////////////////////////////// -// TabStripModel, public: -TabStripModel::TabStripModel(TabStripModelDelegate* delegate, Profile* profile) - : delegate_(delegate), - profile_(profile), - closing_all_(false), - in_notify_(false), - weak_factory_(this) { - DCHECK(!delegate_); -} - -TabStripModel::~TabStripModel() { - contents_data_.clear(); -} - -void TabStripModel::AddObserver(TabStripModelObserver* observer) { - observers_.AddObserver(observer); -} - -void TabStripModel::RemoveObserver(TabStripModelObserver* observer) { - observers_.RemoveObserver(observer); -} - -bool TabStripModel::ContainsIndex(int index) const { - return index >= 0 && index < count(); -} - -void TabStripModel::AppendWebContents(WebContents* contents, - bool foreground) { - // delegate_->WillAddWebContents(contents); - std::unique_ptr data = - base::MakeUnique(contents); - - int index = contents_data_.size(); - contents_data_.push_back(std::move(data)); - for (auto& observer : observers_) - observer.TabInsertedAt(this, contents, index, foreground); -} - -WebContents* TabStripModel::ReplaceWebContentsAt(int index, - WebContents* new_contents) { - // delegate_->WillAddWebContents(new_contents); - - DCHECK(ContainsIndex(index)); - WebContents* old_contents = GetWebContentsAt(index); - - for (size_t i = 0; i < contents_data_.size(); ++i) { - if (contents_data_[i]->web_contents() == old_contents) { - contents_data_[i]->SetWebContents(new_contents); - break; - } - } - - for (auto& observer : observers_) - observer.TabReplacedAt(this, old_contents, new_contents, index); - - // When the active WebContents is replaced send out a selection notification - // too. We do this as nearly all observers need to treat a replacement of the - // selected contents as the selection changing. - // TODO(bridiver) - listen for this event and actually swap them - if (active_index() == index) { - for (auto& observer : observers_) - observer.ActiveTabChanged(old_contents, new_contents, active_index(), - TabStripModelObserver::CHANGE_REASON_REPLACED); - } - return old_contents; -} - -WebContents* TabStripModel::DetachWebContentsAt(int index) { - CHECK(!in_notify_); - if (contents_data_.empty()) - return nullptr; - DCHECK(ContainsIndex(index)); - - WebContents* removed_contents = GetWebContentsAt(index); - - for (size_t i = 0; i < contents_data_.size(); ++i) { - if (contents_data_[i]->web_contents() == removed_contents) { - contents_data_.erase(contents_data_.begin() + i); - break; - } - } - - for (auto& observer : observers_) - observer.TabDetachedAt(removed_contents, index); - - if (active_index() == index) { - ui::ListSelectionModel new_model; - new_model.Copy(selection_model_); - new_model.SetSelectedIndex(kNoTab); - selection_model_.Copy(new_model); - } - - if (empty()) { - selection_model_.Clear(); - // TabDetachedAt() might unregister observers, so send |TabStripEmpty()| in - // a second pass. - for (auto& observer : observers_) - observer.TabStripEmpty(); - } - return removed_contents; -} - -void TabStripModel::ActivateTabAt(int index, bool user_gesture) { - DCHECK(ContainsIndex(index)); - ui::ListSelectionModel new_model; - new_model.Copy(selection_model_); - new_model.SetSelectedIndex(index); - SetSelection(new_model, user_gesture ? NOTIFY_USER_GESTURE : NOTIFY_DEFAULT); -} - -WebContents* TabStripModel::GetActiveWebContents() const { - return GetWebContentsAt(active_index()); -} - -WebContents* TabStripModel::GetWebContentsAt(int index) const { - if (index != kNoTab && index < (int)contents_data_.size()) - return contents_data_[index]->web_contents(); - return nullptr; -} - -int TabStripModel::GetIndexOfWebContents(const WebContents* contents) const { - for (size_t i = 0; i < contents_data_.size(); ++i) { - if (contents_data_[i]->web_contents() == contents) - return i; - } - return kNoTab; -} - -void TabStripModel::SetTabPinned(int index, bool pinned) { - DCHECK(ContainsIndex(index)); - - auto tab_helper = TabHelper::FromWebContents(GetWebContentsAt(index)); - DCHECK(tab_helper); - - if (pinned != tab_helper->is_pinned()) - tab_helper->SetPinned(pinned); - - for (auto& observer : observers_) - observer.TabPinnedStateChanged(this, tab_helper->web_contents(), - index); -} - -bool TabStripModel::IsTabPinned(int index) const { - if (!ContainsIndex(index)) - return false; - - auto tab_helper = TabHelper::FromWebContents(GetWebContentsAt(index)); - DCHECK(tab_helper); - - return tab_helper->is_pinned(); -} - -bool TabStripModel::IsTabSelected(int index) const { - if (!ContainsIndex(index)) - return false; - - return selection_model_.IsSelected(index); -} - -void TabStripModel::NotifyIfTabDeactivated(WebContents* contents) { - if (contents) { - for (auto& observer : observers_) - observer.TabDeactivated(contents); - } -} - -void TabStripModel::NotifyIfActiveTabChanged(WebContents* old_contents, - NotifyTypes notify_types) { - WebContents* new_contents = GetWebContentsAt(active_index()); - if (old_contents != new_contents) { - int reason = notify_types == NOTIFY_USER_GESTURE - ? TabStripModelObserver::CHANGE_REASON_USER_GESTURE - : TabStripModelObserver::CHANGE_REASON_NONE; - CHECK(!in_notify_); - in_notify_ = true; - for (auto& observer : observers_) - observer.ActiveTabChanged(old_contents, new_contents, active_index(), - reason); - in_notify_ = false; - } -} - -void TabStripModel::NotifyIfActiveOrSelectionChanged( - WebContents* old_contents, - NotifyTypes notify_types, - const ui::ListSelectionModel& old_model) { - NotifyIfActiveTabChanged(old_contents, notify_types); - - if (!selection_model().Equals(old_model)) { - for (auto& observer : observers_) - observer.TabSelectionChanged(this, old_model); - } -} - -void TabStripModel::SetSelection( - const ui::ListSelectionModel& new_model, - NotifyTypes notify_types) { - WebContents* old_contents = GetActiveWebContents(); - ui::ListSelectionModel old_model; - old_model.Copy(selection_model_); - if (new_model.active() != selection_model_.active()) - NotifyIfTabDeactivated(old_contents); - selection_model_.Copy(new_model); - NotifyIfActiveOrSelectionChanged(old_contents, notify_types, old_model); -} - -WebContents* TabStripModel::GetOpenerOfWebContentsAt(int index) { - DCHECK(ContainsIndex(index)); - return contents_data_[index]->opener(); -} - -void TabStripModel::SetOpenerOfWebContentsAt(int index, - WebContents* opener) { - DCHECK(ContainsIndex(index)); - DCHECK(opener); - contents_data_[index]->set_opener(opener); -} - diff --git a/lib/browser/api/extensions.js b/lib/browser/api/extensions.js index 8168376d6..d4353c572 100644 --- a/lib/browser/api/extensions.js +++ b/lib/browser/api/extensions.js @@ -424,8 +424,23 @@ app.on('web-contents-created', function (event, tab) { tab.on('set-active', function (evt, active) { chromeTabsUpdated(tabId) // immediate }) - tab.on('set-tab-index', function (evt, index) { - chromeTabsUpdated(tabId) + tab.on('tab-inserted-at', function (evt, index, foreground) { + chromeTabsUpdated(tabId) // immediate + }) + tab.on('tab-changed-at', function (evt, index) { + chromeTabsUpdated(tabId) // immediate + }) + tab.on('tab-moved', function (evt, fromIndex, toIndex) { + chromeTabsUpdated(tabId) // immediate + }) + tab.on('tab-selection-changed', function (evt) { + chromeTabsUpdated(tabId) // immediate + }) + tab.on('tab-closing-at', function (evt, index) { + chromeTabsUpdated(tabId) // immediate + }) + tab.on('tab-detached-at', function (evt, index) { + chromeTabsUpdated(tabId) // immediate }) tab.on('will-destroy', function () { chromeTabsRemoved(tabId)