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
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/autocomplete/tab_matcher_desktop.h"
#include "base/feature_list.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/common/omnibox_features.h"
#include "content/public/browser/web_contents_user_data.h"
namespace {
class AutocompleteClientWebContentsUserData
: public content::WebContentsUserData<
AutocompleteClientWebContentsUserData> {
public:
~AutocompleteClientWebContentsUserData() override = default;
int GetLastCommittedEntryIndex() { return last_committed_entry_index_; }
const GURL& GetLastCommittedStrippedURL() {
return last_committed_stripped_url_;
}
void UpdateLastCommittedStrippedURL(
int last_committed_index,
const GURL& last_committed_url,
const TemplateURLService* template_url_service,
const bool keep_search_intent_params) {
if (last_committed_url.is_valid()) {
last_committed_entry_index_ = last_committed_index;
// Use a blank input as the stripped URL will be reused with other inputs.
// Also keep the search intent params. Otherwise, this can result in over
// triggering of the Switch to Tab action on plain-text suggestions for
// open entity SRPs, or vice versa, on entity suggestions for open
// plain-text SRPs.
last_committed_stripped_url_ = AutocompleteMatch::GURLToStrippedGURL(
last_committed_url, AutocompleteInput(), template_url_service,
std::u16string(), keep_search_intent_params);
}
}
private:
explicit AutocompleteClientWebContentsUserData(
content::WebContents* contents);
friend class content::WebContentsUserData<
AutocompleteClientWebContentsUserData>;
int last_committed_entry_index_ = -1;
GURL last_committed_stripped_url_;
WEB_CONTENTS_USER_DATA_KEY_DECL();
};
AutocompleteClientWebContentsUserData::AutocompleteClientWebContentsUserData(
content::WebContents* web_contents)
: content::WebContentsUserData<AutocompleteClientWebContentsUserData>(
*web_contents) {}
WEB_CONTENTS_USER_DATA_KEY_IMPL(AutocompleteClientWebContentsUserData);
} // namespace
bool TabMatcherDesktop::IsTabOpenWithURL(const GURL& url,
const AutocompleteInput* input,
bool exclude_active_tab) const {
const AutocompleteInput empty_input;
if (!input)
input = &empty_input;
// Use a blank input as the stripped URL will be reused with other inputs.
// Also keep the search intent params. Otherwise, this can result in over
// triggering of the Switch to Tab action on plain-text suggestions for
// open entity SRPs, or vice versa, on entity suggestions for open plain-text
// SRPs.
const bool keep_search_intent_params = base::FeatureList::IsEnabled(
omnibox::kDisambiguateTabMatchingForEntitySuggestions);
const GURL stripped_url = AutocompleteMatch::GURLToStrippedGURL(
url, *input, template_url_service_, std::u16string(),
keep_search_intent_params);
for (auto* web_contents : GetOpenWebContents(exclude_active_tab)) {
if (IsStrippedURLEqualToWebContentsURL(stripped_url, web_contents,
keep_search_intent_params)) {
return true;
}
}
return false;
}
bool TabMatcherDesktop::IsTabOpenWithSameTitleOrSimilarURL(
const std::u16string& title,
const GURL& url,
const GURL::Replacements& replacements,
bool exclude_active_tab) const {
auto strip_url = [&](const GURL& url) -> GURL {
return AutocompleteMatch::GURLToStrippedGURL(
url.ReplaceComponents(replacements), AutocompleteInput(),
template_url_service_, std::u16string(),
/*keep_search_intent_params=*/false);
};
for (auto* web_contents : GetOpenWebContents(exclude_active_tab)) {
if (title == web_contents->GetTitle() ||
strip_url(url) == strip_url(web_contents->GetLastCommittedURL())) {
return true;
}
}
return false;
}
std::vector<TabMatcher::TabWrapper> TabMatcherDesktop::GetOpenTabs(
const AutocompleteInput* input,
bool exclude_active_tab) const {
std::vector<TabMatcher::TabWrapper> open_tabs;
for (auto* web_contents : GetOpenWebContents(exclude_active_tab)) {
open_tabs.emplace_back(web_contents->GetTitle(),
web_contents->GetLastCommittedURL(),
web_contents->GetLastActiveTime());
}
return open_tabs;
}
std::vector<content::WebContents*> TabMatcherDesktop::GetOpenWebContents(
bool exclude_active_tab) const {
Browser* active_browser = BrowserList::GetInstance()->GetLastActive();
content::WebContents* active_tab = nullptr;
if (active_browser)
active_tab = active_browser->tab_strip_model()->GetActiveWebContents();
std::vector<content::WebContents*> all_tabs;
for (Browser* browser : *BrowserList::GetInstance()) {
if (profile_ != browser->profile()) {
// Only look at the same profile (and anonymity level).
continue;
}
for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
auto* web_contents = browser->tab_strip_model()->GetWebContentsAt(i);
if (web_contents != active_tab || !exclude_active_tab) {
all_tabs.push_back(web_contents);
}
}
}
return all_tabs;
}
bool TabMatcherDesktop::IsStrippedURLEqualToWebContentsURL(
const GURL& stripped_url,
content::WebContents* web_contents,
const bool keep_search_intent_params) const {
AutocompleteClientWebContentsUserData::CreateForWebContents(web_contents);
AutocompleteClientWebContentsUserData* user_data =
AutocompleteClientWebContentsUserData::FromWebContents(web_contents);
DCHECK(user_data);
if (user_data->GetLastCommittedEntryIndex() !=
web_contents->GetController().GetLastCommittedEntryIndex()) {
user_data->UpdateLastCommittedStrippedURL(
web_contents->GetController().GetLastCommittedEntryIndex(),
web_contents->GetLastCommittedURL(), template_url_service_,
keep_search_intent_params);
}
return stripped_url == user_data->GetLastCommittedStrippedURL();
}
|