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 "ppapi/proxy/host_resolver_resource_base.h"
6
7#include "base/bind.h"
8#include "ppapi/c/pp_errors.h"
9#include "ppapi/proxy/net_address_resource.h"
10#include "ppapi/proxy/ppapi_messages.h"
11#include "ppapi/shared_impl/tracked_callback.h"
12#include "ppapi/shared_impl/var.h"
13
14namespace ppapi {
15namespace proxy {
16
17namespace {
18
19int32_t ConvertPPError(int32_t pp_error, bool private_api) {
20  // The private API doesn't return network-specific error codes or
21  // PP_ERROR_NOACCESS. In order to preserve the behavior, we convert those to
22  // PP_ERROR_FAILED.
23  // TODO(yzshen): Consider defining ranges for different kinds of PP_Error
24  // codes, so that we can detect network-specific error codes in a better way.
25  if (private_api &&
26      (pp_error <= PP_ERROR_CONNECTION_CLOSED ||
27       pp_error == PP_ERROR_NOACCESS)) {
28    return PP_ERROR_FAILED;
29  }
30
31  return pp_error;
32}
33
34}  // namespace
35
36HostResolverResourceBase::HostResolverResourceBase(Connection connection,
37                                                   PP_Instance instance,
38                                                   bool private_api)
39    : PluginResource(connection, instance),
40      private_api_(private_api),
41      allow_get_results_(false) {
42  if (private_api)
43    SendCreate(BROWSER, PpapiHostMsg_HostResolver_CreatePrivate());
44  else
45    SendCreate(BROWSER, PpapiHostMsg_HostResolver_Create());
46}
47
48HostResolverResourceBase::~HostResolverResourceBase() {
49}
50
51int32_t HostResolverResourceBase::ResolveImpl(
52    const char* host,
53    uint16_t port,
54    const PP_HostResolver_Private_Hint* hint,
55    scoped_refptr<TrackedCallback> callback) {
56  allow_get_results_ = false;
57  if (!host || !hint)
58    return PP_ERROR_BADARGUMENT;
59  if (ResolveInProgress())
60    return PP_ERROR_INPROGRESS;
61
62  resolve_callback_ = callback;
63
64  HostPortPair host_port;
65  host_port.host = host;
66  host_port.port = port;
67
68  SendResolve(host_port, hint);
69  return PP_OK_COMPLETIONPENDING;
70}
71
72PP_Var HostResolverResourceBase::GetCanonicalNameImpl() {
73  if (!allow_get_results_)
74    return PP_MakeUndefined();
75
76  return StringVar::StringToPPVar(canonical_name_);
77}
78
79uint32_t HostResolverResourceBase::GetSizeImpl() {
80  if (!allow_get_results_)
81    return 0;
82  return static_cast<uint32_t>(net_address_list_.size());
83}
84
85scoped_refptr<NetAddressResource> HostResolverResourceBase::GetNetAddressImpl(
86    uint32_t index) {
87  if (!allow_get_results_ || index >= GetSizeImpl())
88    return scoped_refptr<NetAddressResource>();
89
90  return net_address_list_[index];
91}
92
93void HostResolverResourceBase::OnPluginMsgResolveReply(
94    const ResourceMessageReplyParams& params,
95    const std::string& canonical_name,
96    const std::vector<PP_NetAddress_Private>& net_address_list) {
97  if (params.result() == PP_OK) {
98    allow_get_results_ = true;
99    canonical_name_ = canonical_name;
100
101    net_address_list_.clear();
102    for (std::vector<PP_NetAddress_Private>::const_iterator iter =
103             net_address_list.begin();
104         iter != net_address_list.end();
105         ++iter) {
106      net_address_list_.push_back(
107          new NetAddressResource(connection(), pp_instance(), *iter));
108    }
109  } else {
110    canonical_name_.clear();
111    net_address_list_.clear();
112  }
113  resolve_callback_->Run(ConvertPPError(params.result(), private_api_));
114}
115
116void HostResolverResourceBase::SendResolve(
117    const HostPortPair& host_port,
118    const PP_HostResolver_Private_Hint* hint) {
119  PpapiHostMsg_HostResolver_Resolve msg(host_port, *hint);
120  Call<PpapiPluginMsg_HostResolver_ResolveReply>(
121      BROWSER,
122      msg,
123      base::Bind(&HostResolverResourceBase::OnPluginMsgResolveReply,
124                 base::Unretained(this)));
125}
126
127bool HostResolverResourceBase::ResolveInProgress() const {
128  return TrackedCallback::IsPending(resolve_callback_);
129}
130
131}  // namespace proxy
132}  // namespace ppapi
133