CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(
    CefRefPtr<CefBrowser> browser,
    CefRefPtr<CefFrame> frame,
    CefRefPtr<CefRequest> request) {
  CEF_REQUIRE_IO_THREAD();

  std::string url = request->GetURL();
  if (url.find(kTestOrigin) == 0) {
    // Handle URLs in the test origin.
    std::string file_name, mime_type;
    if (ParseTestUrl(url, &file_name, &mime_type)) {
      if (file_name == "request.html") {
        // Show the request contents.
        std::string dump;
        DumpRequestContents(request, dump);
        std::string str = "<html><body bgcolor=\"white\"><pre>" + dump +
                          "</pre></body></html>";
        CefRefPtr<CefStreamReader> stream =
            CefStreamReader::CreateForData(
                static_cast<void*>(const_cast<char*>(str.c_str())),
                str.size());
        DCHECK(stream.get());
        return new CefStreamResourceHandler("text/html", stream);
      } else {
        // Load the resource from file.
        CefRefPtr<CefStreamReader> stream =
            GetBinaryResourceReader(file_name.c_str());
        if (stream.get())
          return new CefStreamResourceHandler(mime_type, stream);
      }
    }
  }

  return NULL;
}
bool LocalSchemeHandler::ReadResponse(void* dataOut, int bytesToRead, int& bytesRead, CefRefPtr<CefCallback> callback)
{
    CEF_REQUIRE_IO_THREAD();
        
    bool hasData = false;
    bytesRead = 0;
    
    if (m_pData != NULL)
    {
        if (m_offset < m_size)
        {
            // copy the next block of data into the buffer
            int transferSize = std::min(bytesToRead, m_size - m_offset);
            memcpy(dataOut, m_pData + m_offset, transferSize);
            m_offset += transferSize;
            
            bytesRead = transferSize;
            hasData = true;
        }
        
        if (m_offset >= m_size)
        {
            delete[] m_pData;
            m_pData = NULL;
        }
    }
    
    return hasData;
}
bool LocalSchemeHandler::ProcessRequest(CefRefPtr<CefRequest> request, CefRefPtr<CefCallback> callback)
{
    CEF_REQUIRE_IO_THREAD();
        
    String url = request->GetURL();
    Error err;
    m_pData = NULL;
    
    // remove query and hash parts
    String::size_type posQuery = url.find(TEXT("?"));
    String::size_type posHash = url.find(TEXT("#"));
    String::size_type len = String::npos;

    if (posQuery != String::npos && posHash != String::npos)
        len = std::min(posQuery, posHash);
    else if (posQuery != String::npos)
        len = posQuery;
    else if (posHash != String::npos)
        len = posHash;
    
    // the URL is prefixed with "local://"
    FileUtil::ReadFileBinary(DecodeURL(url.substr(8, len - 8)), &m_pData, m_size, err);
    m_mimeType = GetMIMETypeForFilename(url);

    // indicate the headers are available
    callback->Continue();
    return true;
}
bool ContentResourceHandler::ProcessRequest(CefRefPtr<CefRequest> request, CefRefPtr<CefCallback> callback)
{
	CEF_REQUIRE_IO_THREAD();

	callback->Continue();

	return true;
}
void Session::OnExpired()
{
	std::lock_guard<std::mutex> lg(m_mtx); 
	CEF_REQUIRE_IO_THREAD();

	m_cookies.clear();
	m_expried = true;
}
void LocalSchemeHandler::GetResponseHeaders(CefRefPtr<CefResponse> response, int64& responseLength, CefString& redirectUrl)
{
    CEF_REQUIRE_IO_THREAD();
        
    response->SetMimeType(m_mimeType);
    response->SetStatus(m_pData == NULL ? 404 : 200);

    responseLength = m_size;
}
void ContentResourceHandler::Cancel()
{
	CEF_REQUIRE_IO_THREAD();

	if (m_file)
	{
		m_file->Close();
		m_file = nullptr;
	}
}
bool ClientHandler::OnQuotaRequest(CefRefPtr<CefBrowser> browser,
                                   const CefString& origin_url,
                                   int64 new_size,
                                   CefRefPtr<CefQuotaCallback> callback) {
  CEF_REQUIRE_IO_THREAD();

  static const int64 max_size = 1024 * 1024 * 20;  // 20mb.

  // Grant the quota request if the size is reasonable.
  callback->Continue(new_size <= max_size);
  return true;
}
bool ContentResourceHandler::ReadResponse(void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr<CefCallback> callback)
{
	CEF_REQUIRE_IO_THREAD();

	if (m_file->IsEndOfFile())
	{
		return false;
	}

	bytes_read = m_file->Read(data_out, bytes_to_read);

	return true;
}
void ContentResourceHandler::GetResponseHeaders(CefRefPtr<CefResponse> response, int64& response_length, CefString& redirectUrl)
{
	CEF_REQUIRE_IO_THREAD();

	if (!m_mimeType.empty())
	{
		response->SetMimeType(m_mimeType);
	}

	response->SetStatus(200);
	response->SetStatusText("OK");

	response_length = m_fileSize;
}
bool ClientHandler::OnBeforePopup(CefRefPtr<CefBrowser> browser,
                                  CefRefPtr<CefFrame> frame,
                                  const CefString& target_url,
                                  const CefString& target_frame_name,
                                  const CefPopupFeatures& popupFeatures,
                                  CefWindowInfo& windowInfo,
                                  CefRefPtr<CefClient>& client,
                                  CefBrowserSettings& settings,
                                  bool* no_javascript_access) {
  CEF_REQUIRE_IO_THREAD();

  if (browser->GetHost()->IsWindowRenderingDisabled()) {
    // Cancel popups in off-screen rendering mode.
    return true;
  }
  return false;
}
void LocalSchemeHandler::Cancel()
{
    CEF_REQUIRE_IO_THREAD();
}
/**
 * Return a new scheme handler instance to handle the request.
 */
CefRefPtr<CefResourceHandler> LocalSchemeHandlerFactory::Create(
    CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& schemeName, CefRefPtr<CefRequest> request)
{
    CEF_REQUIRE_IO_THREAD();
    return new LocalSchemeHandler();
}