blob: b49bd51a64978ea62197f3597fdff81a23c1ee3f [file] [log] [blame]
// Copyright 2018 The Chromium 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 "content/browser/renderer_host/frame_token_message_queue.h"
#include "base/bind.h"
#include "ipc/ipc_message.h"
namespace content {
FrameTokenMessageQueue::FrameTokenMessageQueue(Client* client)
: client_(client) {}
FrameTokenMessageQueue::~FrameTokenMessageQueue() {}
void FrameTokenMessageQueue::DidProcessFrame(uint32_t frame_token) {
// Frame tokens always increase.
if (frame_token <= last_received_frame_token_) {
client_->OnInvalidFrameToken(frame_token);
return;
}
last_received_frame_token_ = frame_token;
// Gets the first callback associated with a token after |frame_token| or
// callback_map_.end().
auto upper_bound = callback_map_.upper_bound(frame_token);
// std::multimap already sorts on keys, so this will process all enqueued
// messages up to the current frame token.
for (auto it = callback_map_.begin(); it != upper_bound; ++it)
std::move(it->second).Run();
// Clear all callbacks up to the current frame token.
callback_map_.erase(callback_map_.begin(), upper_bound);
}
void FrameTokenMessageQueue::EnqueueOrRunFrameTokenCallback(
uint32_t frame_token,
base::OnceClosure callback) {
// Zero token is invalid.
if (!frame_token) {
client_->OnInvalidFrameToken(frame_token);
return;
}
if (frame_token <= last_received_frame_token_) {
std::move(callback).Run();
return;
}
callback_map_.insert(std::make_pair(frame_token, std::move(callback)));
}
void FrameTokenMessageQueue::OnFrameSwapMessagesReceived(
uint32_t frame_token,
std::vector<IPC::Message> messages) {
EnqueueOrRunFrameTokenCallback(
frame_token, base::BindOnce(&FrameTokenMessageQueue::ProcessSwapMessages,
base::Unretained(this), std::move(messages)));
}
void FrameTokenMessageQueue::Reset() {
last_received_frame_token_ = 0;
callback_map_.clear();
}
void FrameTokenMessageQueue::ProcessSwapMessages(
std::vector<IPC::Message> messages) {
for (const IPC::Message& i : messages) {
client_->OnProcessSwapMessage(i);
if (i.dispatch_error())
client_->OnMessageDispatchError(i);
}
}
} // namespace content