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

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: Fix compile error 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 #include "services/shell/public/cpp/interface_registry.h"
18
19 namespace content {
20
21 namespace {
22
23 const char kWebSocketManagerKeyName[] = "web_socket_manager";
24
25 // Max number of pending connections per WebSocketManager used for per-renderer
26 // WebSocket throttling.
27 const int kMaxPendingWebSocketConnections = 255;
28
29 } // namespace
30
31 class WebSocketManager::Handle : public base::SupportsUserData::Data {
32 public:
33 explicit Handle(WebSocketManager* manager) : manager_(manager) {}
34 ~Handle() override {
35 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, manager_);
36 }
37 WebSocketManager* manager() const { return manager_; }
38 private:
39 WebSocketManager* manager_;
40 };
41
42 // static
43 void WebSocketManager::CreateWebSocket(int process_id, int frame_id,
44 mojom::WebSocketRequest request) {
45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
46
47 RenderProcessHost* host = RenderProcessHost::FromID(process_id);
48 CHECK(host);
49
50 Handle* handle =
51 static_cast<Handle*>(host->GetUserData(kWebSocketManagerKeyName));
52 if (!handle) {
53 handle = new Handle(
54 new WebSocketManager(process_id, host->GetStoragePartition()));
55 host->SetUserData(kWebSocketManagerKeyName, handle);
56 }
57
58 BrowserThread::PostTask(
59 BrowserThread::IO,
60 FROM_HERE,
61 base::Bind(&WebSocketManager::DoCreateWebSocket,
62 base::Unretained(handle->manager()),
63 frame_id,
64 base::Passed(&request)));
65 }
66
67 WebSocketManager::WebSocketManager(int process_id,
68 StoragePartition* storage_partition)
69 : process_id_(process_id),
70 storage_partition_(storage_partition),
71 num_pending_connections_(0),
72 num_current_succeeded_connections_(0),
73 num_previous_succeeded_connections_(0),
74 num_current_failed_connections_(0),
75 num_previous_failed_connections_(0) {}
76
77 WebSocketManager::~WebSocketManager() {
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
79
80 for (auto impl : impls_) {
81 impl->GoAway();
82 delete impl;
83 }
84 }
85
86 void WebSocketManager::DoCreateWebSocket(int frame_id,
87 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(CreateWebSocketImpl(this, std::move(request), frame_id,
100 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 int frame_id,
143 base::TimeDelta delay) {
144 return new WebSocketImpl(delegate, std::move(request), frame_id, delay);
145 }
146
147 int WebSocketManager::GetClientProcessId() {
148 return process_id_;
149 }
150
151 StoragePartition* WebSocketManager::GetStoragePartition() {
152 return storage_partition_;
153 }
154
155 void WebSocketManager::OnReceivedResponseFromServer(WebSocketImpl* impl) {
156 // The server accepted this WebSocket connection.
157 impl->OnHandshakeSucceeded();
158 --num_pending_connections_;
159 DCHECK_GE(num_pending_connections_, 0);
160 ++num_current_succeeded_connections_;
161 }
162
163 void WebSocketManager::OnLostConnectionToClient(WebSocketImpl* impl) {
164 // The client is no longer interested in this WebSocket.
165 if (!impl->handshake_succeeded()) {
166 // Update throttling counters (failure).
167 --num_pending_connections_;
168 DCHECK_GE(num_pending_connections_, 0);
169 ++num_current_failed_connections_;
170 }
171 impl->GoAway();
172 impls_.erase(impl);
173 delete impl;
174 }
175
176 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698