blob: 70fa708fac53bbd44466318f22d7cd7174d3be21 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ledger/bin/app/page_connection_notifier.h"
#include <lib/callback/scoped_callback.h>
#include <lib/fit/function.h>
#include "src/ledger/bin/storage/public/types.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace ledger {
PageConnectionNotifier::PageConnectionNotifier(
std::string ledger_name, storage::PageId page_id,
PageUsageListener* page_usage_listener)
: ledger_name_(std::move(ledger_name)),
page_id_(std::move(page_id)),
page_usage_listener_(page_usage_listener),
weak_factory_(this) {}
PageConnectionNotifier::~PageConnectionNotifier() {}
void PageConnectionNotifier::RegisterExternalRequest() {
if (has_external_requests_) {
return;
}
must_notify_on_page_unused_ = true;
has_external_requests_ = true;
page_usage_listener_->OnPageOpened(ledger_name_, page_id_);
}
void PageConnectionNotifier::UnregisterExternalRequests() {
if (has_external_requests_) {
page_usage_listener_->OnPageClosed(ledger_name_, page_id_);
has_external_requests_ = false;
CheckEmpty();
}
}
ExpiringToken PageConnectionNotifier::NewInternalRequestToken() {
++internal_request_count_;
return ExpiringToken(callback::MakeScoped(weak_factory_.GetWeakPtr(), [this] {
FXL_DCHECK(internal_request_count_ > 0);
--internal_request_count_;
CheckEmpty();
}));
}
void PageConnectionNotifier::set_on_empty(fit::closure on_empty_callback) {
on_empty_callback_ = std::move(on_empty_callback);
}
bool PageConnectionNotifier::IsEmpty() {
return internal_request_count_ == 0 && !has_external_requests_;
}
void PageConnectionNotifier::CheckEmpty() {
if (!IsEmpty()) {
return;
}
if (must_notify_on_page_unused_) {
// We need to keep the object alive while |OnPageUnused| runs.
auto token = NewInternalRequestToken();
must_notify_on_page_unused_ = false;
page_usage_listener_->OnPageUnused(ledger_name_, page_id_);
// If the page is empty at this point, destructing |token| will call
// |CheckEmpty()| again.
return;
}
if (on_empty_callback_) {
on_empty_callback_();
}
}
} // namespace ledger