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
|
// Copyright 2012 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/extensions/window_controller_list.h"
#include <algorithm>
#include "base/containers/contains.h"
#include "base/observer_list.h"
#include "chrome/browser/extensions/api/tabs/windows_util.h"
#include "chrome/browser/extensions/window_controller_list_observer.h"
#include "chrome/common/extensions/api/windows.h"
#include "components/sessions/core/session_id.h"
#include "extensions/browser/extension_function.h"
#include "extensions/buildflags/buildflags.h"
#include "ui/base/base_window.h"
static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));
namespace extensions {
///////////////////////////////////////////////////////////////////////////////
// WindowControllerList
// static
WindowControllerList* WindowControllerList::GetInstance() {
return base::Singleton<WindowControllerList>::get();
}
WindowControllerList::WindowControllerList() = default;
WindowControllerList::~WindowControllerList() = default;
void WindowControllerList::AddExtensionWindow(WindowController* window) {
windows_.push_back(window);
for (auto& observer : observers_)
observer.OnWindowControllerAdded(window);
}
void WindowControllerList::RemoveExtensionWindow(WindowController* window) {
auto iter = std::ranges::find(windows_, window);
if (iter != windows_.end()) {
windows_.erase(iter);
for (auto& observer : observers_)
observer.OnWindowControllerRemoved(window);
}
}
void WindowControllerList::NotifyWindowBoundsChanged(WindowController* window) {
if (base::Contains(windows_, window)) {
for (auto& observer : observers_)
observer.OnWindowBoundsChanged(window);
}
}
void WindowControllerList::NotifyWindowFocusChanged(WindowController* window,
bool has_focus) {
if (base::Contains(windows_, window)) {
for (auto& observer : observers_) {
observer.OnWindowFocusChanged(window, has_focus);
}
}
}
void WindowControllerList::AddObserver(WindowControllerListObserver* observer) {
observers_.AddObserver(observer);
}
void WindowControllerList::RemoveObserver(
WindowControllerListObserver* observer) {
observers_.RemoveObserver(observer);
}
WindowController* WindowControllerList::FindWindowForFunctionByIdWithFilter(
const ExtensionFunction* function,
int id,
WindowController::TypeFilter filter) const {
for (auto iter = windows_.begin(); iter != windows_.end(); ++iter) {
if ((*iter)->GetWindowId() == id) {
if (windows_util::CanOperateOnWindow(function, *iter, filter))
return *iter;
return nullptr;
}
}
return nullptr;
}
WindowController* WindowControllerList::CurrentWindowForFunction(
ExtensionFunction* function) const {
return CurrentWindowForFunctionWithFilter(function,
WindowController::kNoWindowFilter);
}
WindowController* WindowControllerList::CurrentWindowForFunctionWithFilter(
ExtensionFunction* function,
WindowController::TypeFilter filter) const {
// Always prefer the focused window if available. If there is no focused
// window, prefer the window to which the sender window is logically parented.
// Since the browser window is not "focused" when an extension popup is open
// (because popup is hosted in a separate window, which is focused instead),
// we need to check for the logical parent window here. If neither of these
// are available, return the last window.
WindowController* last_window = nullptr;
WindowController* parent_window = nullptr;
for (const auto& controller : windows_) {
if (!windows_util::CanOperateOnWindow(function, controller, filter)) {
continue;
}
if (controller->window()->IsActive()) {
// If the window is focused, return it immediately.
return controller;
}
#if !BUILDFLAG(IS_ANDROID)
// TODO(crbug.com/371432155): Support on Android.
// windows_util::CalledFromChildWindow() checks native widgets for parents.
if (windows_util::CalledFromChildWindow(function, controller)) {
parent_window = controller;
}
#endif
last_window = controller;
}
return parent_window ? parent_window : last_window;
}
} // namespace extensions
|