| // Copyright 2022 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/ash/file_system_provider/operation_request_manager.h" |
| |
| #include "base/time/time.h" |
| #include "chrome/browser/ash/browser_delegate/browser_controller.h" |
| #include "chrome/browser/ash/browser_delegate/browser_delegate.h" |
| #include "chrome/browser/extensions/window_controller_list.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "content/public/browser/web_contents.h" |
| #include "extensions/browser/app_window/app_window_registry.h" |
| #include "extensions/common/constants.h" |
| |
| namespace ash::file_system_provider { |
| namespace { |
| |
| } // namespace |
| |
| OperationRequestManager::OperationRequestManager( |
| Profile* profile, |
| const std::string& provider_id, |
| NotificationManagerInterface* notification_manager, |
| base::TimeDelta timeout) |
| : RequestManager(profile, notification_manager, timeout), |
| provider_id_(provider_id) {} |
| |
| OperationRequestManager::~OperationRequestManager() = default; |
| |
| void OperationRequestManager::OnRequestTimeout(int request_id) { |
| for (auto& observer : observers_) |
| observer.OnRequestTimedOut(request_id); |
| |
| if (!notification_manager_) { |
| RejectRequestInternal(request_id, RequestValue(), |
| base::File::FILE_ERROR_ABORT, |
| OperationCompletion::kAbortedInternally); |
| return; |
| } |
| |
| auto request_it = requests_.find(request_id); |
| if (request_it == requests_.end()) { |
| return; |
| } |
| |
| if (!IsInteractingWithUser()) { |
| request_it->second->shown_unresponsive_notification = true; |
| notification_manager_->ShowUnresponsiveNotification( |
| request_id, |
| base::BindOnce( |
| &OperationRequestManager::OnUnresponsiveNotificationResult, |
| weak_ptr_factory_.GetWeakPtr(), request_id)); |
| } else { |
| ResetTimer(request_id); |
| } |
| } |
| |
| bool OperationRequestManager::IsInteractingWithUser() const { |
| if (current_user_interactions_ > 0) { |
| return true; |
| } |
| |
| // First try for app windows. If not found, then fall back to browser windows |
| // and tabs. |
| const extensions::AppWindowRegistry* const registry = |
| extensions::AppWindowRegistry::Get(profile_); |
| DCHECK(registry); |
| if (registry->GetCurrentAppWindowForApp(provider_id_)) |
| return true; |
| |
| // This loop is heavy, but it's not called often. Only when a request timeouts |
| // which is at most once every 10 seconds per request (except tests). |
| for (extensions::WindowController* window : |
| *extensions::WindowControllerList::GetInstance()) { |
| const BrowserDelegate* const browser = |
| BrowserController::GetInstance()->GetDelegate(window->GetBrowser()); |
| if (!browser) |
| continue; |
| for (unsigned int i = 0, n = browser->GetWebContentsCount(); i < n; ++i) { |
| const GURL& url = browser->GetWebContentsAt(i)->GetURL(); |
| if (url.SchemeIs(extensions::kExtensionScheme) && |
| url.host_piece() == provider_id_) { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| } // namespace ash::file_system_provider |