| Index: util/net/http_transport_win.cc
 | 
| diff --git a/util/net/http_transport_win.cc b/util/net/http_transport_win.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..fc73a10ed7017220652adb707f9431ab1e8de9ac
 | 
| --- /dev/null
 | 
| +++ b/util/net/http_transport_win.cc
 | 
| @@ -0,0 +1,158 @@
 | 
| +// Copyright 2015 The Crashpad Authors. All rights reserved.
 | 
| +//
 | 
| +// Licensed under the Apache License, Version 2.0 (the "License");
 | 
| +// you may not use this file except in compliance with the License.
 | 
| +// You may obtain a copy of the License at
 | 
| +//
 | 
| +//     http://www.apache.org/licenses/LICENSE-2.0
 | 
| +//
 | 
| +// Unless required by applicable law or agreed to in writing, software
 | 
| +// distributed under the License is distributed on an "AS IS" BASIS,
 | 
| +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
| +// See the License for the specific language governing permissions and
 | 
| +// limitations under the License.
 | 
| +
 | 
| +#include "util/net/http_transport.h"
 | 
| +
 | 
| +#include <windows.h>
 | 
| +#include <wininet.h>
 | 
| +#pragma comment(lib, "wininet.lib")
 | 
| +
 | 
| +#include "base/logging.h"
 | 
| +#include "base/strings/stringprintf.h"
 | 
| +#include "base/strings/utf_string_conversions.h"
 | 
| +
 | 
| +namespace crashpad {
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +class HTTPTransportWin final : public HTTPTransport {
 | 
| + public:
 | 
| +  HTTPTransportWin();
 | 
| +  ~HTTPTransportWin() override;
 | 
| +
 | 
| +  bool ExecuteSynchronously() override;
 | 
| +
 | 
| + private:
 | 
| +  DISALLOW_COPY_AND_ASSIGN(HTTPTransportWin);
 | 
| +};
 | 
| +
 | 
| +HTTPTransportWin::HTTPTransportWin() : HTTPTransport() {
 | 
| +}
 | 
| +
 | 
| +HTTPTransportWin::~HTTPTransportWin() {
 | 
| +}
 | 
| +
 | 
| +bool HTTPTransportWin::ExecuteSynchronously() {
 | 
| +  HINTERNET internet = InternetOpen(
 | 
| +      L"Unknown", INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0);
 | 
| +  if (!internet) {
 | 
| +    PLOG(ERROR) << "InternetOpen";
 | 
| +    return false;
 | 
| +  }
 | 
| +  URL_COMPONENTS url_components = {0};
 | 
| +  url_components.dwStructSize = sizeof(URL_COMPONENTS);
 | 
| +  std::wstring url_wide(base::UTF8ToUTF16(url()));
 | 
| +  url_components.dwSchemeLength = 1;
 | 
| +  url_components.dwHostNameLength = 1;
 | 
| +  url_components.dwUrlPathLength = 1;
 | 
| +  url_components.dwExtraInfoLength = 1;
 | 
| +  PCHECK(InternetCrackUrl(url_wide.c_str(), 0, 0, &url_components));
 | 
| +
 | 
| +  std::wstring scheme(url_components.lpszScheme, url_components.dwSchemeLength);
 | 
| +  CHECK(scheme == L"http");
 | 
| +  std::wstring host_name(url_components.lpszHostName,
 | 
| +                         url_components.dwHostNameLength);
 | 
| +  std::wstring url_path(url_components.lpszUrlPath,
 | 
| +                        url_components.dwUrlPathLength);
 | 
| +  std::wstring extra_info(url_components.lpszExtraInfo,
 | 
| +                          url_components.dwExtraInfoLength);
 | 
| +
 | 
| +  HINTERNET session = InternetConnect(internet,
 | 
| +                                      host_name.c_str(),
 | 
| +                                      INTERNET_DEFAULT_HTTP_PORT,
 | 
| +                                      nullptr,
 | 
| +                                      nullptr,
 | 
| +                                      INTERNET_SERVICE_HTTP,
 | 
| +                                      0,
 | 
| +                                      0);
 | 
| +  if (!session) {
 | 
| +    PLOG(ERROR) << "InternetConnect";
 | 
| +    return false;
 | 
| +  }
 | 
| +  const wchar_t* accept_types[] = {L"*/*", nullptr};
 | 
| +  HINTERNET request = HttpOpenRequest(session,
 | 
| +                                      base::UTF8ToUTF16(method()).c_str(),
 | 
| +                                      url_path.c_str(),
 | 
| +                                      nullptr,
 | 
| +                                      nullptr,
 | 
| +                                      accept_types,
 | 
| +                                      INTERNET_FLAG_NO_UI,
 | 
| +                                      0);
 | 
| +  if (!request) {
 | 
| +    PLOG(ERROR) << "HttpOpenRequest";
 | 
| +    return false;
 | 
| +  }
 | 
| +  std::wstring headers_as_string;
 | 
| +  for (const auto& pair : headers()) {
 | 
| +    headers_as_string += base::UTF8ToUTF16(pair.first) + L": " +
 | 
| +                         base::UTF8ToUTF16(pair.second) + L"\r\n";
 | 
| +  }
 | 
| +  if (!HttpSendRequest(request,
 | 
| +                       headers_as_string.c_str(),
 | 
| +                       headers_as_string.size(),
 | 
| +                       nullptr,  // TODO(scottmg): Support body_stream().
 | 
| +                       0)) {
 | 
| +    PLOG(ERROR) << "HttpSendRequest";
 | 
| +    return false;
 | 
| +  }
 | 
| +  DWORD status_code_buffer = 0;
 | 
| +  DWORD sizeof_status_code_buffer = sizeof(sizeof_status_code_buffer);
 | 
| +  DWORD query_index = 0;
 | 
| +  if (!HttpQueryInfo(request,
 | 
| +                     HTTP_QUERY_STATUS_CODE,
 | 
| +                     &status_code_buffer,
 | 
| +                     &sizeof_status_code_buffer,
 | 
| +                     &query_index)) {
 | 
| +    PLOG(ERROR) << "HttpQueryInfo";
 | 
| +    return false;
 | 
| +  }
 | 
| +  if (status_code_buffer != 200) {
 | 
| +    PLOG(ERROR) << base::StringPrintf("HTTP status %ld", status_code_buffer);
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  char read_buffer[4 << 10];
 | 
| +  DWORD bytes_read = 0;
 | 
| +  while (InternetReadFile(
 | 
| +      request, &read_buffer, sizeof(read_buffer), &bytes_read)) {
 | 
| +    if (bytes_read == 0)
 | 
| +      break;
 | 
| +    // TODO(scottmg): Do we need the response?
 | 
| +  }
 | 
| +
 | 
| +  if (!InternetCloseHandle(request)) {
 | 
| +    PLOG(ERROR) << "InternetCloseHandle(request)";
 | 
| +    return false;
 | 
| +  }
 | 
| +  if (!InternetCloseHandle(session)) {
 | 
| +    PLOG(ERROR) << "InternetCloseHandle(request)";
 | 
| +    return false;
 | 
| +  }
 | 
| +  if (!InternetCloseHandle(internet)) {
 | 
| +    PLOG(ERROR) << "InternetCloseHandle(request)";
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +// static
 | 
| +scoped_ptr<HTTPTransport> HTTPTransport::Create() {
 | 
| +  return scoped_ptr<HTTPTransportWin>(new HTTPTransportWin);
 | 
| +}
 | 
| +
 | 
| +}  // namespace crashpad
 | 
| +
 | 
| 
 |