| // 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. |
| |
| #import "ios/chrome/browser/tabs/model/tab_pickup/tab_pickup_infobar_delegate.h" |
| |
| #import "base/functional/bind.h" |
| #import "base/functional/callback_helpers.h" |
| #import "base/metrics/histogram_functions.h" |
| #import "components/infobars/core/infobar_delegate.h" |
| #import "components/sync_sessions/open_tabs_ui_delegate.h" |
| #import "components/sync_sessions/session_sync_service.h" |
| #import "ios/chrome/browser/favicon/model/favicon_loader.h" |
| #import "ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h" |
| #import "ios/chrome/browser/metrics/model/new_tab_page_uma.h" |
| #import "ios/chrome/browser/sessions/session_util.h" |
| #import "ios/chrome/browser/shared/model/browser/browser.h" |
| #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" |
| #import "ios/chrome/browser/shared/model/url/chrome_url_constants.h" |
| #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" |
| #import "ios/chrome/browser/shared/model/web_state_list/web_state_opener.h" |
| #import "ios/chrome/browser/sync/model/session_sync_service_factory.h" |
| #import "ios/chrome/browser/synced_sessions/model/distant_session.h" |
| #import "ios/chrome/browser/synced_sessions/model/distant_tab.h" |
| #import "ios/chrome/browser/synced_sessions/model/synced_sessions.h" |
| #import "ios/chrome/browser/tabs/model/tab_pickup/features.h" |
| #import "ios/chrome/common/ui/favicon/favicon_attributes.h" |
| #import "ios/chrome/common/ui/favicon/favicon_constants.h" |
| #import "ios/web/public/web_state.h" |
| |
| TabPickupInfobarDelegate::TabPickupInfobarDelegate( |
| Browser* browser, |
| const synced_sessions::DistantSession* session, |
| const synced_sessions::DistantTab* tab) |
| : browser_(browser) { |
| CHECK(IsTabPickupEnabled()); |
| CHECK(!IsTabPickupDisabledByUser()); |
| |
| favicon_loader_ = IOSChromeFaviconLoaderFactory::GetForBrowserState( |
| browser_->GetBrowserState()); |
| |
| session_name_ = session->name; |
| synced_time_ = session->modified_time; |
| tab_url_ = tab->virtual_url; |
| tab_id_ = tab->tab_id; |
| session_tag_ = tab->session_tag; |
| } |
| |
| TabPickupInfobarDelegate::~TabPickupInfobarDelegate() = default; |
| |
| #pragma mark - Public methods |
| |
| void TabPickupInfobarDelegate::FetchFavIconImage( |
| ProceduralBlock block_handler) { |
| if (!IsTabPickupFaviconAvaible()) { |
| block_handler(); |
| return; |
| } |
| favicon_loader_->FaviconForPageUrl( |
| tab_url_, kDesiredSmallFaviconSizePt, kMinFaviconSizePt, |
| /*fallback_to_google_server=*/true, |
| base::CallbackToBlock( |
| base::BindRepeating(&TabPickupInfobarDelegate::FaviconFetched, |
| weak_factory_.GetWeakPtr(), block_handler))); |
| } |
| |
| void TabPickupInfobarDelegate::OpenDistantTab() { |
| ChromeBrowserState* browser_state = browser_->GetBrowserState(); |
| WebStateList* web_state_list = browser_->GetWebStateList(); |
| |
| sync_sessions::OpenTabsUIDelegate* open_tabs_delegate = |
| SessionSyncServiceFactory::GetForBrowserState(browser_state) |
| ->GetOpenTabsUIDelegate(); |
| |
| const sessions::SessionTab* session_tab = nullptr; |
| if (open_tabs_delegate->GetForeignTab(session_tag_, tab_id_, &session_tab)) { |
| base::TimeDelta time_since_last_use = base::Time::Now() - synced_time_; |
| base::UmaHistogramCustomTimes("IOS.DistantTab.TimeSinceLastUse", |
| time_since_last_use, base::Minutes(1), |
| base::Days(24), 50); |
| base::UmaHistogramCustomTimes("IOS.TabPickup.TabOpened.TimeSinceLastUse", |
| time_since_last_use, base::Minutes(1), |
| base::Days(24), 50); |
| |
| bool is_ntp = web_state_list->GetActiveWebState()->GetVisibleURL() == |
| kChromeUINewTabURL; |
| new_tab_page_uma::RecordNTPAction( |
| browser_state->IsOffTheRecord(), is_ntp, |
| new_tab_page_uma::ACTION_OPENED_FOREIGN_SESSION); |
| |
| std::unique_ptr<web::WebState> web_state = |
| session_util::CreateWebStateWithNavigationEntries( |
| browser_state, session_tab->current_navigation_index, |
| session_tab->navigations); |
| web_state_list->InsertWebState( |
| std::move(web_state), |
| WebStateList::InsertionParams::AtIndex(web_state_list->count()) |
| .Activate()); |
| } |
| } |
| |
| #pragma mark - ConfirmInfoBarDelegate methods |
| |
| // Returns an empty message to satisfy implementation requirement for |
| // ConfirmInfoBarDelegate. |
| std::u16string TabPickupInfobarDelegate::GetMessageText() const { |
| return std::u16string(); |
| } |
| |
| infobars::InfoBarDelegate::InfoBarIdentifier |
| TabPickupInfobarDelegate::GetIdentifier() const { |
| return TAB_PICKUP_INFOBAR_DELEGATE; |
| } |
| |
| bool TabPickupInfobarDelegate::EqualsDelegate( |
| infobars::InfoBarDelegate* delegate) const { |
| return delegate->GetIdentifier() == GetIdentifier(); |
| } |
| |
| #pragma mark - Private methods |
| |
| void TabPickupInfobarDelegate::FaviconFetched(ProceduralBlock block_handler, |
| FaviconAttributes* attributes) { |
| DCHECK(block_handler); |
| if (!attributes.usesDefaultImage) { |
| favicon_image_ = attributes.faviconImage; |
| block_handler(); |
| } |
| } |