168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// found in the LICENSE file.
468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/child/websocket_bridge.h"
668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <stdint.h>
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <string>
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <utility>
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <vector>
1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/logging.h"
1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/strings/string_util.h"
1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/child/child_thread.h"
1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/child/websocket_dispatcher.h"
1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/common/websocket.h"
1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/common/websocket_messages.h"
1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ipc/ipc_message.h"
1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ipc/ipc_message_macros.h"
2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebSerializedOrigin.h"
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebSocketHandle.h"
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebSocketHandleClient.h"
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebSocketHandshakeRequestInfo.h"
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebSocketHandshakeResponseInfo.h"
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebString.h"
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURL.h"
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebVector.h"
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/gurl.h"
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/origin.h"
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using blink::WebSerializedOrigin;
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebSocketHandle;
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebSocketHandleClient;
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebString;
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURL;
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebVector;
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace content {
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace {
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const unsigned short kAbnormalShutdownOpCode = 1006;
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WebSocketBridge::WebSocketBridge()
4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : channel_id_(kInvalidChannelId),
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      render_frame_id_(MSG_ROUTING_NONE),
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      client_(NULL) {}
5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WebSocketBridge::~WebSocketBridge() {
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (channel_id_ != kInvalidChannelId) {
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // The connection is abruptly disconnected by the renderer without
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // closing handshake.
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ChildThread::current()->Send(
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        new WebSocketMsg_DropChannel(channel_id_,
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     false,
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     kAbnormalShutdownOpCode,
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     std::string()));
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Disconnect();
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WebSocketBridge::OnMessageReceived(const IPC::Message& msg) {
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool handled = true;
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(WebSocketBridge, msg)
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_AddChannelResponse, DidConnect)
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_NotifyStartOpeningHandshake,
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        DidStartOpeningHandshake)
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_NotifyFinishOpeningHandshake,
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        DidFinishOpeningHandshake)
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_NotifyFailure, DidFail)
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, DidReceiveData)
7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, DidReceiveFlowControl)
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, DidClose)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IPC_MESSAGE_HANDLER(WebSocketMsg_NotifyClosing,
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        DidStartClosingHandshake)
7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return handled;
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WebSocketBridge::DidConnect(bool fail,
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 const std::string& selected_protocol,
8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 const std::string& extensions) {
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WebSocketHandleClient* client = client_;
8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DVLOG(1) << "WebSocketBridge::DidConnect("
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << fail << ", "
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << selected_protocol << ", "
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << extensions << ")";
9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (fail)
9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Disconnect();
9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!client)
9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WebString protocol_to_pass = WebString::fromUTF8(selected_protocol);
9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WebString extensions_to_pass = WebString::fromUTF8(extensions);
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  client->didConnect(this, fail, protocol_to_pass, extensions_to_pass);
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |this| can be deleted here.
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WebSocketBridge::DidStartOpeningHandshake(
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebSocketHandshakeRequest& request) {
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "WebSocketBridge::DidStartOpeningHandshake("
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << request.url << ")";
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // All strings are already encoded to ASCII in the browser.
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  blink::WebSocketHandshakeRequestInfo request_to_pass;
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  request_to_pass.setURL(WebURL(request.url));
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (size_t i = 0; i < request.headers.size(); ++i) {
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::pair<std::string, std::string>& header = request.headers[i];
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    request_to_pass.addHeaderField(WebString::fromLatin1(header.first),
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                   WebString::fromLatin1(header.second));
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  request_to_pass.setHeadersText(WebString::fromLatin1(request.headers_text));
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  client_->didStartOpeningHandshake(this, request_to_pass);
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WebSocketBridge::DidFinishOpeningHandshake(
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebSocketHandshakeResponse& response) {
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "WebSocketBridge::DidFinishOpeningHandshake("
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << response.url << ")";
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // All strings are already encoded to ASCII in the browser.
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  blink::WebSocketHandshakeResponseInfo response_to_pass;
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  response_to_pass.setStatusCode(response.status_code);
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  response_to_pass.setStatusText(WebString::fromLatin1(response.status_text));
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (size_t i = 0; i < response.headers.size(); ++i) {
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::pair<std::string, std::string>& header = response.headers[i];
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    response_to_pass.addHeaderField(WebString::fromLatin1(header.first),
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    WebString::fromLatin1(header.second));
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  response_to_pass.setHeadersText(WebString::fromLatin1(response.headers_text));
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  client_->didFinishOpeningHandshake(this, response_to_pass);
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WebSocketBridge::DidFail(const std::string& message) {
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "WebSocketBridge::DidFail(" << message << ")";
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WebSocketHandleClient* client = client_;
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Disconnect();
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!client)
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WebString message_to_pass = WebString::fromUTF8(message);
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  client->didFail(this, message_to_pass);
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |this| can be deleted here.
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WebSocketBridge::DidReceiveData(bool fin,
14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     WebSocketMessageType type,
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     const std::vector<char>& data) {
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DVLOG(1) << "WebSocketBridge::DidReceiveData("
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << fin << ", "
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << type << ", "
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << "(data size = " << data.size() << "))";
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!client_)
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WebSocketHandle::MessageType type_to_pass =
15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      WebSocketHandle::MessageTypeContinuation;
15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  switch (type) {
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case WEB_SOCKET_MESSAGE_TYPE_CONTINUATION:
16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      type_to_pass = WebSocketHandle::MessageTypeContinuation;
16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case WEB_SOCKET_MESSAGE_TYPE_TEXT:
16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      type_to_pass = WebSocketHandle::MessageTypeText;
16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case WEB_SOCKET_MESSAGE_TYPE_BINARY:
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      type_to_pass = WebSocketHandle::MessageTypeBinary;
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const char* data_to_pass = data.empty() ? NULL : &data[0];
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  client_->didReceiveData(this, fin, type_to_pass, data_to_pass, data.size());
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |this| can be deleted here.
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WebSocketBridge::DidReceiveFlowControl(int64_t quota) {
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DVLOG(1) << "WebSocketBridge::DidReceiveFlowControl(" << quota << ")";
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!client_)
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  client_->didReceiveFlowControl(this, quota);
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |this| can be deleted here.
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WebSocketBridge::DidClose(bool was_clean,
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               unsigned short code,
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                               const std::string& reason) {
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DVLOG(1) << "WebSocketBridge::DidClose("
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << was_clean << ", "
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << code << ", "
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << reason << ")";
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WebSocketHandleClient* client = client_;
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Disconnect();
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!client)
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WebString reason_to_pass = WebString::fromUTF8(reason);
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  client->didClose(this, was_clean, code, reason_to_pass);
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |this| can be deleted here.
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebSocketBridge::DidStartClosingHandshake() {
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(1) << "WebSocketBridge::DidStartClosingHandshake()";
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!client_)
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  client_->didStartClosingHandshake(this);
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |this| can be deleted here.
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WebSocketBridge::connect(
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const WebURL& url,
21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const WebVector<WebString>& protocols,
21323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const WebSerializedOrigin& origin,
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    WebSocketHandleClient* client) {
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK_EQ(kInvalidChannelId, channel_id_);
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WebSocketDispatcher* dispatcher =
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ChildThread::current()->websocket_dispatcher();
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  channel_id_ = dispatcher->AddBridge(this);
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  client_ = client;
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<std::string> protocols_to_pass;
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < protocols.size(); ++i)
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    protocols_to_pass.push_back(protocols[i].utf8());
22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  url::Origin origin_to_pass(origin);
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DVLOG(1) << "Bridge#" << channel_id_ << " Connect(" << url << ", ("
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << JoinString(protocols_to_pass, ", ") << "), "
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << origin_to_pass.string() << ")";
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ChildThread::current()->Send(new WebSocketHostMsg_AddChannelRequest(
23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      channel_id_, url, protocols_to_pass, origin_to_pass, render_frame_id_));
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WebSocketBridge::send(bool fin,
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                           WebSocketHandle::MessageType type,
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                           const char* data,
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                           size_t size) {
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (channel_id_ == kInvalidChannelId)
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WebSocketMessageType type_to_pass = WEB_SOCKET_MESSAGE_TYPE_CONTINUATION;
24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  switch (type) {
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case WebSocketHandle::MessageTypeContinuation:
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      type_to_pass = WEB_SOCKET_MESSAGE_TYPE_CONTINUATION;
24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case WebSocketHandle::MessageTypeText:
24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      type_to_pass = WEB_SOCKET_MESSAGE_TYPE_TEXT;
24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case WebSocketHandle::MessageTypeBinary:
25068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      type_to_pass = WEB_SOCKET_MESSAGE_TYPE_BINARY;
25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
25368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DVLOG(1) << "Bridge #" << channel_id_ << " Send("
25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << fin << ", " << type_to_pass << ", "
25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << "(data size = "  << size << "))";
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ChildThread::current()->Send(
25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      new WebSocketMsg_SendFrame(channel_id_,
26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 fin,
26168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 type_to_pass,
26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 std::vector<char>(data, data + size)));
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WebSocketBridge::flowControl(int64_t quota) {
26668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (channel_id_ == kInvalidChannelId)
26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
26868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
26968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DVLOG(1) << "Bridge #" << channel_id_ << " FlowControl(" << quota << ")";
27068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ChildThread::current()->Send(
27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      new WebSocketMsg_FlowControl(channel_id_, quota));
27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WebSocketBridge::close(unsigned short code,
27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                            const WebString& reason) {
27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (channel_id_ == kInvalidChannelId)
27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::string reason_to_pass = reason.utf8();
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DVLOG(1) << "Bridge #" << channel_id_ << " Close("
28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << code << ", " << reason_to_pass << ")";
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This method is for closing handshake and hence |was_clean| shall be true.
28468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ChildThread::current()->Send(
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new WebSocketMsg_DropChannel(channel_id_, true, code, reason_to_pass));
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
28768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WebSocketBridge::Disconnect() {
28968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (channel_id_ == kInvalidChannelId)
29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WebSocketDispatcher* dispatcher =
29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ChildThread::current()->websocket_dispatcher();
29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  dispatcher->RemoveBridge(channel_id_);
29468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  channel_id_ = kInvalidChannelId;
29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  client_ = NULL;
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace content
300