blob: 9588ad0e4437d96b3dd21273f574e28704a16178 [file] [log] [blame]
// Copyright 2020 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.
#import "ios/chrome/browser/main/browser_util.h"
#include <memory>
#include <ostream>
#include <set>
#include "base/check_op.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/main/browser.h"
#import "ios/chrome/browser/main/browser_list.h"
#import "ios/chrome/browser/main/browser_list_factory.h"
#import "ios/chrome/browser/snapshots/snapshot_browser_agent.h"
#import "ios/chrome/browser/snapshots/snapshot_cache.h"
#import "ios/chrome/browser/web/tab_id_tab_helper.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Given a set of |browsers|, finds the one with |tab_id|. Returns the browser
// and |tab_index| of the tab within the returned browser’s WebStateList.
Browser* FindBrowser(NSString* tab_id,
const std::set<Browser*>& browsers,
int& tab_index) {
for (Browser* browser : browsers) {
WebStateList* web_state_list = browser->GetWebStateList();
for (int i = 0; i < web_state_list->count(); ++i) {
web::WebState* web_state = web_state_list->GetWebStateAt(i);
NSString* current_tab_id =
TabIdTabHelper::FromWebState(web_state)->tab_id();
if ([current_tab_id isEqualToString:tab_id]) {
tab_index = i;
return browser;
}
}
}
tab_index = WebStateList::kInvalidIndex;
return nil;
}
// Finds the browser in |browser_list| containing a tab with |tab_id|. Searches
// incognito browsers if |incognito| is true, otherwise searches regular
// browsers. Returns the browser and |tab_index| of the tab within the returned
// browser's WebStateList.
Browser* FindBrowser(NSString* tab_id,
BrowserList* browser_list,
bool incognito,
int& tab_index) {
return incognito ? FindBrowser(tab_id, browser_list->AllIncognitoBrowsers(),
tab_index)
: FindBrowser(tab_id, browser_list->AllRegularBrowsers(),
tab_index);
}
// Moves snapshot associated with |snapshot_id| from |source_browser| to
// |destination_browser|'s snapshot cache.
void MoveSnapshot(NSString* snapshot_id,
Browser* source_browser,
Browser* destination_browser) {
DCHECK(snapshot_id.length);
SnapshotCache* source_cache =
SnapshotBrowserAgent::FromBrowser(source_browser)->snapshot_cache();
SnapshotCache* destination_cache =
SnapshotBrowserAgent::FromBrowser(destination_browser)->snapshot_cache();
[source_cache
retrieveImageForSnapshotID:snapshot_id
callback:^(UIImage* snapshot) {
if (snapshot) {
[destination_cache setImage:snapshot
withSnapshotID:snapshot_id];
[source_cache
removeImageWithSnapshotID:snapshot_id];
}
}];
}
} // namespace
void MoveTabToBrowser(NSString* tab_id,
Browser* destination_browser,
int destination_tab_index) {
DCHECK(tab_id.length);
ChromeBrowserState* browser_state = destination_browser->GetBrowserState();
BrowserList* browser_list =
BrowserListFactory::GetForBrowserState(browser_state);
int source_tab_index = WebStateList::kInvalidIndex;
Browser* source_browser = FindBrowser(
tab_id, browser_list, browser_state->IsOffTheRecord(), source_tab_index);
if (!source_browser) {
NOTREACHED() << "Either the tab_id is incorrect, or the user is attempting "
"to move a tab across profiles (incognito <-> regular)";
return;
}
if (source_browser == destination_browser) {
// This is a reorder operation within the same WebStateList.
destination_browser->GetWebStateList()->MoveWebStateAt(
source_tab_index, destination_tab_index);
return;
}
MoveSnapshot(tab_id, source_browser, destination_browser);
std::unique_ptr<web::WebState> web_state =
source_browser->GetWebStateList()->DetachWebStateAt(source_tab_index);
int insertion_flags = WebStateList::INSERT_FORCE_INDEX;
if (destination_browser->GetWebStateList()->empty()) {
insertion_flags = WebStateList::INSERT_ACTIVATE;
}
destination_browser->GetWebStateList()->InsertWebState(
destination_tab_index, std::move(web_state), insertion_flags,
WebStateOpener());
}