/*
 * Copyright 2011 Google Inc.
 *
 * 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.
 */

// Author: sligocki@google.com (Shawn Ligocki)

#include "pagespeed/automatic/proxy_fetch.h"

#include <algorithm>
#include <cstddef>

#include "base/logging.h"
#include "net/instaweb/config/rewrite_options_manager.h"
#include "net/instaweb/http/public/cache_url_async_fetcher.h"
#include "net/instaweb/http/public/log_record.h"
#include "net/instaweb/http/public/logging_proto_impl.h"
#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/public/global_constants.h"
#include "net/instaweb/rewriter/public/blink_util.h"
#include "net/instaweb/rewriter/public/domain_rewrite_filter.h"
#include "net/instaweb/rewriter/public/experiment_matcher.h"
#include "net/instaweb/rewriter/public/experiment_util.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "net/instaweb/rewriter/public/url_namer.h"
#include "net/instaweb/util/public/fallback_property_page.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/callback.h"
#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/ref_counted_ptr.h"
#include "pagespeed/kernel/base/request_trace.h"
#include "pagespeed/kernel/base/stl_util.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/http/content_type.h"
#include "pagespeed/kernel/http/google_url.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"
#include "pagespeed/kernel/thread/queued_alarm.h"
#include "pagespeed/kernel/thread/thread_synchronizer.h"
#include "pagespeed/opt/logging/request_timing_info.h"

namespace net_instaweb {

const char ProxyFetch::kCollectorConnectProxyFetchFinish[] =
    "CollectorConnectProxyFetchFinish";
const char ProxyFetch::kCollectorDetachFinish[] = "CollectorDetachFinish";
const char ProxyFetch::kCollectorDoneFinish[] = "CollectorDoneFinish";
const char ProxyFetch::kCollectorFinish[] = "CollectorFinish";
const char ProxyFetch::kCollectorDetachStart[] = "CollectorDetachStart";
const char ProxyFetch::kCollectorRequestHeadersCompleteFinish[] =
    "kCollectorRequestHeadersCompleteFinish";

const char ProxyFetch::kHeadersSetupRaceAlarmQueued[] =
    "HeadersSetupRace:AlarmQueued";
const char ProxyFetch::kHeadersSetupRaceDone[] = "HeadersSetupRace:Done";
const char ProxyFetch::kHeadersSetupRaceFlush[] = "HeadersSetupRace:Flush";
const char ProxyFetch::kHeadersSetupRacePrefix[] = "HeadersSetupRace:";
const char ProxyFetch::kHeadersSetupRaceWait[] = "HeadersSetupRace:Wait";

ProxyFetchFactory::ProxyFetchFactory(ServerContext* server_context)
    : server_context_(server_context),
      timer_(server_context->timer()),
      handler_(server_context->message_handler()),
      outstanding_proxy_fetches_mutex_(
          server_context->thread_system()->NewMutex()) {
}

ProxyFetchFactory::~ProxyFetchFactory() {
  // Factory should outlive all fetches.
  DCHECK(outstanding_proxy_fetches_.empty());
  // Note: access to the set-size is not mutexed but in theory we should
  // be quiesced by this point.
  LOG(INFO) << "ProxyFetchFactory exiting with "
            << outstanding_proxy_fetches_.size()
            << " outstanding requests.";
}

ProxyFetch* ProxyFetchFactory::CreateNewProxyFetch(
    const GoogleString& url_in, AsyncFetch* async_fetch,
    RewriteDriver* driver,
    ProxyFetchPropertyCallbackCollector* property_callback,
    AsyncFetch* original_content_fetch) {
  const GoogleString* url_to_fetch = &url_in;

  // Check whether this an encoding of a non-rewritten resource served
  // from a non-transparently proxied domain.
  UrlNamer* namer = server_context_->url_namer();
  GoogleString decoded_resource;
  GoogleUrl gurl(url_in), request_origin;
  DCHECK(!server_context_->IsPagespeedResource(gurl))
      << "expect ResourceFetch called for pagespeed resources, not ProxyFetch";

  bool cross_domain = false;
  if (gurl.IsWebValid()) {
    if (namer->Decode(gurl, driver->options(), &request_origin,
                      &decoded_resource)) {
      const RewriteOptions* options = driver->options();
      if (namer->IsAuthorized(gurl, *options)) {
        // The URL is proxied, but is not rewritten as a pagespeed resource,
        // so don't try to do the cache-lookup or URL fetch without stripping
        // the proxied portion.
        url_to_fetch = &decoded_resource;
        cross_domain = true;
        namer->PrepForCrossDomain(async_fetch);
      } else {
        async_fetch->response_headers()->SetStatusAndReason(
            HttpStatus::kForbidden);
        driver->Cleanup();
        if (property_callback != NULL) {
          property_callback->Detach(HttpStatus::kForbidden);
        }
        async_fetch->Done(false);
        if (original_content_fetch != NULL) {
          original_content_fetch->Done(false);
        }
        return NULL;
      }
    }
  }

  ProxyFetch* fetch = new ProxyFetch(
      *url_to_fetch, cross_domain, property_callback, async_fetch,
      original_content_fetch, driver, server_context_, timer_, this);
  if (cross_domain) {
    // If we're proxying resources from a different domain, the host header is
    // likely set to the proxy host rather than the origin host.  Depending on
    // the origin, this will not work: it will not expect to see
    // the Proxy Host in its headers.
    fetch->request_headers()->RemoveAll(HttpAttributes::kHost);

    // The domain is also supposed to be cookieless, so enforce not
    // sending any cookies to origin, as a precaution against contamination.
    fetch->request_headers()->RemoveAll(HttpAttributes::kCookie);
    fetch->request_headers()->RemoveAll(HttpAttributes::kCookie2);

    // Similarly we don't want to forward authorization, since we may end up
    // forwarding it to wrong host. For proxy-authorization, we remove it here
    // since if our own server implements it, it should do so before touching
    // ProxyInterface, and this prevents it from accidentally leaking.
    // TODO(morlovich): Should we also change 401 and 407 into a 403 on
    // response?
    fetch->request_headers()->RemoveAll(HttpAttributes::kAuthorization);
    fetch->request_headers()->RemoveAll(HttpAttributes::kProxyAuthorization);
  } else {
    // If we didn't already remove all the cookies, remove the experiment
    // ones so we don't confuse the origin.
    experiment::RemoveExperimentCookie(fetch->request_headers());
  }
  RegisterNewFetch(fetch);
  return fetch;
}

void ProxyFetchFactory::StartNewProxyFetch(
    const GoogleString& url_in, AsyncFetch* async_fetch,
    RewriteDriver* driver,
    ProxyFetchPropertyCallbackCollector* property_callback,
    AsyncFetch* original_content_fetch) {
  ProxyFetch* fetch = CreateNewProxyFetch(
      url_in, async_fetch, driver, property_callback, original_content_fetch);
  if (fetch != NULL) {
    fetch->StartFetch();
  }
}

void ProxyFetchFactory::RegisterNewFetch(ProxyFetch* fetch) {
  ScopedMutex lock(outstanding_proxy_fetches_mutex_.get());
  outstanding_proxy_fetches_.insert(fetch);
}

void ProxyFetchFactory::RegisterFinishedFetch(ProxyFetch* fetch) {
  ScopedMutex lock(outstanding_proxy_fetches_mutex_.get());
  outstanding_proxy_fetches_.erase(fetch);
}

ProxyFetchPropertyCallback::ProxyFetchPropertyCallback(
    PageType page_type,
    PropertyCache* property_cache,
    const StringPiece& url,
    const StringPiece& options_signature_hash,
    UserAgentMatcher::DeviceType device_type,
    ProxyFetchPropertyCallbackCollector* collector,
    AbstractMutex* mutex)
    : PropertyPage(
          page_type,
          url,
          options_signature_hash,
          UserAgentMatcher::DeviceTypeSuffix(device_type),
          collector->request_context(),
          mutex,
          property_cache),
      page_type_(page_type),
      collector_(collector) {
}

bool ProxyFetchPropertyCallback::IsCacheValid(int64 write_timestamp_ms) const {
  return collector_->IsCacheValid(write_timestamp_ms);
}

void ProxyFetchPropertyCallback::Done(bool success) {
  collector_->Done(this);
}

ProxyFetchPropertyCallbackCollector::ProxyFetchPropertyCallbackCollector(
    ServerContext* server_context, const StringPiece& url,
    const RequestContextPtr& request_ctx, const RewriteOptions* options,
    UserAgentMatcher::DeviceType device_type)
    : mutex_(server_context->thread_system()->NewMutex()),
      server_context_(server_context),
      sequence_(server_context_->html_workers()->NewSequence()),
      url_(url.data(), url.size()),
      request_context_(request_ctx),
      device_type_(device_type),
      is_options_valid_(true),
      detached_(false),
      done_(false),
      request_headers_ok_(false),
      proxy_fetch_(NULL),
      options_(options),
      status_code_(HttpStatus::kUnknownStatusCode) {
}

ProxyFetchPropertyCallbackCollector::~ProxyFetchPropertyCallbackCollector() {
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  server_context_->html_workers()->FreeSequence(sequence_);
  if (!post_lookup_task_vector_.empty()) {
    LOG(DFATAL) << "ProxyFetchPropertyCallbackCollector function vector is not "
                << "empty.";
  }
  STLDeleteElements(&pending_callbacks_);
  STLDeleteValues(&property_pages_);

  // Following sync point is added to make sure that thread in which unit-tests
  // are running will not get finished before deleting
  // ProxyFetchPropertyCallbackCollector.  In production binaries, these are
  // no-op.
  sync->Signal(ProxyFetch::kCollectorFinish);
}

void ProxyFetchPropertyCallbackCollector::AddCallback(
    ProxyFetchPropertyCallback* callback) {
  ScopedMutex lock(mutex_.get());
  pending_callbacks_.insert(callback);
}

PropertyPage* ProxyFetchPropertyCallbackCollector::ReleasePropertyPage(
    ProxyFetchPropertyCallback::PageType page_type) {
  ScopedMutex lock(mutex_.get());
  if (property_pages_.find(page_type) != property_pages_.end()) {
    PropertyPage* page = property_pages_[page_type];
    property_pages_[page_type] = NULL;
    return page;
  }
  return NULL;
}

bool ProxyFetchPropertyCallbackCollector::IsCacheValid(
    int64 write_timestamp_ms) const {
  ScopedMutex lock(mutex_.get());
  // Since PropertyPage::CallDone is not yet called, we know that
  // ProxyFetchPropertyCallbackCollector::Done is not called and hence done_ is
  // false and hence this has not yet been deleted. We can't DCHECK this though
  // since we're not on sequence_.
  // But Detach might have been called already and then options_ is not valid.
  if (!is_options_valid_) {
    return false;
  }
  return (options_ == NULL ||
          options_->IsUrlCacheValid(url_, write_timestamp_ms,
                                    true /* search_wildcards */));
}

// Calls to Done(), RequestHeadersComplete(), ConnectProxyFetch(), and Detach()
// may occur on different threads.  But they are scheduled on a sequence to
// avoid races across these functions.
void ProxyFetchPropertyCallbackCollector::Done(
    ProxyFetchPropertyCallback* callback) {
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  sequence_->Add(MakeFunction(
      this, &ProxyFetchPropertyCallbackCollector::ExecuteDone, callback));

  // No class variable is safe to use beyond this point.
  // Used in tests to block the test thread after Done() is called.
  sync->Wait(ProxyFetch::kCollectorDoneFinish);
}

void ProxyFetchPropertyCallbackCollector::ExecuteDone(
    ProxyFetchPropertyCallback* callback) {
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  pending_callbacks_.erase(callback);
  property_pages_[callback->page_type()] = callback;
  if (pending_callbacks_.empty()) {
    DCHECK(request_context_.get() != NULL);
    request_context_->mutable_timing_info()->PropertyCacheLookupFinished();
    PropertyPage* actual_page = ReleasePropertyPage(
        PropertyPage::kPropertyCachePage);
    if (actual_page != NULL) {
      // TODO(jmarantz): Now that there is no more client property cache,
      // is it necessary to do this test?
      // Compose the primary and fallback property pages into a
      // FallbackPropertyPage, so filters can use the fallback property in the
      // absence of the primary.
      PropertyPage* fallback_page = ReleasePropertyPage(
          PropertyPage::kPropertyCacheFallbackPage);
      fallback_property_page_.reset(
          new FallbackPropertyPage(actual_page, fallback_page));
    }

    origin_property_page_.reset(
        ReleasePropertyPage(PropertyPage::kPropertyCachePerOriginPage));

    done_ = true;

    // This should be called only after fallback property page is set because
    // there can be post lookup task which requires fallback_property_page.
    RunPostLookupsAndCleanupIfSafe();
  }

  // No class variable is safe to use beyond this point.
  sync->Signal(ProxyFetch::kCollectorDoneFinish);
}

void ProxyFetchPropertyCallbackCollector::RunPostLookupsAndCleanupIfSafe() {
  if (!done_ || !request_headers_ok_) {
    return;
  }

  for (int i = 0, n = post_lookup_task_vector_.size(); i < n; ++i) {
    post_lookup_task_vector_[i]->CallRun();
  }
  post_lookup_task_vector_.clear();

  if (proxy_fetch_ != NULL) {
    // ConnectProxyFetch() is already called.
    proxy_fetch_->PropertyCacheComplete(this);  // deletes this.
  } else if (detached_) {
    // Detach() is already called.
    UpdateStatusCodeInPropertyCache();
    delete this;
  }
}

void ProxyFetchPropertyCallbackCollector::RequestHeadersComplete() {
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  sequence_->Add(MakeFunction(
      this,
      &ProxyFetchPropertyCallbackCollector::ExecuteRequestHeadersComplete));

  // No class variable is safe to use beyond this point.
  // Simulate this method being synchronous in unit tests
  sync->Wait(ProxyFetch::kCollectorRequestHeadersCompleteFinish);
}

void ProxyFetchPropertyCallbackCollector::ExecuteRequestHeadersComplete() {
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  request_headers_ok_ = true;
  RunPostLookupsAndCleanupIfSafe();

  // No class variable is safe to use beyond this point.
  sync->Signal(ProxyFetch::kCollectorRequestHeadersCompleteFinish);
}

void ProxyFetchPropertyCallbackCollector::ConnectProxyFetch(
    ProxyFetch* proxy_fetch) {
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  sequence_->Add(MakeFunction(
      this,
      &ProxyFetchPropertyCallbackCollector::ExecuteConnectProxyFetch,
      proxy_fetch));
  // Used in tests to block the test thread after ConnectProxyFetch() is called.
  sync->Wait(ProxyFetch::kCollectorConnectProxyFetchFinish);
}

void ProxyFetchPropertyCallbackCollector::ExecuteConnectProxyFetch(
    ProxyFetch* proxy_fetch) {
  DCHECK(proxy_fetch_ == NULL);
  DCHECK(!detached_);
  proxy_fetch_ = proxy_fetch;

  // Use global options in case options is NULL.
  const RewriteOptions* options =
      options_ != NULL ? options_ : server_context_->global_options();

  if (!options->await_pcache_lookup()) {
    std::set<ProxyFetchPropertyCallback*>::iterator iter;
    for (iter = pending_callbacks_.begin(); iter != pending_callbacks_.end();
         ++iter) {
      // Finish all the PropertyCache lookups as soon as possible as origin
      // starts sending content.
      (*iter)->FastFinishLookup();
    }
  }
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  if (done_) {
    // Done() is already called.
    proxy_fetch->PropertyCacheComplete(this);  // deletes this.
  }

  // No class variable is safe to use beyond this point.
  sync->Signal(ProxyFetch::kCollectorConnectProxyFetchFinish);
}

void ProxyFetchPropertyCallbackCollector::UpdateStatusCodeInPropertyCache() {
  // If we have not transferred the ownership of PagePropertyCache to
  // ProxyFetch yet, and we have the status code, then write the status_code in
  // PropertyCache.
  AbstractPropertyPage* page = fallback_property_page();
  if (page == NULL || status_code_ == HttpStatus::kUnknownStatusCode) {
    return;
  }
  page->UpdateValue(
      server_context_->dom_cohort(), RewriteDriver::kStatusCodePropertyName,
      IntegerToString(status_code_));
  page->WriteCohort(server_context_->dom_cohort());
}

void ProxyFetchPropertyCallbackCollector::Detach(HttpStatus::Code status_code) {
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  {
    ScopedMutex lock(mutex_.get());
    is_options_valid_ = false;
  }
  sequence_->Add(MakeFunction(
      this, &ProxyFetchPropertyCallbackCollector::ExecuteDetach, status_code));
  // Used in tests to block the test thread after Detach() is called.
  sync->Wait(ProxyFetch::kCollectorDetachFinish);
}

void ProxyFetchPropertyCallbackCollector::ExecuteDetach(
    HttpStatus::Code status_code) {
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  sync->Wait(ProxyFetch::kCollectorDetachStart);

  DCHECK(!detached_);
  detached_ = true;
  proxy_fetch_ = NULL;
  status_code_ = status_code;

  for (int i = 0, n = post_lookup_task_vector_.size(); i < n; ++i) {
    post_lookup_task_vector_[i]->CallCancel();
  }
  post_lookup_task_vector_.clear();

  if (done_) {
    // Done is already called.
    UpdateStatusCodeInPropertyCache();
    delete this;
  }
  // No class variable is safe to use beyond this point.
  sync->Signal(ProxyFetch::kCollectorDetachFinish);
}

void ProxyFetchPropertyCallbackCollector::AddPostLookupTask(Function* func) {
  sequence_->Add(MakeFunction(
      this,
      &ProxyFetchPropertyCallbackCollector::ExecuteAddPostLookupTask,
      func));
}

void ProxyFetchPropertyCallbackCollector::ExecuteAddPostLookupTask(
    Function* func) {
  DCHECK(!detached_);
  if (done_ && request_headers_ok_) {
    // Already done is called, run the task immediately.
    func->CallRun();
    return;
  }

  // Queue the task.
  post_lookup_task_vector_.push_back(func);
}

ProxyFetch::ProxyFetch(
    const GoogleString& url,
    bool cross_domain,
    ProxyFetchPropertyCallbackCollector* property_cache_callback,
    AsyncFetch* async_fetch,
    AsyncFetch* original_content_fetch,
    RewriteDriver* driver,
    ServerContext* server_context,
    Timer* timer,
    ProxyFetchFactory* factory)
    : SharedAsyncFetch(async_fetch),
      url_(url),
      server_context_(server_context),
      timer_(timer),
      cross_domain_(cross_domain),
      claims_html_(false),
      started_parse_(false),
      parse_text_called_(false),
      done_called_(false),
      property_cache_callback_(property_cache_callback),
      original_content_fetch_(original_content_fetch),
      driver_(driver),
      queue_run_job_created_(false),
      mutex_(server_context->thread_system()->NewMutex()),
      network_flush_outstanding_(false),
      sequence_(NULL),
      done_outstanding_(false),
      finishing_(false),
      done_result_(false),
      waiting_for_flush_to_finish_(false),
      idle_alarm_(NULL),
      factory_(factory),
      distributed_fetch_(false),
      trusted_input_(false) {
  driver_->SetWriter(async_fetch);
  set_request_headers(async_fetch->request_headers());
  set_response_headers(async_fetch->response_headers());

  // Was this proxy_fetch created on behalf of a distributed rewrite? Note: We
  // don't verify the distributed rewrite key because we want to be conservative
  // about when we apply rewriting.
  if (request_headers()->Has(HttpAttributes::kXPsaDistributedRewriteFetch) ||
      request_headers()->Has(HttpAttributes::kXPsaDistributedRewriteForHtml)) {
    distributed_fetch_ = true;
  }

  DCHECK(driver_->request_headers() != NULL);
  driver_->EnableBlockingRewrite(request_headers());

  // Set the implicit cache ttl and the min cache ttl for the response headers
  // based on the value specified in the options.
  response_headers()->set_implicit_cache_ttl_ms(
      Options()->implicit_cache_ttl_ms());
  response_headers()->set_min_cache_ttl_ms(
      Options()->min_cache_ttl_ms());

  VLOG(1) << "Attaching RewriteDriver " << driver_
          << " to HtmlRewriter " << this;
}

ProxyFetch::~ProxyFetch() {
  DCHECK(done_called_) << "Callback should be called before destruction";
  DCHECK(!queue_run_job_created_);
  DCHECK(!network_flush_outstanding_);
  DCHECK(!done_outstanding_);
  DCHECK(!waiting_for_flush_to_finish_);
  DCHECK(text_queue_.empty());
  DCHECK(property_cache_callback_ == NULL);
}

bool ProxyFetch::StartParse() {
  // The response headers get munged between when we initially determine
  // which rewrite options we need (in proxy_interface.cc) and here.
  // Therefore, we can not set the Set-Cookie header there, and must
  // do it here instead.
  if (Options()->need_to_store_experiment_data() &&
      Options()->running_experiment()) {
    int experiment_value = Options()->experiment_id();
    server_context_->experiment_matcher()->StoreExperimentData(
        experiment_value, url_,
        server_context_->timer()->NowMs() +
            Options()->experiment_cookie_duration_ms(),
        response_headers());
  }
  driver_->set_response_headers_ptr(response_headers());
  {
    // PropertyCacheComplete checks sequence_ to see whether it should
    // start processing queued text, so we need to mutex-protect it.
    // Often we expect the PropertyCache lookup to complete before
    // StartParse is called, but that is not guaranteed.
    ScopedMutex lock(mutex_.get());
    sequence_ = driver_->html_worker();
  }

  // Start parsing.
  // TODO(sligocki): Allow calling StartParse with GoogleUrl.
  if (!driver_->StartParse(url_)) {
    // We don't expect this to ever fail.
    LOG(ERROR) << "StartParse failed for URL: " << url_;
    return false;
  } else {
    VLOG(1) << "Parse successfully started.";
    return true;
  }
}

const RewriteOptions* ProxyFetch::Options() {
  return driver_->options();
}

void ProxyFetch::HandleHeadersComplete() {
  const RewriteOptions* options = Options();
  if ((response_headers() != NULL) &&
      options->Enabled(RewriteOptions::kRewriteDomains) &&
      (options->domain_rewrite_hyperlinks() ||
       options->domain_rewrite_cookies())) {
    GoogleUrl gurl(url_);

    // We will need to update the Location: and set-cookie headers.
    // We have to do it here rather than relying on normal rewriting
    // via DomainRewriteFilter since that does not run for redirects
    // when there is no content in the HTML.
    //
    // Similarly other non-200s may have cookies, so may also need patching.
    // (200s will get handled by DomainRewriteFilter via normal rewriting).
    DomainRewriteFilter::UpdateDomainHeaders(
        gurl, server_context_, options, response_headers());
    response_headers()->ComputeCaching();
  }

  // If domain rewrite filter is enabled we need to also rewrite the location
  // headers when origin is serving redirects.
  // TODO(matterbury): Consider other 3xx responses.
  // [but note that doing this for 304 Not Modified is probably a dumb idea]
  if (response_headers() != NULL &&
      (response_headers()->status_code() == HttpStatus::kFound ||
       response_headers()->status_code() == HttpStatus::kMovedPermanently)) {
    const char* loc = response_headers()->Lookup1(HttpAttributes::kLocation);
    if (loc != NULL && !driver_->pagespeed_query_params().empty()) {
      GoogleUrl base_url(url_);
      GoogleUrl locn_url(base_url, loc);
      // Only add them back if we're being redirected back to the same domain.
      if (base_url.Origin() == locn_url.Origin()) {
        // TODO(jmarantz): Add a method to GoogleUrl that makes this easy.
        GoogleString new_loc(loc);
        StrAppend(&new_loc, locn_url.has_query() ? "&" : "?",
                  driver_->pagespeed_query_params());
        response_headers()->Replace(HttpAttributes::kLocation, new_loc);
        response_headers()->ComputeCaching();
      }
    }
  }

  // Set or clear sticky option cookies as appropriate.
  if (response_headers() != NULL) {
    GoogleUrl gurl(url_);
    driver_->SetOrClearPageSpeedOptionCookies(gurl, response_headers());
  }

  // Figure out semantic info from response_headers_
  claims_html_ = response_headers()->IsHtmlLike();
  if (original_content_fetch_ != NULL && !trusted_input_) {
    ResponseHeaders* headers = original_content_fetch_->response_headers();
    headers->CopyFrom(*response_headers());

    if (!server_context_->ProxiesHtml() && claims_html_) {
      LOG(DFATAL) << "Investigate how servers that don't proxy HTML can be "
                     "initiated with original_content_fetch_ non-null";
      headers->SetStatusAndReason(HttpStatus::kForbidden);
    }
    original_content_fetch_->HeadersComplete();
  }

  bool sanitize = cross_domain_;
  if (claims_html_ && !server_context_->ProxiesHtml() && !trusted_input_) {
    response_headers()->SetStatusAndReason(HttpStatus::kForbidden);
    sanitize = true;
  }

  // Make sure we never serve cookies if the domain we are serving
  // under isn't the domain of the origin.
  if (sanitize) {
    // ... by calling Sanitize to remove them.
    bool changed = response_headers()->Sanitize();
    if (changed) {
      response_headers()->ComputeCaching();
    }
  }

  // We do not call SharedAsyncFetch::HandleHeadersComplete() because
  // we are going to defer propagating headers to the HTTP server
  // infrastructure until we have seen some content.  For example if
  // we may not add a X-PageSpeed header if we don't sniff HTML.
  //
  // Another reason is convert_meta_tags, in which we alter HTTP response
  // headers based on HTML meta-tags.
  //
  // However we want to propagate whether the content size is known to
  // the base fetch.
  PropagateContentLength();
}

void ProxyFetch::AddPagespeedHeader() {
  if (Options()->enabled()) {
    response_headers()->Add(kPageSpeedHeader, Options()->x_header_value());
    response_headers()->ComputeCaching();
  }
}

void ProxyFetch::SetupForHtml() {
  const RewriteOptions* options = Options();

  if (options->enabled() && options->IsAllowed(url_) && !distributed_fetch_) {
    // Note that we guard with distributed_fetch_ to avoid parsing HTML on a
    // distributed task, that's left to the ingress task to do.
    started_parse_ = StartParse();
    if (started_parse_) {
      // TODO(sligocki): Get these in the main flow.
      // Add, remove and update headers as appropriate.
      int64 ttl_ms;
      GoogleString cache_control_suffix;
      if ((options->max_html_cache_time_ms() == 0) ||
          response_headers()->HasValue(
              HttpAttributes::kCacheControl, "no-cache") ||
          response_headers()->HasValue(
              HttpAttributes::kCacheControl, "must-revalidate")) {
        ttl_ms = 0;
        cache_control_suffix = ", no-cache";
        // Preserve values like no-store and no-transform.
        cache_control_suffix +=
            response_headers()->CacheControlValuesToPreserve();
      } else {
        ttl_ms = std::min(options->max_html_cache_time_ms(),
                          response_headers()->cache_ttl_ms());
        // TODO(sligocki): We defensively set Cache-Control: private, but if
        // original HTML was publicly cacheable, we should be able to set
        // the rewritten HTML as publicly cacheable likewise.
        // NOTE: If we do allow "public", we need to deal with other
        // Cache-Control quantifiers, like "proxy-revalidate".
        cache_control_suffix = ", private";
      }

      // When testing, wait a little here for unit tests to make sure
      // we don't race ahead & run filters while we are still cleaning
      // up headers.  When this particular bug is fixed,
      // HeadersComplete will *not* be called on async_fetch_ until
      // after this function returns, so we'd block indefinitely.
      // Instead, block just for 200ms so the test can pass with
      // limited delay.  Note that this is a no-op except in test
      // ProxyInterfaceTest.FiltersRaceSetup which enables thread-sync
      // prefix "HeadersSetupRace:".
      ThreadSynchronizer* sync = server_context_->thread_synchronizer();
      sync->Signal(kHeadersSetupRaceWait);
      sync->TimedWait(kHeadersSetupRaceFlush, kTestSignalTimeoutMs);

      response_headers()->SetDateAndCaching(
          response_headers()->date_ms(), ttl_ms, cache_control_suffix);
      // TODO(sligocki): Support Etags and/or Last-Modified.
      response_headers()->RemoveAll(HttpAttributes::kEtag);
      response_headers()->RemoveAll(HttpAttributes::kLastModified);

      // HTML sizes are likely to be altered by HTML rewriting.
      response_headers()->RemoveAll(HttpAttributes::kContentLength);

      // TODO(sligocki): See mod_instaweb.cc line 528, which strips Expires and
      // Content-MD5.  Perhaps we should do that here as well.
    }
  }
}

void ProxyFetch::StartFetch() {
  factory_->server_context_->rewrite_options_manager()->PrepareRequest(
      Options(),
      request_context(),
      &url_,
      request_headers(),
      NewCallback(this, &ProxyFetch::DoFetch));
}

void ProxyFetch::DoFetch(bool prepare_success) {
  if (property_cache_callback_ != NULL) {
    property_cache_callback_->RequestHeadersComplete();
  }

  if (!prepare_success) {
    Done(false);
    return;
  }

  const RewriteOptions* options = driver_->options();
  const bool is_allowed = options->IsAllowed(url_);
  const bool is_enabled = options->enabled();
  {
    ScopedMutex lock(log_record()->mutex());
    if (!is_allowed) {
      log_record()->logging_info()->set_is_url_disallowed(true);
    }
    if (!is_enabled) {
      log_record()->logging_info()->set_is_request_disabled(true);
    }
  }

  if (is_enabled && is_allowed) {
    // Pagespeed enabled on URL.
    if (options->in_place_rewriting_enabled()) {
      // For Ajax rewrites, we go through RewriteDriver to give it
      // a chance to optimize resources. (If they are HTML, it will
      // not touch them, and we will stream them to the parser here).
      driver_->FetchResource(url_, this);
      return;
    }
    // Otherwise we just do a normal fetch from cache, and if it's
    // HTML we will do a streaming rewrite.
  } else {
    // Pagespeed disabled on URL.
    if (options->reject_blacklisted()) {
      // We were asked to error out in this case.
      response_headers()->SetStatusAndReason(
          options->reject_blacklisted_status_code());
      Done(true);
      return;
    } else if (cross_domain_ && !is_allowed) {
      // If we find a cross domain request that is blacklisted, send a 302
      // redirect to the decoded url instead of doing a passthrough.
      response_headers()->Add(HttpAttributes::kLocation, url_);
      response_headers()->SetStatusAndReason(HttpStatus::kFound);
      Done(false);
      return;
    }
    // Else we should do a passthrough. In that case, we still do a normal
    // origin fetch, but we will never rewrite anything, since
    // SetupForHtml() will re-check enabled() and IsAllowed();
  }

  cache_fetcher_.reset(driver_->CreateCacheFetcher());
  // Since we are proxying resources to user, we want to fetch it even if
  // there is a kRecentFetchNotCacheable message in the cache.
  cache_fetcher_->set_ignore_recent_fetch_failed(true);
  cache_fetcher_->Fetch(url_, factory_->handler_, this);
}

void ProxyFetch::ScheduleQueueExecutionIfNeeded() {
  mutex_->DCheckLocked();

  // Already queued -> no need to queue again.
  if (queue_run_job_created_) {
    return;
  }

  // We're waiting for any property-cache lookups and previous flushes to
  // complete, so no need to queue it here.  The queuing will happen when
  // the PropertyCache lookup is complete or from FlushDone.
  if (waiting_for_flush_to_finish_ || (property_cache_callback_ != NULL)) {
    return;
  }

  queue_run_job_created_ = true;
  sequence_->Add(MakeFunction(this, &ProxyFetch::ExecuteQueued));
}

void ProxyFetch::PropertyCacheComplete(
    ProxyFetchPropertyCallbackCollector* callback_collector) {
  driver_->TraceLiteral("PropertyCache lookup completed");
  ScopedMutex lock(mutex_.get());

  if (driver_ == NULL) {
    LOG(DFATAL) << "Expected non-null driver.";
  } else {
    // Set the page property and device property objects in the driver.
    driver_->set_fallback_property_page(
        callback_collector->ReleaseFallbackPropertyPage());
    driver_->set_origin_property_page(
        callback_collector->ReleaseOriginPropertyPage());
    driver_->set_device_type(callback_collector->device_type());
  }
  // We have to set the callback to NULL to let ScheduleQueueExecutionIfNeeded
  // proceed (it waits until it's NULL). And we have to delete it because then
  // we have no reference to it to delete it in Finish.
  if (property_cache_callback_ == NULL) {
    LOG(DFATAL) << "Expected non-null property_cache_callback_.";
  } else {
    delete property_cache_callback_;
    property_cache_callback_ = NULL;
  }
  if (sequence_ != NULL) {
    ScheduleQueueExecutionIfNeeded();
  }
}

bool ProxyFetch::HandleWrite(const StringPiece& str,
                             MessageHandler* message_handler) {
  if (claims_html_ && !server_context_->ProxiesHtml() && !trusted_input_) {
    return true;
  }

  // TODO(jmarantz): check if the server is being shut down and punt.
  if (original_content_fetch_ != NULL) {
    original_content_fetch_->Write(str, message_handler);
  }

  if (claims_html_ && !html_detector_.already_decided()) {
    if (html_detector_.ConsiderInput(str)) {
      // Figured out whether really HTML or not.
      if (html_detector_.probable_html()) {
        log_record()->SetIsHtml(true);
        if (Options()->max_html_parse_bytes() != 0) {
          SetupForHtml();
        }
      }

      // Now we're done mucking about with headers, add one noting our
      // involvement.
      AddPagespeedHeader();

      if ((property_cache_callback_ != NULL) && started_parse_) {
        // Connect the ProxyFetch in the PropertyCacheCallbackCollector.  This
        // ensures that we will not start executing HTML filters until
        // property cache lookups are complete --- we will keep collecting
        // things into our queue below, but ScheduleQueueExecutionIfNeeded will
        // wait until lookup completed before scheduling the actual parse.
        property_cache_callback_->ConnectProxyFetch(this);
      }

      // If we buffered up any bytes in previous calls, make sure to
      // release them.
      GoogleString buffer;
      html_detector_.ReleaseBuffered(&buffer);
      if (!buffer.empty()) {
        // Recurse on initial buffer of whitespace before processing
        // this call's input below.
        Write(buffer, message_handler);
      }
    } else {
      // Don't know whether HTML or not --- wait for more data.
      return true;
    }
  }

  bool ret = true;
  if (started_parse_) {
    // Buffer up all text & flushes until our worker-thread gets a chance
    // to run. Also split up HTML into manageable chunks if we get a burst,
    // as it will make it easier to insert flushes in between them in
    // ExecuteQueued(), which we want to do in order to limit memory use and
    // latency.
    size_t chunk_size = Options()->flush_buffer_limit_bytes();
    StringStarVector chunks;
    for (size_t pos = 0; pos < str.size(); pos += chunk_size) {
      GoogleString* buffer =
          new GoogleString(str.data() + pos,
                           std::min(chunk_size, str.size() - pos));
      chunks.push_back(buffer);
    }

    {
      ScopedMutex lock(mutex_.get());
      text_queue_.insert(text_queue_.end(), chunks.begin(), chunks.end());
      ScheduleQueueExecutionIfNeeded();
    }
  } else {
    ret = SharedAsyncFetch::HandleWrite(str, message_handler);
  }
  return ret;
}

bool ProxyFetch::HandleFlush(MessageHandler* message_handler) {
  // TODO(jmarantz): check if the server is being shut down and punt.

  if (claims_html_ && !html_detector_.already_decided()) {
    return true;
  }

  bool ret = true;
  if (started_parse_) {
    // Buffer up Flushes for handling in our QueuedWorkerPool::Sequence
    // in ExecuteQueued.  Note that this can re-order Flushes behind
    // pending text, and aggregate together multiple flushes received from
    // the network into one.
    if (Options()->flush_html()) {
      ScopedMutex lock(mutex_.get());
      network_flush_outstanding_ = true;
      ScheduleQueueExecutionIfNeeded();
    }
  } else {
    ret = SharedAsyncFetch::HandleFlush(message_handler);
  }
  return ret;
}

void ProxyFetch::HandleDone(bool success) {
  // TODO(jmarantz): check if the server is being shut down and punt,
  // possibly by calling Finish(false).
  if (original_content_fetch_ != NULL) {
    original_content_fetch_->Done(success);
    // Null the pointer since original_content_fetch_ is not guaranteed to exist
    // beyond this point.
    original_content_fetch_ = NULL;
  }

  bool finish = true;

  if (success) {
    if (claims_html_ && !html_detector_.already_decided()) {
      // This is an all-whitespace document, so we couldn't figure out
      // if it's HTML or not. Handle as pass-through.
      html_detector_.ForceDecision(false /* not html */);
      GoogleString buffered;
      html_detector_.ReleaseBuffered(&buffered);
      AddPagespeedHeader();
      SharedAsyncFetch::HandleHeadersComplete();
      Write(buffered, server_context_->message_handler());
    }
  } else if (!response_headers()->headers_complete()) {
    // This is a fetcher failure, like connection refused, not just an error
    // status code.
    response_headers()->SetStatusAndReason(HttpStatus::kNotFound);
  }

  VLOG(1) << "Fetch result:" << success << " " << url_
          << " : " << response_headers()->status_code();
  if (started_parse_) {
    ScopedMutex lock(mutex_.get());
    done_outstanding_ = true;
    done_result_ = success;
    ScheduleQueueExecutionIfNeeded();
    finish = false;
  }

  if (finish) {
    Finish(success);
  }
}

bool ProxyFetch::IsCachedResultValid(const ResponseHeaders& headers) {
  return OptionsAwareHTTPCacheCallback::IsCacheValid(
      url_, *Options(), request_context(), headers);
}

void ProxyFetch::FlushDone() {
  ScopedMutex lock(mutex_.get());
  DCHECK(waiting_for_flush_to_finish_);
  waiting_for_flush_to_finish_ = false;

  if (!text_queue_.empty() || network_flush_outstanding_ || done_outstanding_) {
    ScheduleQueueExecutionIfNeeded();
  }
}

void ProxyFetch::ExecuteQueued() {
  bool do_flush = false;
  bool do_finish = false;
  bool done_result = false;
  bool force_flush = false;

  size_t buffer_limit = Options()->flush_buffer_limit_bytes();
  StringStarVector v;
  {
    ScopedMutex lock(mutex_.get());
    DCHECK(!waiting_for_flush_to_finish_);

    // See if we should force a flush based on how much stuff has
    // accumulated.
    size_t total = 0;
    size_t force_flush_chunk_count = 0;  // set only if force_flush is true.
    for (size_t c = 0, n = text_queue_.size(); c < n; ++c) {
      total += text_queue_[c]->length();
      if (total >= buffer_limit) {
        force_flush = true;
        force_flush_chunk_count = c + 1;
        break;
      }
    }

    // Are we forcing a flush of some, but not all, of the queued
    // content?
    bool partial_forced_flush =
        force_flush && (force_flush_chunk_count != text_queue_.size());
    if (partial_forced_flush) {
      for (size_t c = 0; c < force_flush_chunk_count; ++c) {
        v.push_back(text_queue_[c]);
      }
      size_t old_len = text_queue_.size();
      text_queue_.erase(text_queue_.begin(),
                        text_queue_.begin() + force_flush_chunk_count);
      DCHECK_EQ(old_len, v.size() + text_queue_.size());

      // Note that in this case, since text_queue_ isn't empty,
      // the call to ScheduleQueueExecutionIfNeeded from FlushDone
      // will make us run again.
    } else {
      v.swap(text_queue_);
    }
    do_flush = network_flush_outstanding_ || force_flush;
    do_finish = done_outstanding_;
    done_result = done_result_;

    network_flush_outstanding_ = false;

    // Note that we don't clear done_outstanding_ here yet, as we
    // can only handle it if we are not also handling a flush.
    queue_run_job_created_ = false;
    if (do_flush) {
      // Stop queuing up invocations of us until the flush we will do
      // below is done.
      waiting_for_flush_to_finish_ = true;
    }
  }

  if (!parse_text_called_) {
    request_context()->mutable_timing_info()->ParsingStarted();
    parse_text_called_ = true;
  }

  // Collect all text received from the fetcher
  for (int i = 0, n = v.size(); i < n; ++i) {
    GoogleString* str = v[i];
    driver_->ParseText(*str);
    delete str;
  }
  if (do_flush) {
    if (force_flush) {
      driver_->RequestFlush();
    }
    if (driver_->flush_requested()) {
      // A flush is about to happen, so we don't want to redundantly
      // flush due to idleness.
      CancelIdleAlarm();
    } else {
      // We will not actually flush, just run through the state-machine, so
      // we want to just advance the idleness timeout.
      QueueIdleAlarm();
    }
    driver_->ExecuteFlushIfRequestedAsync(
        MakeFunction(this, &ProxyFetch::FlushDone));
  } else if (do_finish) {
    CancelIdleAlarm();
    Finish(done_result);
  } else {
    // Advance timeout.
    QueueIdleAlarm();
  }
}

void ProxyFetch::Finish(bool success) {
  ProxyFetchPropertyCallbackCollector* detach_callback = NULL;
  {
    ScopedMutex lock(mutex_.get());
    DCHECK(!waiting_for_flush_to_finish_);
    done_outstanding_ = false;
    finishing_ = true;

    // Avoid holding two locks (this->mutex_ + property_cache_callback_->mutex_)
    // by copying the pointer and detaching after unlocking this->mutex_.
    detach_callback = property_cache_callback_;
    property_cache_callback_ = NULL;
  }
  // The only way detach_callback can be non-NULL here is if the resource isn't
  // being parsed (it's not HTML) and the collector hasn't finished yet, but in
  // that case we never attached the collector to us, so when it's done it won't
  // access us, which is good since we self-delete at the end of this method.
  if (detach_callback != NULL) {
    // Set the status code only for html responses or errors in property cache.
    bool is_response_ok = response_headers()->status_code() == HttpStatus::kOK;
    bool not_html = html_detector_.already_decided() &&
        !html_detector_.probable_html();
    HttpStatus::Code status_code = HttpStatus::kUnknownStatusCode;
    if (!is_response_ok || (claims_html_ && !not_html)) {
      status_code = static_cast<HttpStatus::Code>(
          response_headers()->status_code());
    }
    detach_callback->Detach(status_code);
  }

  if (driver_ != NULL) {
    if (started_parse_) {
      driver_->FinishParseAsync(
          MakeFunction(this, &ProxyFetch::CompleteFinishParse, success));
      return;

    } else {
      // In the unlikely case that StartParse fails (invalid URL?) or the
      // resource is not HTML, we must manually mark the driver for cleanup.
      driver_->Cleanup();
      driver_ = NULL;
    }
  }

  SharedAsyncFetch::HandleDone(success);
  done_called_ = true;
  factory_->RegisterFinishedFetch(this);

  // In ProxyInterfaceTest.HeadersSetupRace, raise a signal that
  // indicates the test functionality is complete.  In other contexts
  // this is a no-op.
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  delete this;
  sync->Signal(kHeadersSetupRaceDone);
}

void ProxyFetch::CompleteFinishParse(bool success) {
  driver_ = NULL;
  // Have to call directly -- sequence is gone with driver.
  Finish(success);
}

void ProxyFetch::CancelIdleAlarm() {
  if (idle_alarm_ != NULL) {
    idle_alarm_->CancelAlarm();
    idle_alarm_ = NULL;
  }
}

void ProxyFetch::QueueIdleAlarm() {
  const RewriteOptions* options = Options();
  if (!options->flush_html() || (options->idle_flush_time_ms() <= 0)) {
    return;
  }

  CancelIdleAlarm();
  idle_alarm_ = new QueuedAlarm(
      driver_->scheduler(), sequence_,
      timer_->NowUs() + Options()->idle_flush_time_ms() * Timer::kMsUs,
      MakeFunction(this, &ProxyFetch::HandleIdleAlarm));

  // In ProxyInterfaceTest.HeadersSetupRace, raise a signal that
  // indicates the idle-callback has initiated.  In other contexts
  // this is a no-op.
  ThreadSynchronizer* sync = server_context_->thread_synchronizer();
  sync->Signal(kHeadersSetupRaceAlarmQueued);
}

void ProxyFetch::HandleIdleAlarm() {
  // Clear references to the alarm object as it will be deleted once we exit.
  idle_alarm_ = NULL;

  if (waiting_for_flush_to_finish_ || done_outstanding_ || finishing_) {
    return;
  }

  // Inject an own flush, and queue up its dispatch.
  driver_->ShowProgress("- Flush injected due to input idleness -");
  driver_->RequestFlush();
  Flush(factory_->message_handler());
}

namespace {

PropertyCache::CohortVector GetCohortList(
    bool requires_blink_cohort,
    const ServerContext* server_context) {
  PropertyCache* page_property_cache = server_context->page_property_cache();
  const PropertyCache::CohortVector cohort_list =
      page_property_cache->GetAllCohorts();
  if (requires_blink_cohort) {
    return cohort_list;
  }

  PropertyCache::CohortVector cohort_list_without_blink;
  for (int i = 0, m = cohort_list.size(); i < m; ++i) {
    if (cohort_list[i]->name() == BlinkUtil::kBlinkCohort) {
      continue;
    }
    cohort_list_without_blink.push_back(cohort_list[i]);
  }
  return cohort_list_without_blink;
}

bool UrlMightHavePropertyCacheEntry(const GoogleUrl& url) {
  const ContentType* type = NameExtensionToContentType(url.LeafSansQuery());
  if (type == NULL) {
    // No extension or unknown; could be HTML:
    //   http://www.example.com/
    //   http://www.example.com/index
    //   http://www.example.com/index.php
    return true;
  }

  // Use a complete switch-statement rather than type()->IsHtmlLike()
  // so that every time we add a new content-type we make an explicit
  // decision about whether it should induce a pcache read.
  //
  // TODO(jmarantz): currently this returns false for ".txt".  Thus we will
  // do no optimizations relying on property-cache on HTML files ending with
  // ".txt".  We should determine whether this is the right thing or not.
  switch (type->type()) {
    case ContentType::kHtml:
    case ContentType::kXhtml:
    case ContentType::kCeHtml:
      return true;
    case ContentType::kJavascript:
    case ContentType::kCss:
    case ContentType::kText:
    case ContentType::kXml:
    case ContentType::kPng:
    case ContentType::kGif:
    case ContentType::kJpeg:
    case ContentType::kSwf:
    case ContentType::kWebp:
    case ContentType::kIco:
    case ContentType::kPdf:
    case ContentType::kOther:
    case ContentType::kJson:
    case ContentType::kSourceMap:
    case ContentType::kVideo:
    case ContentType::kAudio:
    case ContentType::kOctetStream:
      return false;
  }
  LOG(DFATAL) << "URL " << url.Spec() << ": unexpected type:" << type->type()
              << "; " << type->mime_type() << "; " << type->file_extension();
  return false;
}

}  // namespace

ProxyFetchPropertyCallbackCollector*
    ProxyFetchFactory::InitiatePropertyCacheLookup(
        const bool is_resource_fetch,
        const GoogleUrl& request_url,
        ServerContext* server_context,
        RewriteOptions* options,
        AsyncFetch* async_fetch,
        const bool requires_blink_cohort) {
  if (options == NULL) {
    options = server_context->global_options();
  }
  RequestContextPtr request_ctx = async_fetch->request_context();
  DCHECK(request_ctx.get() != NULL);
  if (request_ctx->root_trace_context() != NULL) {
    request_ctx->root_trace_context()->TraceLiteral(
        "PropertyCache lookup start");
  }
  StringPiece user_agent =
      async_fetch->request_headers()->Lookup1(HttpAttributes::kUserAgent);
  UserAgentMatcher::DeviceType device_type =
      server_context->user_agent_matcher()->GetDeviceTypeForUA(user_agent);

  scoped_ptr<ProxyFetchPropertyCallbackCollector> callback_collector(
      new ProxyFetchPropertyCallbackCollector(
          server_context, request_url.Spec(), request_ctx, options,
          device_type));
  bool added_callback = false;
  PropertyPageStarVector property_callbacks;

  ProxyFetchPropertyCallback* property_callback = NULL;
  ProxyFetchPropertyCallback* fallback_property_callback = NULL;
  ProxyFetchPropertyCallback* origin_property_callback = NULL;
  PropertyCache* page_property_cache = server_context->page_property_cache();
  if (!is_resource_fetch &&
      server_context->page_property_cache()->enabled() &&
      UrlMightHavePropertyCacheEntry(request_url)) {
    GoogleString options_signature_hash;
    if (options != NULL) {
      server_context->ComputeSignature(options);
      options_signature_hash =
          server_context->GetRewriteOptionsSignatureHash(options);
    }

    // For most optimization properties, we limit ourselves to GET. POST is
    // forms, which are generally way too dynamic, and other methods are
    // likely to be some sort of RPC form rather than web browser traffic.
    if (async_fetch->request_headers()->method() == RequestHeaders::kGet) {
      AbstractMutex* mutex = server_context->thread_system()->NewMutex();
      property_callback = new ProxyFetchPropertyCallback(
          PropertyPage::kPropertyCachePage,
          page_property_cache,
          request_url.Spec(),
          options_signature_hash,
          device_type,
          callback_collector.get(),
          mutex);
      callback_collector->AddCallback(property_callback);
      added_callback = true;
      // Trigger property cache lookup for the requests which contains query
      // param as cache key without query params. The result of this lookup will
      // be used if actual property page does not contains property value.
      if (options != NULL &&
          options->use_fallback_property_cache_values()) {
        GoogleString fallback_page_url;
        if (request_url.PathAndLeaf() != "/" &&
            !request_url.PathAndLeaf().empty()) {
          // Don't bother looking up fallback properties for the root, "/",
          // since there is nothing to fall back to.
          fallback_page_url =
              FallbackPropertyPage::GetFallbackPageUrl(request_url);
        }

        if (!fallback_page_url.empty()) {
          fallback_property_callback =
              new ProxyFetchPropertyCallback(
                  PropertyPage::kPropertyCacheFallbackPage,
                  page_property_cache,
                  fallback_page_url,
                  options_signature_hash,
                  device_type,
                  callback_collector.get(),
                  server_context->thread_system()->NewMutex());
          callback_collector->AddCallback(fallback_property_callback);
        }
      }
    }

    // For site-wide properties, we want to handle POSTs as well, so form
    // results can use global info as well --- the globalness reducing
    // concerns about dynamism of forms.
    if (options != NULL && options->UsePerOriginPropertyCachePage() &&
        (async_fetch->request_headers()->method() == RequestHeaders::kGet ||
         async_fetch->request_headers()->method() == RequestHeaders::kPost)) {
      origin_property_callback = new ProxyFetchPropertyCallback(
          PropertyPage::kPropertyCachePerOriginPage,
          page_property_cache,
          request_url.Origin(),
          options_signature_hash,
          device_type,
          callback_collector.get(),
          server_context->thread_system()->NewMutex());
      callback_collector->AddCallback(origin_property_callback);
      added_callback = true;
    }
  }

  // All callbacks need to be registered before Reads to avoid race.
  PropertyCache::CohortVector cohort_list_without_blink =
      GetCohortList(false /* requires_blink_cohort */, server_context);
  if (property_callback != NULL) {
    page_property_cache->ReadWithCohorts(
        requires_blink_cohort ?
            GetCohortList(
                true /* requires_blink_cohort */, server_context) :
            cohort_list_without_blink,
            property_callback);
  }

  if (fallback_property_callback != NULL) {
    // Always read property page with fallback values without blink as there is
    // no property in BlinkCohort which can used fallback values.
    page_property_cache->ReadWithCohorts(cohort_list_without_blink,
                                         fallback_property_callback);
  }

  if (origin_property_callback != NULL) {
    page_property_cache->ReadWithCohorts(cohort_list_without_blink,
                                         origin_property_callback);
  }

  if (added_callback) {
    request_ctx->mutable_timing_info()->PropertyCacheLookupStarted();
  } else {
    callback_collector.reset(NULL);
  }
  return callback_collector.release();
}

}  // namespace net_instaweb
