File: tab_matcher_desktop.cc

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (162 lines) | stat: -rw-r--r-- 6,410 bytes parent folder | download | duplicates (3)
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();
}