Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: content/browser/websockets/websocket_manager.cc

Issue 2119973002: Port WebSockets to Mojo IPC (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleanup Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/websockets/websocket_manager.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <vector>
10
11 #include "base/callback.h"
12 #include "base/logging.h"
13 #include "base/numerics/safe_conversions.h"
14 #include "base/rand_util.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/render_process_host.h"
17
18 namespace content {
19
20 namespace {
21
22 const char kWebSocketManagerKeyName[] = "web_socket_manager";
23
24 // Max number of pending connections per WebSocketManager used for per-renderer
25 // WebSocket throttling.
26 const int kMaxPendingWebSocketConnections = 255;
27
28 } // namespace
29
30 class WebSocketManager::Handle : public base::SupportsUserData::Data {
31 public:
32 explicit Handle(WebSocketManager* manager) : manager_(manager) {}
33
34 ~Handle() override {
35 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, manager_);
36 }
37
38 WebSocketManager* manager() const { return manager_; }
39
40 private:
41 WebSocketManager* manager_;
42 };
43
44 // static
45 void WebSocketManager::CreateWebSocket(int process_id,
46 mojom::WebSocketRequest request) {
47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
48
49 RenderProcessHost* host = RenderProcessHost::FromID(process_id);
50 CHECK(host);
51
52 Handle* handle =
53 static_cast<Handle*>(host->GetUserData(kWebSocketManagerKeyName));
54 if (!handle) {
55 handle = new Handle(
56 new WebSocketManager(process_id, host->GetStoragePartition()));
57 host->SetUserData(kWebSocketManagerKeyName, handle);
58 }
59
60 BrowserThread::PostTask(
61 BrowserThread::IO,
62 FROM_HERE,
63 base::Bind(&WebSocketManager::DoCreateWebSocket,
64 base::Unretained(handle->manager()),
65 base::Passed(&request)));
66 }
67
68 WebSocketManager::WebSocketManager(int process_id,
69 StoragePartition* storage_partition)
70 : process_id_(process_id),
71 storage_partition_(storage_partition),
72 num_pending_connections_(0),
73 num_current_succeeded_connections_(0),
74 num_previous_succeeded_connections_(0),
75 num_current_failed_connections_(0),
76 num_previous_failed_connections_(0) {}
77
78 WebSocketManager::~WebSocketManager() {
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
80
81 for (auto impl : impls_) {
82 impl->GoAway();
83 delete impl;
84 }
85 }
86
87 void WebSocketManager::DoCreateWebSocket(mojom::WebSocketRequest request) {
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
89
90 if (num_pending_connections_ >= kMaxPendingWebSocketConnections) {
91 // Too many websockets! By returning here, we let |request| die, which
92 // will be observed by the client as Mojo connection error.
93 return;
94 }
95
96 // Keep all WebSocketImpls alive until either the client drops its
97 // connection (see OnLostConnectionToClient) or we need to shutdown.
98
99 impls_.insert(
100 CreateWebSocketImpl(this, std::move(request), CalculateDelay()));
101 ++num_pending_connections_;
102
103 if (!throttling_period_timer_.IsRunning()) {
104 throttling_period_timer_.Start(
105 FROM_HERE,
106 base::TimeDelta::FromMinutes(2),
107 this,
108 &WebSocketManager::ThrottlingPeriodTimerCallback);
109 }
110 }
111
112 // Calculate delay as described in the per-renderer WebSocket throttling
113 // design doc: https://goo.gl/tldFNn
114 base::TimeDelta WebSocketManager::CalculateDelay() const {
115 int64_t f = num_previous_failed_connections_ +
116 num_current_failed_connections_;
117 int64_t s = num_previous_succeeded_connections_ +
118 num_current_succeeded_connections_;
119 int p = num_pending_connections_;
120 return base::TimeDelta::FromMilliseconds(
121 base::RandInt(1000, 5000) *
122 (1 << std::min(p + f / (s + 1), INT64_C(16))) / 65536);
123 }
124
125 void WebSocketManager::ThrottlingPeriodTimerCallback() {
126 num_previous_failed_connections_ = num_current_failed_connections_;
127 num_current_failed_connections_ = 0;
128
129 num_previous_succeeded_connections_ = num_current_succeeded_connections_;
130 num_current_succeeded_connections_ = 0;
131
132 if (num_pending_connections_ == 0 &&
133 num_previous_failed_connections_ == 0 &&
134 num_previous_succeeded_connections_ == 0) {
135 throttling_period_timer_.Stop();
136 }
137 }
138
139 WebSocketImpl* WebSocketManager::CreateWebSocketImpl(
140 WebSocketImpl::Delegate* delegate,
141 mojom::WebSocketRequest request,
142 base::TimeDelta delay) {
143 return new WebSocketImpl(delegate, std::move(request), delay);
144 }
145
146 int WebSocketManager::GetClientProcessId() {
147 return process_id_;
148 }
149
150 StoragePartition* WebSocketManager::GetStoragePartition() {
151 return storage_partition_;
152 }
153
154 void WebSocketManager::OnReceivedResponseFromServer(WebSocketImpl* impl) {
155 // The server accepted this WebSocket connection.
156 impl->OnHandshakeSucceeded();
157 --num_pending_connections_;
158 DCHECK_GE(num_pending_connections_, 0);
159 ++num_current_succeeded_connections_;
160 }
161
162 void WebSocketManager::OnLostConnectionToClient(WebSocketImpl* impl) {
163 // The client is no longer interested in this WebSocket.
164 if (!impl->handshake_succeeded()) {
165 // Update throttling counters (failure).
166 --num_pending_connections_;
167 DCHECK_GE(num_pending_connections_, 0);
168 ++num_current_failed_connections_;
169 }
170 impl->GoAway();
171 impls_.erase(impl);
172 delete impl;
173 }
174
175 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698