// Copyright (c) 2012 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "libcef/browser/net/internal_scheme_handler.h"

#include <string>
#include <utility>

#include "libcef/common/content_client.h"

#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "net/base/mime_util.h"
#include "ui/base/resource/resource_bundle.h"

namespace scheme {

namespace {

base::FilePath FilePathFromASCII(const std::string& str) {
#if defined(OS_WIN)
  return base::FilePath(base::ASCIIToUTF16(str));
#else
  return base::FilePath(str);
#endif
}

std::string GetMimeType(const std::string& filename) {
  // Requests should not block on the disk!  On POSIX this goes to disk.
  // http://code.google.com/p/chromium/issues/detail?id=59849
  base::ThreadRestrictions::ScopedAllowIO allow_io;

  std::string mime_type;
  const base::FilePath& file_path = FilePathFromASCII(filename);
  if (net::GetMimeTypeFromFile(file_path, &mime_type))
    return mime_type;

  // Check for newer extensions used by internal resources but not yet
  // recognized by the mime type detector.
  const std::string& extension = CefString(file_path.FinalExtension());
  if (extension == ".woff2")
    return "application/font-woff2";

  NOTREACHED() << "No known mime type for file: " << filename.c_str();
  return "text/plain";
}

class RedirectHandler : public CefResourceHandler {
 public:
  explicit RedirectHandler(const GURL& url) : url_(url) {}

  bool Open(CefRefPtr<CefRequest> request,
            bool& handle_request,
            CefRefPtr<CefCallback> callback) override {
    // Continue immediately.
    handle_request = true;
    return true;
  }

  void GetResponseHeaders(CefRefPtr<CefResponse> response,
                          int64& response_length,
                          CefString& redirectUrl) override {
    response_length = 0;
    redirectUrl = url_.spec();
  }

  bool Read(void* data_out,
            int bytes_to_read,
            int& bytes_read,
            CefRefPtr<CefResourceReadCallback> callback) override {
    NOTREACHED();
    return false;
  }

  void Cancel() override {}

 private:
  GURL url_;

  IMPLEMENT_REFCOUNTING(RedirectHandler);
  DISALLOW_COPY_AND_ASSIGN(RedirectHandler);
};

class InternalHandler : public CefResourceHandler {
 public:
  InternalHandler(const std::string& mime_type,
                  CefRefPtr<CefStreamReader> reader,
                  int size)
      : mime_type_(mime_type), reader_(reader), size_(size) {}

  bool Open(CefRefPtr<CefRequest> request,
            bool& handle_request,
            CefRefPtr<CefCallback> callback) override {
    // Continue immediately.
    handle_request = true;
    return true;
  }

  void GetResponseHeaders(CefRefPtr<CefResponse> response,
                          int64& response_length,
                          CefString& redirectUrl) override {
    response_length = size_;

    response->SetMimeType(mime_type_);
    response->SetStatus(200);
  }

  bool Read(void* data_out,
            int bytes_to_read,
            int& bytes_read,
            CefRefPtr<CefResourceReadCallback> callback) override {
    // Read until the buffer is full or until Read() returns 0 to indicate no
    // more data.
    bytes_read = 0;
    int read = 0;
    do {
      read = static_cast<int>(
          reader_->Read(static_cast<char*>(data_out) + bytes_read, 1,
                        bytes_to_read - bytes_read));
      bytes_read += read;
    } while (read != 0 && bytes_read < bytes_to_read);

    return (bytes_read > 0);
  }

  void Cancel() override {}

 private:
  std::string mime_type_;
  CefRefPtr<CefStreamReader> reader_;
  int size_;

  IMPLEMENT_REFCOUNTING(InternalHandler);
  DISALLOW_COPY_AND_ASSIGN(InternalHandler);
};

class InternalHandlerFactory : public CefSchemeHandlerFactory {
 public:
  explicit InternalHandlerFactory(
      std::unique_ptr<InternalHandlerDelegate> delegate)
      : delegate_(std::move(delegate)) {}

  CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
                                       CefRefPtr<CefFrame> frame,
                                       const CefString& scheme_name,
                                       CefRefPtr<CefRequest> request) override {
    GURL url = GURL(request->GetURL().ToString());

    InternalHandlerDelegate::Action action;
    if (delegate_->OnRequest(browser, request, &action)) {
      if (!action.redirect_url.is_empty() && action.redirect_url.is_valid())
        return new RedirectHandler(action.redirect_url);

      if (action.mime_type.empty())
        action.mime_type = GetMimeType(url.path());

      if (!action.bytes && action.resource_id >= 0) {
        std::string str =
            ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
                action.resource_id);
        if (str.empty()) {
          NOTREACHED() << "Failed to load internal resource for id: "
                       << action.resource_id << " URL: " << url.spec().c_str();
          return nullptr;
        }
        action.bytes = base::RefCountedString::TakeString(&str);
      }

      if (action.bytes) {
        action.stream = CefStreamReader::CreateForData(
            const_cast<unsigned char*>(action.bytes->data()),
            action.bytes->size());
        action.stream_size = action.bytes->size();
      }

      if (action.stream.get()) {
        return new InternalHandler(action.mime_type, action.stream,
                                   action.stream_size);
      }
    }

    return nullptr;
  }

 private:
  std::unique_ptr<InternalHandlerDelegate> delegate_;

  IMPLEMENT_REFCOUNTING(InternalHandlerFactory);
  DISALLOW_COPY_AND_ASSIGN(InternalHandlerFactory);
};

}  // namespace

InternalHandlerDelegate::Action::Action() : stream_size(-1), resource_id(-1) {}

CefRefPtr<CefSchemeHandlerFactory> CreateInternalHandlerFactory(
    std::unique_ptr<InternalHandlerDelegate> delegate) {
  DCHECK(delegate.get());
  return new InternalHandlerFactory(std::move(delegate));
}

}  // namespace scheme
