chromium/ios/chrome/browser/net/model/ios_chrome_url_request_context_getter.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ios/chrome/browser/net/model/ios_chrome_url_request_context_getter.h"

#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "ios/chrome/browser/profile/model/profile_ios_io_data.h"
#include "ios/web/public/thread/web_task_traits.h"
#include "ios/web/public/thread/web_thread.h"
#include "net/cookies/cookie_store.h"

class IOSChromeURLRequestContextFactory {
 public:
  IOSChromeURLRequestContextFactory() {}

  IOSChromeURLRequestContextFactory(const IOSChromeURLRequestContextFactory&) =
      delete;
  IOSChromeURLRequestContextFactory& operator=(
      const IOSChromeURLRequestContextFactory&) = delete;

  virtual ~IOSChromeURLRequestContextFactory() {}

  // Called to create a new instance (will only be called once).
  virtual net::URLRequestContext* Create() = 0;

 protected:
};

namespace {

// ----------------------------------------------------------------------------
// Helper factories
// ----------------------------------------------------------------------------

// Factory that creates the main URLRequestContext.
class FactoryForMain : public IOSChromeURLRequestContextFactory {
 public:
  FactoryForMain(const ProfileIOSIOData* io_data,
                 ProtocolHandlerMap* protocol_handlers)
      : io_data_(io_data) {
    std::swap(protocol_handlers_, *protocol_handlers);
  }

  net::URLRequestContext* Create() override {
    io_data_->Init(&protocol_handlers_);
    return io_data_->GetMainRequestContext();
  }

 private:
  const raw_ptr<const ProfileIOSIOData> io_data_;
  ProtocolHandlerMap protocol_handlers_;
};

}  // namespace

// ----------------------------------------------------------------------------
// IOSChromeURLRequestContextGetter
// ----------------------------------------------------------------------------

IOSChromeURLRequestContextGetter::IOSChromeURLRequestContextGetter(
    std::unique_ptr<IOSChromeURLRequestContextFactory> factory)
    : factory_(std::move(factory)), url_request_context_(nullptr) {
  DCHECK(factory_);
}

IOSChromeURLRequestContextGetter::~IOSChromeURLRequestContextGetter() {
  // NotifyContextShuttingDown() must have been called.
  DCHECK(!factory_.get());
  DCHECK(!url_request_context_);
}

// Lazily create a URLRequestContext using our factory.
net::URLRequestContext*
IOSChromeURLRequestContextGetter::GetURLRequestContext() {
  DCHECK_CURRENTLY_ON(web::WebThread::IO);

  if (factory_.get()) {
    DCHECK(!url_request_context_);
    url_request_context_ = factory_->Create();
    factory_.reset();
  }

  return url_request_context_;
}

void IOSChromeURLRequestContextGetter::NotifyContextShuttingDown() {
  DCHECK_CURRENTLY_ON(web::WebThread::IO);

  factory_.reset();
  url_request_context_ = nullptr;
  URLRequestContextGetter::NotifyContextShuttingDown();
}

scoped_refptr<base::SingleThreadTaskRunner>
IOSChromeURLRequestContextGetter::GetNetworkTaskRunner() const {
  return web::GetIOThreadTaskRunner({});
}

// static
IOSChromeURLRequestContextGetter* IOSChromeURLRequestContextGetter::Create(
    const ProfileIOSIOData* io_data,
    ProtocolHandlerMap* protocol_handlers) {
  return new IOSChromeURLRequestContextGetter(
      std::make_unique<FactoryForMain>(io_data, protocol_handlers));
}