Hello andreip,

I'd like you to do a code review.  Please execute
        g4 diff -c 9185258

or point your web browser to
        http://mondrian/9185258

to review the following code:

Change 9185258 by stevebl...@steveblock-gears3 on 2008/11/27 13:10:24 *pending*

        Adds OPHttpRequest. Mailed on behalf of Opera.
        
        R=andreip
        [email protected],[email protected]
        DELTA=455  (373 added, 5 deleted, 77 changed)
        OCL=9185258

Affected files ...

... //depot/googleclient/gears/opensource/gears/base/opera/opera_utils.cc#1 edit
... //depot/googleclient/gears/opensource/gears/base/opera/opera_utils.h#1 edit
... 
//depot/googleclient/gears/opensource/gears/localserver/opera/http_request_op.cc#1
 edit
... 
//depot/googleclient/gears/opensource/gears/localserver/opera/http_request_op.h#1
 edit

455 delta lines: 373 added, 5 deleted, 77 changed

Also consider running:
        g4 lint -c 9185258

which verifies that the changelist doesn't introduce new style violations.

If you can't do the review, please let me know as soon as possible.  During
your review, please ensure that all new code has corresponding unit tests and
that existing unit tests are updated appropriately.  Visit
http://www/eng/code_review.html for more information.

This is a semiautomated message from "g4 mail".  Complaints or suggestions?
Mail [email protected].
Change 9185258 by stevebl...@steveblock-gears3 on 2008/11/27 13:10:24 *pending*

        Adds OPHttpRequest. Note that this depends on pending CL 9135600.
        
        R=andreip
        [email protected],[email protected]
        DELTA=550  (435 added, 58 deleted, 57 changed)
        OCL=9185258

Affected files ...

... //depot/googleclient/gears/opensource/gears/base/opera/opera_utils.cc#1 edit
... //depot/googleclient/gears/opensource/gears/base/opera/opera_utils.h#1 edit
... 
//depot/googleclient/gears/opensource/gears/localserver/opera/http_request_op.cc#1
 edit
... 
//depot/googleclient/gears/opensource/gears/localserver/opera/http_request_op.h#1
 edit

==== //depot/googleclient/gears/opensource/gears/base/opera/opera_utils.cc#1 - 
c:\MyDocs\Gears3/googleclient/gears/opensource/gears/base/opera/opera_utils.cc 
====
# action=edit type=text
--- googleclient/gears/opensource/gears/base/opera/opera_utils.cc       
2008-12-16 16:39:40.000000000 +0000
+++ googleclient/gears/opensource/gears/base/opera/opera_utils.cc       
2008-12-16 15:46:58.000000000 +0000
@@ -115,18 +115,19 @@
 };
 
 // static
-OperaGearsAPI *OperaUtils::opera_api_ = NULL;
+OperaGearsApiInterface *OperaUtils::opera_api_ = NULL;
 // static
 ThreadId OperaUtils::browser_thread_ = 0;
 
 //static
-void OperaUtils::Init(OperaGearsAPI *opera_api, ThreadId browser_thread) {
+void OperaUtils::Init(OperaGearsApiInterface *opera_api,
+                      ThreadId browser_thread) {
   opera_api_ = opera_api;
   browser_thread_ = browser_thread;
 }
 
 // static
-OperaGearsAPI *OperaUtils::GetBrowserApiForGears() {
+OperaGearsApiInterface *OperaUtils::GetBrowserApiForGears() {
   assert(opera_api_ != NULL);
   return opera_api_;
 }
==== //depot/googleclient/gears/opensource/gears/base/opera/opera_utils.h#1 - 
c:\MyDocs\Gears3/googleclient/gears/opensource/gears/base/opera/opera_utils.h 
====
# action=edit type=text
--- googleclient/gears/opensource/gears/base/opera/opera_utils.h        
2008-12-16 16:39:40.000000000 +0000
+++ googleclient/gears/opensource/gears/base/opera/opera_utils.h        
2008-12-16 15:46:59.000000000 +0000
@@ -32,7 +32,7 @@
 
 #include "gears/base/common/message_queue.h"  // for ThreadId
 
-class OperaGearsAPI;
+class OperaGearsApiInterface;
 class OperaWorkerThreadInterface;
 
 class OperaUtils {
@@ -40,10 +40,10 @@
   // Called by Opera when it first loads Gears. opera_api points to an object
   // that implements the Opera API for Gears. browser_thread must be
   // set to the ID of the thread Opera runs on.
-  static void Init(OperaGearsAPI *opera_api, ThreadId browser_thread);
+  static void Init(OperaGearsApiInterface *opera_api, ThreadId browser_thread);
 
   // Returns the pointer to the Opera API for Gears.
-  static OperaGearsAPI *GetBrowserApiForGears();
+  static OperaGearsApiInterface *GetBrowserApiForGears();
 
   // Returns the ID of the thread the browser runs on.
   static ThreadId GetBrowserThreadId();
@@ -56,7 +56,7 @@
 
  private:
   // Holds the pointer to the global Opera API for Gears.
-  static OperaGearsAPI *opera_api_;
+  static OperaGearsApiInterface *opera_api_;
   // Holds the ID of the thread the browser runs on.
   static ThreadId browser_thread_;
 
==== 
//depot/googleclient/gears/opensource/gears/localserver/opera/http_request_op.cc#1
 - 
c:\MyDocs\Gears3/googleclient/gears/opensource/gears/localserver/opera/http_request_op.cc
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/localserver/opera/http_request_op.cc    
2008-11-27 13:10:19.000000000 +0000
+++ googleclient/gears/opensource/gears/localserver/opera/http_request_op.cc    
2008-12-16 16:27:10.000000000 +0000
@@ -25,72 +25,129 @@
 
 #include "gears/localserver/opera/http_request_op.h"
 
+#include <algorithm>
+#include <vector>
+
+#include "gears/base/common/byte_store.h"
+#include "gears/base/common/string_utils.h"
+#include "gears/base/common/thread_locals.h"
+#include "gears/base/common/url_utils.h"
+#include "gears/base/npapi/browser_utils.h"
+#include "gears/base/opera/opera_utils.h"
+#include "gears/base/opera/browsing_context_op.h"
+#include "gears/blob/blob_interface.h"
+#include "gears/blob/blob_stream_ie.h"
+#include "gears/blob/buffer_blob.h"
+#include "gears/localserver/common/safe_http_request.h"
 
 
//------------------------------------------------------------------------------
 // Create
 
//------------------------------------------------------------------------------
 // static
 bool HttpRequest::Create(scoped_refptr<HttpRequest>* request) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  if (OperaUtils::GetBrowserThreadId() ==
+      ThreadMessageQueue::GetInstance()->GetCurrentThreadId()) {
+    OPHttpRequest *op_request = new OPHttpRequest();
+    if (!op_request) {
+      LOG16((L"HttpRequest::Create - Create failed\n"));
+      return false;
+    }
+    request->reset(op_request);
+    return true;
+  } else {
+    return HttpRequest::CreateSafeRequest(request);
+  }
 }
 
 // static
 bool HttpRequest::CreateSafeRequest(scoped_refptr<HttpRequest>* request) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
-}
+  request->reset(new SafeHttpRequest(OperaUtils::GetBrowserThreadId()));
+  return true;
+}
+
+
+//------------------------------------------------------------------------------
+// AsyncFunctor implementation
+//------------------------------------------------------------------------------
+
+class OPHttpRequestCompletionAsyncFunctor : public AsyncFunctor {
+ public:
+  OPHttpRequestCompletionAsyncFunctor(OPHttpRequest *request)
+    : request_(request) {
+    request->Ref();
+  }
+
+  ~OPHttpRequestCompletionAsyncFunctor() {
+    request_->Unref();
+  }
+
+  virtual void Run() {
+    request_->SetComplete();
+  }
+
+ private:
+  OPHttpRequest *request_;
+};
 
 
//------------------------------------------------------------------------------
 // Construction, destruction and refcounting
 
//------------------------------------------------------------------------------
-OPHttpRequest::OPHttpRequest() {
-  // TODO(steveblock): Implement me.
-  assert(false);
+
+OPHttpRequest::OPHttpRequest()
+    : caching_behavior_(USE_ALL_CACHES),
+      redirect_behavior_(FOLLOW_ALL),
+      was_redirected_(false),
+      url_data_(NULL),
+      was_aborted_(false),
+      listener_(NULL),
+      ready_state_(UNINITIALIZED),
+      actual_data_size_(0),
+      async_(false) {
 }
 
 OPHttpRequest::~OPHttpRequest() {
-  // TODO(steveblock): Implement me.
-  assert(false);
+  if (url_data_) {
+    url_data_->OnCompleted();
+    url_data_ = NULL;
+  }
 }
 
 void OPHttpRequest::Ref() {
-  // TODO(steveblock): Implement me.
-  assert(false);
+  refcount_.Ref();
 }
 
 void OPHttpRequest::Unref() {
-  // TODO(steveblock): Implement me.
-  assert(false);
+  if (refcount_.Unref())
+    delete this;
 }
 
 
//------------------------------------------------------------------------------
 // GetReadyState
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::GetReadyState(ReadyState *state) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  *state = ready_state_;
+  return true;
 }
 
 
//------------------------------------------------------------------------------
 // GetResponseBody
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::GetResponseBody(scoped_refptr<BlobInterface>* blob) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  if (!IsInteractiveOrComplete() || was_aborted_)
+    return false;
+
+  response_body_->CreateBlob(blob);
+  return true;
 }
 
 
//------------------------------------------------------------------------------
 // GetStatus
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::GetStatus(int *status) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  if (!IsInteractiveOrComplete() || was_aborted_)
+    return false;
+  *status = response_payload_.status_code;
+  return true;
 }
 
 
//------------------------------------------------------------------------------
@@ -98,91 +155,137 @@
 // TODO(michaeln): remove this method from the interface, prefer getStatusLine
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::GetStatusText(std::string16 *status_text) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  if (!IsInteractiveOrComplete() || was_aborted_)
+    return false;
+  return ParseHttpStatusLine(response_payload_.status_line,
+                             NULL, NULL, status_text);
 }
 
 
//------------------------------------------------------------------------------
 // GetStatusLine
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::GetStatusLine(std::string16 *status_line) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  if (!IsInteractiveOrComplete() || was_aborted_)
+    return false;
+  *status_line = response_payload_.status_line;
+  return true;
 }
 
 
//------------------------------------------------------------------------------
 // WasRedirected
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::WasRedirected() {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  return IsInteractiveOrComplete() && !was_aborted_ && was_redirected_;
 }
 
 
//------------------------------------------------------------------------------
 // GetFinalUrl
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::GetFinalUrl(std::string16 *full_url) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  if (!IsInteractiveOrComplete() || was_aborted_)
+    return false;
+
+  if (WasRedirected())
+    *full_url = redirect_url_;
+  else
+    *full_url = url_;
+  return true;
 }
 
 
//------------------------------------------------------------------------------
 // GetInitialUrl
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::GetInitialUrl(std::string16 *full_url) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  *full_url = url_;  // may be empty if request has not occurred
+  return true;
 }
 
 
//------------------------------------------------------------------------------
 // Open
 
//------------------------------------------------------------------------------
-bool OPHttpRequest::Open(const char16 *method, const char16* url, bool async,
+bool OPHttpRequest::Open(const char16 *method,
+                         const char16 *url,
+                         bool async,
                          BrowsingContext *browsing_context) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  assert(!IsRelativeUrl(url));
+  if (!IsUninitialized())
+    return false;
+
+  async_ = async;
+  url_ = url;
+  if (!origin_.InitFromUrl(url)) {
+    return false;
+  }
+
+  browsing_context_.reset(static_cast<OPBrowsingContext*>(browsing_context));
+
+  added_request_headers_iter_ = added_request_headers_.end();
+
+  method_ = MakeUpperString(std::string16(method));
+
+  SetReadyState(HttpRequest::OPEN);
+  return true;
 }
 
 
//------------------------------------------------------------------------------
 // SetRequestHeader
-//------------------------------------------------------------------------------
-bool OPHttpRequest::SetRequestHeader(const char16* name, const char16* value) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+// Here we gather additional request headers to be sent.
+//------------------------------------------------------------------------------
+bool OPHttpRequest::SetRequestHeader(const char16 *name, const char16 *value) {
+  if (!IsOpen())
+    return false;
+
+  HeaderEntry new_header = HeaderEntry(name, value);
+  added_request_headers_.push_back(new_header);
+  added_request_headers_iter_ = added_request_headers_.begin();
+
+  return true;
 }
 
 
//------------------------------------------------------------------------------
 // Send
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::Send(BlobInterface *blob) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  post_data_.reset(blob ? blob : new EmptyBlob);
+  post_data_offset_ = 0;
+  if (IsPostOrPut()) {
+    std::string16 size_str;
+    if (post_data_)
+      size_str = Integer64ToString16(post_data_->Length());
+    else
+      size_str = Integer64ToString16(0);
+
+    SetRequestHeader(HttpConstants::kContentLengthHeader, size_str.c_str());
+  }
+
+  return SendImpl();
 }
 
 
//------------------------------------------------------------------------------
 // GetAllResponseHeaders
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::GetAllResponseHeaders(std::string16 *headers) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  if (!IsInteractiveOrComplete() || was_aborted_)
+    return false;
+  headers->assign(response_payload_.headers);
+  return true;
 }
 
 
//------------------------------------------------------------------------------
 // GetResponseCharset
 
//------------------------------------------------------------------------------
 std::string16 OPHttpRequest::GetResponseCharset() {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  if (url_data_) {
+    const char *charset = NULL;
+    url_data_->GetResponseCharset(&charset);
+
+    std::string16 charset16;
+    if (charset && UTF8ToString16(charset, &charset16)) {
+      return charset16;
+    }
+  }
+
+  return std::string16();
 }
 
 
//------------------------------------------------------------------------------
@@ -190,18 +293,22 @@
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::GetResponseHeader(const char16* name,
                                       std::string16 *value) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  if (!IsInteractiveOrComplete() || was_aborted_)
+    return false;
+  return response_payload_.GetHeader(name, value);
 }
 
 
//------------------------------------------------------------------------------
 // Abort
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::Abort() {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
+  if (url_data_) {
+    url_data_->OnCompleted();
+    url_data_ = NULL;
+  }
+  //g_opera->AbortUrl(url_id_);
+  was_aborted_ = true;
+  return true;
 }
 
 
//------------------------------------------------------------------------------
@@ -209,7 +316,177 @@
 
//------------------------------------------------------------------------------
 bool OPHttpRequest::SetListener(HttpListener *listener,
                                 bool enable_data_available) {
-  // TODO(steveblock): Implement me.
-  assert(false);
-  return false;
-}
+  listener_ = listener;
+  return true;
+}
+
+//------------------------------------------------------------------------------
+// GetNextAddedReqHeader
+//------------------------------------------------------------------------------
+bool OPHttpRequest::GetNextAddedReqHeader(const unsigned short **name,
+                                          const unsigned short **value) {
+  // Note that this method is only called by the browser while we are blocked 
in
+  // RequestUrl(), so SetRequestHeader can't be called between successive 
calls.
+  if (added_request_headers_iter_ == added_request_headers_.end())
+    return false;
+
+  *name = added_request_headers_iter_->first.c_str();
+  *value = added_request_headers_iter_->second.c_str();
+
+  added_request_headers_iter_++;
+
+  return true;
+}
+
+// OperaHttpRequestDataProviderInterface implementation
+const wchar_t *OPHttpRequest::GetUrl() {
+  return url_.c_str();
+}
+
+const unsigned short *OPHttpRequest::GetMethod() {
+  return method_.c_str();
+}
+
+long OPHttpRequest::GetPostData(unsigned char *buffer, long max_size) {
+  int64 read;
+  // max_size of -1 is interpreted as a query for the size of the data
+  if (max_size == -1) {
+    read = post_data_.get()->Length();
+    if (read > LONG_MAX)
+      return -1;  // -1 returned means too long for long
+  }
+  else {
+    read = post_data_.get()->Read(buffer, post_data_offset_, max_size);
+    post_data_offset_ += read;
+  }
+
+  // safe cast since max_size is a long value the return value cannot be larger
+  // than long and there is a check in the Length() calculation already
+  return (long)read;
+}
+
+// OperaHttpListenerInterface implementation
+void OPHttpRequest::OnDataReceived() {
+  if (ready_state_ == HttpRequest::OPEN) {
+    // In the OPEN state, this method should only be called after Opera has
+    // called OnRequestCreated(), so url_data_ should be set.
+    assert(url_data_);
+    DWORD status_code = url_data_->GetStatus();
+    // Initialize the payload
+    LOG16((L"OPHttpRequest::OnDataReceived (%d)\n", status_code));
+
+    response_payload_.status_code = status_code;
+
+    const char *status_line;
+    url_data_->GetStatusText(&status_line);
+    if (status_line)
+      UTF8ToString16(status_line, strlen(status_line),
+                     &response_payload_.status_line);
+
+    const char *response_headers;
+    url_data_->GetResponseHeaders(&response_headers);
+    if (response_headers)
+      UTF8ToString16(response_headers, strlen(response_headers),
+                     &response_payload_.headers);
+
+    actual_data_size_ = 0;
+    response_body_.reset(new ByteStore);
+
+    SetReadyState(HttpRequest::INTERACTIVE);
+  }
+
+  if (url_data_) {
+    const char *content;
+    unsigned long content_length;
+    url_data_->GetBodyText(&content, &content_length);
+
+    if (content_length && content) {
+      // Append the new data to the payload
+      response_body_->AddData(content, content_length);
+
+      if (listener_)
+        listener_->DataAvailable(this, response_body_->Length());
+    }
+  }
+
+  if (!url_data_ || url_data_->IsFinished()) {
+    if (async_) {
+      // TODO([email protected]): Look at ways to avoid the need for this
+      // asynchronous call.
+      AsyncRouter::GetInstance()->CallAsync(
+          ThreadMessageQueue::GetInstance()->GetCurrentThreadId(),
+          new OPHttpRequestCompletionAsyncFunctor(this));
+    }
+    else {
+      SetReadyState(HttpRequest::COMPLETE);
+    }
+
+    // reset data source so that we avoid more calls to this
+    // object after we have finised.
+    if (url_data_) {
+      url_data_->OnCompleted();
+      url_data_ = NULL;
+    }
+  }
+}
+
+OperaHttpListenerInterface::RedirectStatus OPHttpRequest::OnRedirected(
+    const unsigned short *redirect_url) {
+  bool follow = false;
+  switch (redirect_behavior_) {
+  case FOLLOW_ALL:
+    follow = true;
+    break;
+
+  case FOLLOW_NONE:
+    follow = false;
+    break;
+
+  case FOLLOW_WITHIN_ORIGIN:
+    follow = origin_.IsSameOriginAsUrl(redirect_url);
+    break;
+  }
+
+  if (!follow)
+    return OperaHttpListenerInterface::REDIRECT_STATUS_CANCEL;
+  was_redirected_ = true;
+  redirect_url_ = redirect_url;
+  return OperaHttpListenerInterface::REDIRECT_STATUS_OK;
+}
+
+void OPHttpRequest::OnError(OperaHttpListenerInterface::LoadingError err) {
+  Abort();
+}
+
+void OPHttpRequest::OnRequestCreated(OperaUrlDataInterface* data) {
+  // This method is called by Opera and data should always be non-NULL.
+  assert(data);
+  url_data_ = data;
+}
+
+void OPHttpRequest::OnRequestDestroyed() {
+  url_data_ = NULL;
+}
+
+void OPHttpRequest::SetComplete() {
+  SetReadyState(HttpRequest::COMPLETE);
+}
+
+bool OPHttpRequest::SendImpl() {
+  if (!IsOpen() || url_.empty() || !browsing_context_.get())
+    return false;
+
+  OperaGearsApiInterface *opera_api = OperaUtils::GetBrowserApiForGears();
+  opera_api->RequestUrl(browsing_context_->GetJsContext(), this, this);
+
+  return !was_aborted_;
+}
+
+void OPHttpRequest::SetReadyState(ReadyState state) {
+  if (state > ready_state_) {
+    ready_state_ = state;
+    if (listener_) {
+      listener_->ReadyStateChanged(this);
+    }
+  }
+}
==== 
//depot/googleclient/gears/opensource/gears/localserver/opera/http_request_op.h#1
 - 
c:\MyDocs\Gears3/googleclient/gears/opensource/gears/localserver/opera/http_request_op.h
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/localserver/opera/http_request_op.h     
2008-11-27 13:10:19.000000000 +0000
+++ googleclient/gears/opensource/gears/localserver/opera/http_request_op.h     
2008-12-16 16:32:58.000000000 +0000
@@ -26,12 +26,23 @@
 #ifndef GEARS_LOCALSERVER_OPERA_HTTP_REQUEST_OP_H__
 #define GEARS_LOCALSERVER_OPERA_HTTP_REQUEST_OP_H__
 
+#include <string>
+#include <vector>
+
+#include "gears/base/common/security_model.h"
+#include "gears/base/common/scoped_refptr.h"
 #include "gears/localserver/common/http_request.h"
-
+#include "gears/localserver/common/localserver_db.h"
+#include "third_party/opera/opera_callback_api.h"
 
 class BlobInterface;
-
-class OPHttpRequest : public HttpRequest {
+class ByteStore;
+class OPBrowsingContext;
+
+class OPHttpRequest
+    : public HttpRequest,
+      public OperaHttpRequestDataProviderInterface,
+      public OperaHttpListenerInterface {
  public:
   OPHttpRequest();
   virtual ~OPHttpRequest();
@@ -84,21 +95,59 @@
   virtual bool GetInitialUrl(std::string16 *full_url);
 
   // methods
-  virtual bool Open(const char16 *method, const char16* url, bool async,
+  virtual bool Open(const char16 *method,
+                    const char16 *url,
+                    bool async,
                     BrowsingContext *browsing_context);
-  virtual bool SetRequestHeader(const char16* name, const char16* value);
+  virtual bool SetRequestHeader(const char16* name, const char16 *value);
   virtual bool Send(BlobInterface* blob);
   virtual bool GetAllResponseHeaders(std::string16 *headers);
   virtual std::string16 GetResponseCharset();
-  virtual bool GetResponseHeader(const char16* name, std::string16 *header);
+  virtual bool GetResponseHeader(const char16 *name, std::string16 *header);
   virtual bool Abort();
 
   // events
-  virtual bool SetListener(HttpListener *listener, bool enable_data_available);
+  virtual bool SetListener(HttpListener *listener,
+                           bool enable_data_availbable);
+
+  // OperaHttpRequestDataProviderInterface implementation
+  virtual bool IsAsync() { return async_; }
+  virtual bool GetNextAddedReqHeader(const unsigned short **name,
+                                     const unsigned short **value);
+  virtual const wchar_t* GetUrl();
+  virtual const unsigned short* GetMethod();
+  virtual long GetPostData(unsigned char *buffer, long max_size);
+
+  // OperaHttpListenerInterface implementation
+  virtual void OnDataReceived();
+  virtual RedirectStatus OnRedirected(const unsigned short *redirect_url);
+  virtual void OnError(LoadingError err);
+  virtual void OnRequestCreated(OperaUrlDataInterface* data);
+  virtual void OnRequestDestroyed();
+
+  void SetComplete();
 
  private:
+  typedef std::pair<std::string16, std::string16> HeaderEntry;
+
+  bool SendImpl();
+  void SetReadyState(ReadyState state);
   bool IsUninitialized() { return ready_state_ == HttpRequest::UNINITIALIZED; }
   bool IsOpen() { return ready_state_ == HttpRequest::OPEN; }
+  bool IsSent() { return ready_state_ == HttpRequest::SENT; }
+  bool IsInteractive() { return ready_state_ == HttpRequest::INTERACTIVE; }
+  bool IsComplete() { return ready_state_ == HttpRequest::COMPLETE; }
+  bool IsInteractiveOrComplete() { return IsInteractive() || IsComplete(); }
+  bool IsPostOrPut() { return method_ == L"POST" || method_ == L"PUT"; }
+
+  RefCount refcount_;
+
+  // The (non-relative) request url
+  std::string16 url_;
+  SecurityOrigin origin_;
+
+  // Whether the request should be performed asynchronously
+  bool async_;
 
   // Whether to bypass caches
   CachingBehavior caching_behavior_;
@@ -109,8 +158,49 @@
   // Whether to send cookies or not
   CookieBehavior cookie_behavior_;
 
+  // The request method
+  std::string16 method_;
+
+  // The POST data
+  scoped_refptr<BlobInterface> post_data_;
+  std::string post_data_string_;
+  int64 post_data_offset_;
+
+  // Additional request headers we've been asked to send with the request
+  std::vector<HeaderEntry> added_request_headers_;
+  std::vector<HeaderEntry>::const_iterator added_request_headers_iter_;
+
   // Our XmlHttpRequest like ready state, 0 thru 4
   ReadyState ready_state_;
+
+  // Whether this request was aborted
+  bool was_aborted_;
+
+  // Whether or not we have been redirected
+  bool was_redirected_;
+
+  // If we've been redirected, the location of the redirect. If we experience
+  // a chain of redirects, this will be the last in the chain upon completion.
+  std::string16 redirect_url_;
+
+  OperaUrlDataInterface *url_data_;
+
+  // Our listener
+  HttpRequest::HttpListener *listener_;
+
+  // We populate this structure with various pieces of response data:
+  // status code, status line, headers, data
+  WebCacheDB::PayloadInfo response_payload_;
+  scoped_refptr<ByteStore> response_body_;
+
+  // The amount of data we've read into the response_payload_.data
+  // Initially the stl vector is allocated to a large size. We keep
+  // track of how much of that allocated space is actually used here.
+  size_t actual_data_size_;
+
+  // Used internally to get the document context in which to
+  // do the HTTP request.
+  scoped_refptr<OPBrowsingContext> browsing_context_;
 };
 
 #endif  // GEARS_LOCALSERVER_OPERA_HTTP_REQUEST_OP_H__

Reply via email to