| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ios/web/public/test/http_server.h" | 5 #import "ios/web/public/test/http_server/http_server.h" |
| 6 | 6 |
| 7 #import <Foundation/Foundation.h> | 7 #import <Foundation/Foundation.h> |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
| 15 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServer.h" | 15 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServer.h" |
| 16 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServerResponse
.h" | 16 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServerResponse
.h" |
| 17 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Requests/GCDWebServerData
Request.h" | 17 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Requests/GCDWebServerData
Request.h" |
| 18 #import "net/base/mac/url_conversions.h" | 18 #import "net/base/mac/url_conversions.h" |
| 19 | 19 |
| 20 #include "url/gurl.h" | 20 #include "url/gurl.h" |
| 21 | 21 |
| 22 namespace { | 22 namespace { |
| 23 | 23 |
| 24 // The default port on which the GCDWebServer is brought up on. | 24 // The default port on which the GCDWebServer is brought up on. |
| 25 const NSUInteger kDefaultPort = 8080; | 25 const NSUInteger kDefaultPort = 8080; |
| 26 | 26 |
| 27 // Converts a GCDWebServerDataRequest (received from the GCDWebServer servlet) | 27 // Converts a GCDWebServerDataRequest (received from the GCDWebServer servlet) |
| 28 // to a request object that the ResponseProvider expects. | 28 // to a request object that the ResponseProvider expects. |
| 29 web::ResponseProvider::Request ResponseProviderRequestFromGCDWebServerRequest( | 29 web::ResponseProvider::Request ResponseProviderRequestFromGCDWebServerRequest( |
| 30 GCDWebServerDataRequest* request) { | 30 GCDWebServerDataRequest* request) { |
| 31 GURL url(net::GURLWithNSURL(request.URL)); | 31 GURL url(net::GURLWithNSURL(request.URL)); |
| 32 std::string method(base::SysNSStringToUTF8(request.method)); | 32 std::string method(base::SysNSStringToUTF8(request.method)); |
| 33 base::scoped_nsobject<NSString> body( | 33 base::scoped_nsobject<NSString> body([[NSString alloc] |
| 34 [[NSString alloc] initWithData:request.data | 34 initWithData:request.data |
| 35 encoding:NSUTF8StringEncoding]); | 35 encoding:NSUTF8StringEncoding]); |
| 36 __block net::HttpRequestHeaders headers; | 36 __block net::HttpRequestHeaders headers; |
| 37 [[request headers] enumerateKeysAndObjectsUsingBlock:^(NSString* header_key, | 37 [[request headers] enumerateKeysAndObjectsUsingBlock:^( |
| 38 NSString* header_value, | 38 NSString* header_key, NSString* header_value, BOOL*) { |
| 39 BOOL*) { | 39 headers.SetHeader(base::SysNSStringToUTF8(header_key), |
| 40 headers.SetHeader(base::SysNSStringToUTF8(header_key), | 40 base::SysNSStringToUTF8(header_value)); |
| 41 base::SysNSStringToUTF8(header_value)); | |
| 42 }]; | 41 }]; |
| 43 return web::ResponseProvider::Request(url, method, | 42 return web::ResponseProvider::Request(url, method, |
| 44 base::SysNSStringToUTF8(body), headers); | 43 base::SysNSStringToUTF8(body), headers); |
| 45 } | 44 } |
| 46 | 45 |
| 47 } // namespace | 46 } // namespace |
| 48 | 47 |
| 49 namespace web { | 48 namespace web { |
| 50 namespace test { | 49 namespace test { |
| 51 | 50 |
| 52 RefCountedResponseProviderWrapper::RefCountedResponseProviderWrapper( | 51 RefCountedResponseProviderWrapper::RefCountedResponseProviderWrapper( |
| 53 std::unique_ptr<ResponseProvider> response_provider) | 52 std::unique_ptr<ResponseProvider> response_provider) |
| 54 : response_provider_(std::move(response_provider)) {} | 53 : response_provider_(std::move(response_provider)) {} |
| 55 | 54 |
| 56 RefCountedResponseProviderWrapper::~RefCountedResponseProviderWrapper() {} | 55 RefCountedResponseProviderWrapper::~RefCountedResponseProviderWrapper() {} |
| 57 | 56 |
| 58 // static | 57 // static |
| 59 HttpServer& HttpServer::GetSharedInstance() { | 58 HttpServer& HttpServer::GetSharedInstance() { |
| 60 static web::test::HttpServer* shared_instance = nullptr; | 59 static web::test::HttpServer* shared_instance = nullptr; |
| 61 static dispatch_once_t once; | 60 static dispatch_once_t once; |
| 62 dispatch_once(&once, ^{ | 61 dispatch_once(&once, ^{ |
| 63 shared_instance = new HttpServer(); | 62 shared_instance = new HttpServer(); |
| 64 }); | 63 }); |
| 65 return *shared_instance; | 64 return *shared_instance; |
| 66 } | 65 } |
| 67 | 66 |
| 68 // static | 67 // static |
| 69 HttpServer& HttpServer::GetSharedInstanceWithResponseProviders( | 68 HttpServer& HttpServer::GetSharedInstanceWithResponseProviders( |
| 70 ProviderList response_providers) { | 69 ProviderList response_providers) { |
| 71 DCHECK([NSThread isMainThread]); | 70 DCHECK([NSThread isMainThread]); |
| 72 HttpServer& server = HttpServer::GetSharedInstance(); | 71 HttpServer& server = HttpServer::GetSharedInstance(); |
| 73 // Use non-const reference as the response_provider ownership is transfered. | 72 // Use non-const reference as the response_provider ownership is transfered. |
| 74 for (std::unique_ptr<ResponseProvider>& provider : response_providers) | 73 for (std::unique_ptr<ResponseProvider>& provider : response_providers) |
| 75 server.AddResponseProvider(std::move(provider)); | 74 server.AddResponseProvider(std::move(provider)); |
| 76 return server; | 75 return server; |
| 77 } | 76 } |
| 78 | 77 |
| 79 void HttpServer::InitHttpServer() { | 78 void HttpServer::InitHttpServer() { |
| 80 DCHECK(gcd_web_server_); | 79 DCHECK(gcd_web_server_); |
| 81 // Note: This block is called from an arbitrary GCD thread. | 80 // Note: This block is called from an arbitrary GCD thread. |
| 82 id process_request = | 81 id process_request = |
| 83 ^GCDWebServerResponse*(GCDWebServerDataRequest* request) { | 82 ^GCDWebServerResponse*(GCDWebServerDataRequest* request) { |
| 84 // Relax the cross-thread access restriction to non-thread-safe RefCount. | 83 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 85 // TODO(crbug.com/707010): Remove ScopedAllowCrossThreadRefCountAccess. | 84 // TODO(crbug.com/707010): Remove ScopedAllowCrossThreadRefCountAccess. |
| 86 base::ScopedAllowCrossThreadRefCountAccess | 85 base::ScopedAllowCrossThreadRefCountAccess |
| 87 allow_cross_thread_ref_count_access; | 86 allow_cross_thread_ref_count_access; |
| 88 | 87 |
| 89 ResponseProvider::Request provider_request = | 88 ResponseProvider::Request provider_request = |
| 90 ResponseProviderRequestFromGCDWebServerRequest(request); | 89 ResponseProviderRequestFromGCDWebServerRequest(request); |
| 91 scoped_refptr<RefCountedResponseProviderWrapper> | 90 scoped_refptr<RefCountedResponseProviderWrapper> |
| 92 ref_counted_response_provider = GetResponseProviderForRequest( | 91 ref_counted_response_provider = |
| 93 provider_request); | 92 GetResponseProviderForRequest(provider_request); |
| 94 | 93 |
| 95 if (!ref_counted_response_provider) { | 94 if (!ref_counted_response_provider) { |
| 96 return [GCDWebServerResponse response]; | 95 return [GCDWebServerResponse response]; |
| 97 } | 96 } |
| 98 ResponseProvider* response_provider = | 97 ResponseProvider* response_provider = |
| 99 ref_counted_response_provider->GetResponseProvider(); | 98 ref_counted_response_provider->GetResponseProvider(); |
| 100 if (!response_provider) { | 99 if (!response_provider) { |
| 101 return [GCDWebServerResponse response]; | 100 return [GCDWebServerResponse response]; |
| 102 } | 101 } |
| 103 | 102 |
| 104 return response_provider->GetGCDWebServerResponse(provider_request); | 103 return response_provider->GetGCDWebServerResponse(provider_request); |
| 105 }; | 104 }; |
| 106 [gcd_web_server_ removeAllHandlers]; | 105 [gcd_web_server_ removeAllHandlers]; |
| 107 // Register a servlet for all HTTP GET, POST methods. | 106 // Register a servlet for all HTTP GET, POST methods. |
| 108 [gcd_web_server_ addDefaultHandlerForMethod:@"GET" | 107 [gcd_web_server_ addDefaultHandlerForMethod:@"GET" |
| 109 requestClass:[GCDWebServerDataRequest class] | 108 requestClass:[GCDWebServerDataRequest class] |
| 110 processBlock:process_request]; | 109 processBlock:process_request]; |
| 111 [gcd_web_server_ addDefaultHandlerForMethod:@"POST" | 110 [gcd_web_server_ addDefaultHandlerForMethod:@"POST" |
| 112 requestClass:[GCDWebServerDataRequest class] | 111 requestClass:[GCDWebServerDataRequest class] |
| 113 processBlock:process_request]; | 112 processBlock:process_request]; |
| 114 } | 113 } |
| 115 | 114 |
| 116 HttpServer::HttpServer() : port_(0) { | 115 HttpServer::HttpServer() : port_(0) { |
| 117 gcd_web_server_.reset([[GCDWebServer alloc] init]); | 116 gcd_web_server_.reset([[GCDWebServer alloc] init]); |
| 118 InitHttpServer(); | 117 InitHttpServer(); |
| 119 } | 118 } |
| 120 | 119 |
| 121 HttpServer::~HttpServer() { | 120 HttpServer::~HttpServer() {} |
| 122 } | |
| 123 | 121 |
| 124 bool HttpServer::StartOnPort(NSUInteger port) { | 122 bool HttpServer::StartOnPort(NSUInteger port) { |
| 125 DCHECK([NSThread isMainThread]); | 123 DCHECK([NSThread isMainThread]); |
| 126 DCHECK(!IsRunning()) << "The server is already running." | 124 DCHECK(!IsRunning()) << "The server is already running." |
| 127 << " Please stop it before starting it again."; | 125 << " Please stop it before starting it again."; |
| 128 BOOL success = [gcd_web_server_ startWithPort:port bonjourName:@""]; | 126 BOOL success = [gcd_web_server_ startWithPort:port bonjourName:@""]; |
| 129 if (success) { | 127 if (success) { |
| 130 SetPort(port); | 128 SetPort(port); |
| 131 } | 129 } |
| 132 return success; | 130 return success; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 150 DCHECK([NSThread isMainThread]); | 148 DCHECK([NSThread isMainThread]); |
| 151 return [gcd_web_server_ isRunning]; | 149 return [gcd_web_server_ isRunning]; |
| 152 } | 150 } |
| 153 | 151 |
| 154 NSUInteger HttpServer::GetPort() const { | 152 NSUInteger HttpServer::GetPort() const { |
| 155 base::AutoLock autolock(port_lock_); | 153 base::AutoLock autolock(port_lock_); |
| 156 return port_; | 154 return port_; |
| 157 } | 155 } |
| 158 | 156 |
| 159 // static | 157 // static |
| 160 GURL HttpServer::MakeUrl(const std::string &url) { | 158 GURL HttpServer::MakeUrl(const std::string& url) { |
| 161 return HttpServer::GetSharedInstance().MakeUrlForHttpServer(url); | 159 return HttpServer::GetSharedInstance().MakeUrlForHttpServer(url); |
| 162 } | 160 } |
| 163 | 161 |
| 164 GURL HttpServer::MakeUrlForHttpServer(const std::string& url) const { | 162 GURL HttpServer::MakeUrlForHttpServer(const std::string& url) const { |
| 165 GURL result(url); | 163 GURL result(url); |
| 166 DCHECK(result.is_valid()); | 164 DCHECK(result.is_valid()); |
| 167 const std::string kLocalhostHost = std::string("localhost"); | 165 const std::string kLocalhostHost = std::string("localhost"); |
| 168 if (result.port() == base::IntToString(GetPort()) && | 166 if (result.port() == base::IntToString(GetPort()) && |
| 169 result.host() == kLocalhostHost) { | 167 result.host() == kLocalhostHost) { |
| 170 return result; | 168 return result; |
| 171 } | 169 } |
| 172 | 170 |
| 173 GURL::Replacements replacements; | 171 GURL::Replacements replacements; |
| 174 replacements.SetHostStr(kLocalhostHost); | 172 replacements.SetHostStr(kLocalhostHost); |
| 175 | 173 |
| 176 const std::string port = std::string( | 174 const std::string port = base::IntToString(static_cast<int>(GetPort())); |
| 177 base::IntToString(static_cast<int>(GetPort()))); | |
| 178 replacements.SetPortStr(port); | 175 replacements.SetPortStr(port); |
| 179 | 176 |
| 180 // It is necessary to prepend the host of the input URL so that URLs such | 177 // It is necessary to prepend the host of the input URL so that URLs such |
| 181 // as http://origin/foo, http://destination/foo can be disamgiguated. | 178 // as http://origin/foo, http://destination/foo can be disamgiguated. |
| 182 const std::string new_path = std::string(result.host() + result.path()); | 179 const std::string new_path = std::string(result.host() + result.path()); |
| 183 replacements.SetPathStr(new_path); | 180 replacements.SetPathStr(new_path); |
| 184 | 181 |
| 185 return result.ReplaceComponents(replacements); | 182 return result.ReplaceComponents(replacements); |
| 186 } | 183 } |
| 187 | 184 |
| 188 scoped_refptr<RefCountedResponseProviderWrapper> | 185 scoped_refptr<RefCountedResponseProviderWrapper> |
| 189 HttpServer::GetResponseProviderForRequest( | 186 HttpServer::GetResponseProviderForRequest( |
| 190 const web::ResponseProvider::Request& request) { | 187 const web::ResponseProvider::Request& request) { |
| 191 base::AutoLock autolock(provider_list_lock_); | 188 base::AutoLock autolock(provider_list_lock_); |
| 192 // Relax the cross-thread access restriction to non-thread-safe RefCount. | 189 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 193 // The lock above protects non-thread-safe RefCount in HTTPServer. | 190 // The lock above protects non-thread-safe RefCount in HTTPServer. |
| 194 base::ScopedAllowCrossThreadRefCountAccess | 191 base::ScopedAllowCrossThreadRefCountAccess |
| 195 allow_cross_thread_ref_count_access; | 192 allow_cross_thread_ref_count_access; |
| 196 scoped_refptr<RefCountedResponseProviderWrapper> result; | 193 scoped_refptr<RefCountedResponseProviderWrapper> result; |
| 197 for (const auto& ref_counted_response_provider : providers_) { | 194 for (const auto& ref_counted_response_provider : providers_) { |
| 198 ResponseProvider* response_provider = | 195 ResponseProvider* response_provider = |
| 199 ref_counted_response_provider.get()->GetResponseProvider(); | 196 ref_counted_response_provider.get()->GetResponseProvider(); |
| 200 if (response_provider->CanHandleRequest(request)) { | 197 if (response_provider->CanHandleRequest(request)) { |
| 201 DCHECK(!result) << | 198 DCHECK(!result) |
| 202 "No more than one response provider can handle the same request."; | 199 << "No more than one response provider can handle the same request."; |
| 203 result = ref_counted_response_provider; | 200 result = ref_counted_response_provider; |
| 204 } | 201 } |
| 205 } | 202 } |
| 206 return result; | 203 return result; |
| 207 } | 204 } |
| 208 | 205 |
| 209 void HttpServer::AddResponseProvider( | 206 void HttpServer::AddResponseProvider( |
| 210 std::unique_ptr<ResponseProvider> response_provider) { | 207 std::unique_ptr<ResponseProvider> response_provider) { |
| 211 DCHECK([NSThread isMainThread]); | 208 DCHECK([NSThread isMainThread]); |
| 212 DCHECK(IsRunning()) << "Can add a response provider only when the server is " | 209 DCHECK(IsRunning()) << "Can add a response provider only when the server is " |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 base::ScopedAllowCrossThreadRefCountAccess | 246 base::ScopedAllowCrossThreadRefCountAccess |
| 250 allow_cross_thread_ref_count_access; | 247 allow_cross_thread_ref_count_access; |
| 251 providers_.clear(); | 248 providers_.clear(); |
| 252 } | 249 } |
| 253 | 250 |
| 254 void HttpServer::SetPort(NSUInteger port) { | 251 void HttpServer::SetPort(NSUInteger port) { |
| 255 base::AutoLock autolock(port_lock_); | 252 base::AutoLock autolock(port_lock_); |
| 256 port_ = port; | 253 port_ = port; |
| 257 } | 254 } |
| 258 | 255 |
| 259 } // namespace test | 256 } // namespace test |
| 260 } // namespace web | 257 } // namespace web |
| OLD | NEW |