1// Copyright (c) 2012 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 "base/basictypes.h"
6#include "base/bind.h"
7#include "base/bind_helpers.h"
8#include "base/compiler_specific.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/message_loop/message_loop.h"
11#include "base/synchronization/waitable_event.h"
12#include "chrome/test/chromedriver/net/url_request_context_getter.h"
13#include "net/base/ip_endpoint.h"
14#include "net/base/net_errors.h"
15#include "net/base/net_log.h"
16#include "net/base/net_util.h"
17#include "net/socket/tcp_server_socket.h"
18#include "net/url_request/url_fetcher.h"
19#include "net/url_request/url_fetcher_delegate.h"
20#include "url/gurl.h"
21
22namespace {
23
24class SyncUrlFetcher : public net::URLFetcherDelegate {
25 public:
26  SyncUrlFetcher(const GURL& url,
27                 URLRequestContextGetter* getter,
28                 std::string* response)
29      : url_(url), getter_(getter), response_(response), event_(false, false) {}
30
31  virtual ~SyncUrlFetcher() {}
32
33  bool Fetch() {
34    getter_->GetNetworkTaskRunner()->PostTask(
35        FROM_HERE,
36        base::Bind(&SyncUrlFetcher::FetchOnIOThread, base::Unretained(this)));
37    event_.Wait();
38    return success_;
39  }
40
41  void FetchOnIOThread() {
42    fetcher_.reset(net::URLFetcher::Create(url_, net::URLFetcher::GET, this));
43    fetcher_->SetRequestContext(getter_);
44    fetcher_->Start();
45  }
46
47  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
48    success_ = (source->GetResponseCode() == 200);
49    if (success_)
50      success_ = source->GetResponseAsString(response_);
51    fetcher_.reset();  // Destroy the fetcher on IO thread.
52    event_.Signal();
53  }
54
55 private:
56  GURL url_;
57  URLRequestContextGetter* getter_;
58  std::string* response_;
59  base::WaitableEvent event_;
60  scoped_ptr<net::URLFetcher> fetcher_;
61  bool success_;
62};
63
64}  // namespace
65
66bool FetchUrl(const std::string& url,
67              URLRequestContextGetter* getter,
68              std::string* response) {
69  return SyncUrlFetcher(GURL(url), getter, response).Fetch();
70}
71
72bool FindOpenPort(int* port) {
73  char parts[] = {127, 0, 0, 1};
74  net::IPAddressNumber address(parts, parts + arraysize(parts));
75  net::NetLog::Source source;
76  for (int i = 0; i < 10; ++i) {
77    net::TCPServerSocket sock(NULL, source);
78    // Use port 0, so that the OS will assign an available ephemeral port.
79    if (sock.Listen(net::IPEndPoint(address, 0), 1) != net::OK)
80      continue;
81    net::IPEndPoint end_point;
82    if (sock.GetLocalAddress(&end_point) != net::OK)
83      continue;
84    *port = end_point.port();
85    return true;
86  }
87  return false;
88}
89