blob: 9e384046bd3b9e61a67b944c77d4456ff3be3104 [file] [log] [blame]
// 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