123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- // Copyright 2017 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 "net/spdy/http2_push_promise_index.h"
- #include <algorithm>
- #include <utility>
- #include "base/trace_event/memory_usage_estimator.h"
- namespace net {
- Http2PushPromiseIndex::Http2PushPromiseIndex() = default;
- Http2PushPromiseIndex::~Http2PushPromiseIndex() {
- DCHECK(unclaimed_pushed_streams_.empty());
- }
- bool Http2PushPromiseIndex::RegisterUnclaimedPushedStream(
- const GURL& url,
- spdy::SpdyStreamId stream_id,
- Delegate* delegate) {
- DCHECK(!url.is_empty());
- DCHECK_GT(stream_id, kNoPushedStreamFound);
- DCHECK(delegate);
- // Find the entry with |url| for |delegate| if such exists (there can be at
- // most one such entry). It is okay to cast away const from |delegate|,
- // because it is only used for lookup.
- auto it = unclaimed_pushed_streams_.lower_bound(UnclaimedPushedStream{
- url, const_cast<Delegate*>(delegate), kNoPushedStreamFound});
- // If such entry is found, do not allow registering another one.
- if (it != unclaimed_pushed_streams_.end() && it->url == url &&
- it->delegate == delegate) {
- return false;
- }
- unclaimed_pushed_streams_.insert(
- it, UnclaimedPushedStream{url, delegate, stream_id});
- return true;
- }
- bool Http2PushPromiseIndex::UnregisterUnclaimedPushedStream(
- const GURL& url,
- spdy::SpdyStreamId stream_id,
- Delegate* delegate) {
- DCHECK(!url.is_empty());
- DCHECK_GT(stream_id, kNoPushedStreamFound);
- DCHECK(delegate);
- size_t result = unclaimed_pushed_streams_.erase(
- UnclaimedPushedStream{url, delegate, stream_id});
- return result == 1;
- }
- // The runtime of this method is linear in unclaimed_pushed_streams_.size(),
- // which is acceptable, because it is only used in NetLog, tests, and DCHECKs.
- size_t Http2PushPromiseIndex::CountStreamsForSession(
- const Delegate* delegate) const {
- DCHECK(delegate);
- return std::count_if(unclaimed_pushed_streams_.begin(),
- unclaimed_pushed_streams_.end(),
- [&delegate](const UnclaimedPushedStream& entry) {
- return entry.delegate == delegate;
- });
- }
- spdy::SpdyStreamId Http2PushPromiseIndex::FindStream(
- const GURL& url,
- const Delegate* delegate) const {
- // Find the entry with |url| for |delegate| if such exists (there can be at
- // most one such entry). It is okay to cast away const from |delegate|,
- // because it is only used for lookup.
- auto it = unclaimed_pushed_streams_.lower_bound(UnclaimedPushedStream{
- url, const_cast<Delegate*>(delegate), kNoPushedStreamFound});
- if (it == unclaimed_pushed_streams_.end() || it->url != url ||
- it->delegate != delegate) {
- return kNoPushedStreamFound;
- }
- return it->stream_id;
- }
- void Http2PushPromiseIndex::ClaimPushedStream(
- const SpdySessionKey& key,
- const GURL& url,
- const HttpRequestInfo& request_info,
- base::WeakPtr<SpdySession>* session,
- spdy::SpdyStreamId* stream_id) {
- DCHECK(!url.is_empty());
- *session = nullptr;
- *stream_id = kNoPushedStreamFound;
- // Find the first entry for |url|, if such exists.
- auto it = unclaimed_pushed_streams_.lower_bound(
- UnclaimedPushedStream{url, nullptr, kNoPushedStreamFound});
- while (it != unclaimed_pushed_streams_.end() && it->url == url) {
- if (it->delegate->ValidatePushedStream(it->stream_id, url, request_info,
- key)) {
- *session = it->delegate->GetWeakPtrToSession();
- *stream_id = it->stream_id;
- unclaimed_pushed_streams_.erase(it);
- return;
- }
- ++it;
- }
- }
- bool Http2PushPromiseIndex::CompareByUrl::operator()(
- const UnclaimedPushedStream& a,
- const UnclaimedPushedStream& b) const {
- // Compare by URL first.
- if (a.url < b.url)
- return true;
- if (a.url > b.url)
- return false;
- // For identical URL, put an entry with delegate == nullptr first.
- // The C++ standard dictates that comparisons between |nullptr| and other
- // pointers are unspecified, hence the need to handle this case separately.
- if (a.delegate == nullptr && b.delegate != nullptr) {
- return true;
- }
- if (a.delegate != nullptr && b.delegate == nullptr) {
- return false;
- }
- // Then compare by Delegate.
- // The C++ standard guarantees that both |nullptr < nullptr| and
- // |nullptr > nullptr| are false, so there is no need to handle that case
- // separately.
- if (a.delegate < b.delegate)
- return true;
- if (a.delegate > b.delegate)
- return false;
- // If URL and Delegate are identical, then compare by stream ID.
- return a.stream_id < b.stream_id;
- }
- } // namespace net
|