| 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
|
| +
|
|
|