- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / base / asynchttprequest.cc
1 /*
2  * libjingle
3  * Copyright 2004--2010, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "talk/base/asynchttprequest.h"
29
30 namespace talk_base {
31
32 enum {
33   MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE,
34   MSG_LAUNCH_REQUEST
35 };
36 static const int kDefaultHTTPTimeout = 30 * 1000;  // 30 sec
37
38 ///////////////////////////////////////////////////////////////////////////////
39 // AsyncHttpRequest
40 ///////////////////////////////////////////////////////////////////////////////
41
42 AsyncHttpRequest::AsyncHttpRequest(const std::string &user_agent)
43     : start_delay_(0),
44       firewall_(NULL),
45       port_(80),
46       secure_(false),
47       timeout_(kDefaultHTTPTimeout),
48       fail_redirect_(false),
49       factory_(Thread::Current()->socketserver(), user_agent),
50       pool_(&factory_),
51       client_(user_agent.c_str(), &pool_),
52       error_(HE_NONE) {
53   client_.SignalHttpClientComplete.connect(this,
54       &AsyncHttpRequest::OnComplete);
55 }
56
57 AsyncHttpRequest::~AsyncHttpRequest() {
58 }
59
60 void AsyncHttpRequest::OnWorkStart() {
61   if (start_delay_ <= 0) {
62     LaunchRequest();
63   } else {
64     Thread::Current()->PostDelayed(start_delay_, this, MSG_LAUNCH_REQUEST);
65   }
66 }
67
68 void AsyncHttpRequest::OnWorkStop() {
69   // worker is already quitting, no need to explicitly quit
70   LOG(LS_INFO) << "HttpRequest cancelled";
71 }
72
73 void AsyncHttpRequest::OnComplete(HttpClient* client, HttpErrorType error) {
74   Thread::Current()->Clear(this, MSG_TIMEOUT);
75
76   set_error(error);
77   if (!error) {
78     LOG(LS_INFO) << "HttpRequest completed successfully";
79
80     std::string value;
81     if (client_.response().hasHeader(HH_LOCATION, &value)) {
82       response_redirect_ = value.c_str();
83     }
84   } else {
85     LOG(LS_INFO) << "HttpRequest completed with error: " << error;
86   }
87
88   worker()->Quit();
89 }
90
91 void AsyncHttpRequest::OnMessage(Message* message) {
92   switch (message->message_id) {
93    case MSG_TIMEOUT:
94     LOG(LS_INFO) << "HttpRequest timed out";
95     client_.reset();
96     worker()->Quit();
97     break;
98    case MSG_LAUNCH_REQUEST:
99     LaunchRequest();
100     break;
101    default:
102     SignalThread::OnMessage(message);
103     break;
104   }
105 }
106
107 void AsyncHttpRequest::DoWork() {
108   // Do nothing while we wait for the request to finish. We only do this so
109   // that we can be a SignalThread; in the future this class should not be
110   // a SignalThread, since it does not need to spawn a new thread.
111   Thread::Current()->ProcessMessages(kForever);
112 }
113
114 void AsyncHttpRequest::LaunchRequest() {
115   factory_.SetProxy(proxy_);
116   if (secure_)
117     factory_.UseSSL(host_.c_str());
118
119   bool transparent_proxy = (port_ == 80) &&
120            ((proxy_.type == PROXY_HTTPS) || (proxy_.type == PROXY_UNKNOWN));
121   if (transparent_proxy) {
122     client_.set_proxy(proxy_);
123   }
124   client_.set_fail_redirect(fail_redirect_);
125   client_.set_server(SocketAddress(host_, port_));
126
127   LOG(LS_INFO) << "HttpRequest start: " << host_ + client_.request().path;
128
129   Thread::Current()->PostDelayed(timeout_, this, MSG_TIMEOUT);
130   client_.start();
131 }
132
133 }  // namespace talk_base