summaryrefslogtreecommitdiffstats
path: root/net/proxy/sync_host_resolver_bridge.cc
blob: 31a326dda47a514a20ffc08318d0de6e38a7deac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright (c) 2010 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/proxy/sync_host_resolver_bridge.h"

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"

namespace net {

// SyncHostResolverBridge -----------------------------------------------------

SyncHostResolverBridge::SyncHostResolverBridge(HostResolver* host_resolver,
                                               MessageLoop* host_resolver_loop)
    : host_resolver_(host_resolver),
      host_resolver_loop_(host_resolver_loop),
      event_(true, false),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          callback_(this, &SyncHostResolverBridge::OnResolveCompletion)),
      outstanding_request_(NULL),
      has_shutdown_(false) {
  DCHECK(host_resolver_loop_);
}

SyncHostResolverBridge::~SyncHostResolverBridge() {
  DCHECK(HasShutdown());
}

int SyncHostResolverBridge::Resolve(const RequestInfo& info,
                                    AddressList* addresses,
                                    CompletionCallback* callback,
                                    RequestHandle* out_req,
                                    const BoundNetLog& net_log) {
  DCHECK(!callback);
  DCHECK(!out_req);

  // Otherwise start an async resolve on the resolver's thread.
  host_resolver_loop_->PostTask(
      FROM_HERE,
      NewRunnableMethod(this, &SyncHostResolverBridge::StartResolve,
                        info, addresses));

  // Wait for the resolve to complete in the resolver's thread.
  event_.Wait();

  {
    AutoLock l(lock_);
    if (has_shutdown_)
      return ERR_ABORTED;
    event_.Reset();
  }

  return err_;
}

void SyncHostResolverBridge::CancelRequest(RequestHandle req) {
  NOTREACHED();
}

void SyncHostResolverBridge::AddObserver(Observer* observer) {
  NOTREACHED();
}

void SyncHostResolverBridge::RemoveObserver(Observer* observer) {
  NOTREACHED();
}

void SyncHostResolverBridge::Shutdown() {
  DCHECK_EQ(MessageLoop::current(), host_resolver_loop_);

  if (outstanding_request_) {
    host_resolver_->CancelRequest(outstanding_request_);
    outstanding_request_ = NULL;
  }

  AutoLock l(lock_);
  has_shutdown_ = true;

  // Wake up the PAC thread in case it was waiting for resolve completion.
  event_.Signal();
}

void SyncHostResolverBridge::StartResolve(const HostResolver::RequestInfo& info,
                                          net::AddressList* addresses) {
  DCHECK_EQ(host_resolver_loop_, MessageLoop::current());
  DCHECK(!outstanding_request_);

  if (HasShutdown())
    return;

  int error = host_resolver_->Resolve(
      info, addresses, &callback_, &outstanding_request_, BoundNetLog());
  if (error != ERR_IO_PENDING)
    OnResolveCompletion(error);  // Completed synchronously.
}

void SyncHostResolverBridge::OnResolveCompletion(int result) {
  DCHECK_EQ(host_resolver_loop_, MessageLoop::current());
  err_ = result;
  outstanding_request_ = NULL;
  event_.Signal();
}

// SingleThreadedProxyResolverUsingBridgedHostResolver -----------------------

SingleThreadedProxyResolverUsingBridgedHostResolver::
SingleThreadedProxyResolverUsingBridgedHostResolver(
    ProxyResolver* proxy_resolver,
    SyncHostResolverBridge* bridged_host_resolver)
    : SingleThreadedProxyResolver(proxy_resolver),
      bridged_host_resolver_(bridged_host_resolver) {
}

SingleThreadedProxyResolverUsingBridgedHostResolver::
~SingleThreadedProxyResolverUsingBridgedHostResolver() {
  bridged_host_resolver_->Shutdown();
}

}  // namespace net