// Copyright (c) 2011 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 "content/renderer/renderer_webkitclient_impl.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/platform_file.h"
#include "base/shared_memory.h"
#include "base/utf_string_conversions.h"
#include "content/common/content_switches.h"
#include "content/common/database_util.h"
#include "content/common/file_system/webfilesystem_impl.h"
#include "content/common/file_utilities_messages.h"
#include "content/common/mime_registry_messages.h"
#include "content/common/view_messages.h"
#include "content/common/webblobregistry_impl.h"
#include "content/common/webmessageportchannel_impl.h"
#include "content/plugin/npobject_util.h"
#include "content/renderer/content_renderer_client.h"
#include "content/renderer/render_thread.h"
#include "content/renderer/render_view.h"
#include "content/renderer/renderer_webaudiodevice_impl.h"
#include "content/renderer/renderer_webidbfactory_impl.h"
#include "content/renderer/renderer_webstoragenamespace_impl.h"
#include "content/renderer/webgraphicscontext3d_command_buffer_impl.h"
#include "content/renderer/websharedworkerrepository_impl.h"
#include "googleurl/src/gurl.h"
#include "ipc/ipc_sync_message_filter.h"
#include "media/audio/audio_util.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebBlobRegistry.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebGraphicsContext3D.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKey.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKeyPath.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptValue.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageEventDispatcher.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
#include "webkit/glue/simple_webmimeregistry_impl.h"
#include "webkit/glue/webclipboard_impl.h"
#include "webkit/glue/webfileutilities_impl.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"

#if defined(OS_WIN)
#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebSandboxSupport.h"
#endif

#if defined(OS_MACOSX)
#include "content/common/font_descriptor_mac.h"
#include "content/common/font_loader_mac.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/mac/WebSandboxSupport.h"
#endif

#if defined(OS_LINUX)
#include <string>
#include <map>

#include "base/synchronization/lock.h"
#include "content/common/child_process_sandbox_support_linux.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/linux/WebSandboxSupport.h"
#endif

#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
#endif

using WebKit::WebAudioDevice;
using WebKit::WebBlobRegistry;
using WebKit::WebFileSystem;
using WebKit::WebFrame;
using WebKit::WebIDBFactory;
using WebKit::WebIDBKey;
using WebKit::WebIDBKeyPath;
using WebKit::WebKitClient;
using WebKit::WebSerializedScriptValue;
using WebKit::WebStorageArea;
using WebKit::WebStorageEventDispatcher;
using WebKit::WebStorageNamespace;
using WebKit::WebString;
using WebKit::WebURL;
using WebKit::WebVector;

//------------------------------------------------------------------------------

class RendererWebKitClientImpl::MimeRegistry
    : public webkit_glue::SimpleWebMimeRegistryImpl {
 public:
  virtual WebKit::WebString mimeTypeForExtension(const WebKit::WebString&);
  virtual WebKit::WebString mimeTypeFromFile(const WebKit::WebString&);
  virtual WebKit::WebString preferredExtensionForMIMEType(
      const WebKit::WebString&);
};

class RendererWebKitClientImpl::FileUtilities
    : public webkit_glue::WebFileUtilitiesImpl {
 public:
  virtual void revealFolderInOS(const WebKit::WebString& path);
  virtual bool getFileSize(const WebKit::WebString& path, long long& result);
  virtual bool getFileModificationTime(const WebKit::WebString& path,
                                       double& result);
  virtual base::PlatformFile openFile(const WebKit::WebString& path,
                                      int mode);
};

class RendererWebKitClientImpl::SandboxSupport
    : public WebKit::WebSandboxSupport {
 public:
#if defined(OS_WIN)
  virtual bool ensureFontLoaded(HFONT);
#elif defined(OS_MACOSX)
  virtual bool loadFont(NSFont* srcFont, ATSFontContainerRef* out);
#elif defined(OS_LINUX)
  virtual WebKit::WebString getFontFamilyForCharacters(
      const WebKit::WebUChar* characters,
      size_t numCharacters,
      const char* preferred_locale);
  virtual void getRenderStyleForStrike(
      const char* family, int sizeAndStyle, WebKit::WebFontRenderStyle* out);

 private:
  // WebKit likes to ask us for the correct font family to use for a set of
  // unicode code points. It needs this information frequently so we cache it
  // here. The key in this map is an array of 16-bit UTF16 values from WebKit.
  // The value is a string containing the correct font family.
  base::Lock unicode_font_families_mutex_;
  std::map<string16, std::string> unicode_font_families_;
#endif
};

//------------------------------------------------------------------------------

RendererWebKitClientImpl::RendererWebKitClientImpl()
    : clipboard_(new webkit_glue::WebClipboardImpl),
      mime_registry_(new RendererWebKitClientImpl::MimeRegistry),
      sandbox_support_(new RendererWebKitClientImpl::SandboxSupport),
      sudden_termination_disables_(0),
      shared_worker_repository_(new WebSharedWorkerRepositoryImpl) {
}

RendererWebKitClientImpl::~RendererWebKitClientImpl() {
}

//------------------------------------------------------------------------------

WebKit::WebClipboard* RendererWebKitClientImpl::clipboard() {
  return clipboard_.get();
}

WebKit::WebMimeRegistry* RendererWebKitClientImpl::mimeRegistry() {
  return mime_registry_.get();
}

WebKit::WebFileUtilities* RendererWebKitClientImpl::fileUtilities() {
  if (!file_utilities_.get()) {
    file_utilities_.reset(new FileUtilities);
    file_utilities_->set_sandbox_enabled(sandboxEnabled());
  }
  return file_utilities_.get();
}

WebKit::WebSandboxSupport* RendererWebKitClientImpl::sandboxSupport() {
  return sandbox_support_.get();
}

WebKit::WebCookieJar* RendererWebKitClientImpl::cookieJar() {
  NOTREACHED() << "Use WebFrameClient::cookieJar() instead!";
  return NULL;
}

bool RendererWebKitClientImpl::sandboxEnabled() {
  // As explained in WebKitClient.h, this function is used to decide whether to
  // allow file system operations to come out of WebKit or not.  Even if the
  // sandbox is disabled, there's no reason why the code should act any
  // differently...unless we're in single process mode.  In which case, we have
  // no other choice.  WebKitClient.h discourages using this switch unless
  // absolutely necessary, so hopefully we won't end up with too many code paths
  // being different in single-process mode.
  return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
}

bool RendererWebKitClientImpl::SendSyncMessageFromAnyThread(
    IPC::SyncMessage* msg) {
  RenderThread* render_thread = RenderThread::current();
  if (render_thread)
    return render_thread->Send(msg);

  scoped_refptr<IPC::SyncMessageFilter> sync_msg_filter(
      ChildThread::current()->sync_message_filter());
  return sync_msg_filter->Send(msg);
}

unsigned long long RendererWebKitClientImpl::visitedLinkHash(
    const char* canonical_url,
    size_t length) {
  return content::GetContentClient()->renderer()->VisitedLinkHash(
      canonical_url, length);
}

bool RendererWebKitClientImpl::isLinkVisited(unsigned long long link_hash) {
  return content::GetContentClient()->renderer()->IsLinkVisited(link_hash);
}

WebKit::WebMessagePortChannel*
RendererWebKitClientImpl::createMessagePortChannel() {
  return new WebMessagePortChannelImpl();
}

void RendererWebKitClientImpl::prefetchHostName(const WebString& hostname) {
  if (hostname.isEmpty())
    return;

  std::string hostname_utf8;
  UTF16ToUTF8(hostname.data(), hostname.length(), &hostname_utf8);
  content::GetContentClient()->renderer()->PrefetchHostName(
      hostname_utf8.data(), hostname_utf8.length());
}

bool RendererWebKitClientImpl::CheckPreparsedJsCachingEnabled() const {
  static bool checked = false;
  static bool result = false;
  if (!checked) {
    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    result = command_line.HasSwitch(switches::kEnablePreparsedJsCaching);
    checked = true;
  }
  return result;
}

void RendererWebKitClientImpl::cacheMetadata(
    const WebKit::WebURL& url,
    double response_time,
    const char* data,
    size_t size) {
  if (!CheckPreparsedJsCachingEnabled())
    return;

  // Let the browser know we generated cacheable metadata for this resource. The
  // browser may cache it and return it on subsequent responses to speed
  // the processing of this resource.
  std::vector<char> copy(data, data + size);
  RenderThread::current()->Send(new ViewHostMsg_DidGenerateCacheableMetadata(
      url, response_time, copy));
}

WebString RendererWebKitClientImpl::defaultLocale() {
  // TODO(darin): Eliminate this webkit_glue call.
  return ASCIIToUTF16(webkit_glue::GetWebKitLocale());
}

void RendererWebKitClientImpl::suddenTerminationChanged(bool enabled) {
  if (enabled) {
    // We should not get more enables than disables, but we want it to be a
    // non-fatal error if it does happen.
    DCHECK_GT(sudden_termination_disables_, 0);
    sudden_termination_disables_ = std::max(sudden_termination_disables_ - 1,
                                            0);
    if (sudden_termination_disables_ != 0)
      return;
  } else {
    sudden_termination_disables_++;
    if (sudden_termination_disables_ != 1)
      return;
  }

  RenderThread* thread = RenderThread::current();
  if (thread)  // NULL in unittests.
    thread->Send(new ViewHostMsg_SuddenTerminationChanged(enabled));
}

WebStorageNamespace* RendererWebKitClientImpl::createLocalStorageNamespace(
    const WebString& path, unsigned quota) {
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
    return WebStorageNamespace::createLocalStorageNamespace(path, quota);
  return new RendererWebStorageNamespaceImpl(DOM_STORAGE_LOCAL);
}

void RendererWebKitClientImpl::dispatchStorageEvent(
    const WebString& key, const WebString& old_value,
    const WebString& new_value, const WebString& origin,
    const WebKit::WebURL& url, bool is_local_storage) {
  DCHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess));
  // Inefficient, but only used in single process mode.
  scoped_ptr<WebStorageEventDispatcher> event_dispatcher(
      WebStorageEventDispatcher::create());
  event_dispatcher->dispatchStorageEvent(key, old_value, new_value, origin,
                                         url, is_local_storage);
}

//------------------------------------------------------------------------------

WebIDBFactory* RendererWebKitClientImpl::idbFactory() {
  if (!web_idb_factory_.get()) {
    if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
      web_idb_factory_.reset(WebIDBFactory::create());
    else
      web_idb_factory_.reset(new RendererWebIDBFactoryImpl());
  }
  return web_idb_factory_.get();
}

void RendererWebKitClientImpl::createIDBKeysFromSerializedValuesAndKeyPath(
    const WebVector<WebSerializedScriptValue>& values,
    const WebString& keyPath,
    WebVector<WebIDBKey>& keys_out) {
  DCHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess));
  WebVector<WebIDBKey> keys(values.size());
  for (size_t i = 0; i < values.size(); ++i) {
    keys[i] = WebIDBKey::createFromValueAndKeyPath(
        values[i], WebIDBKeyPath::create(keyPath));
  }
  keys_out.swap(keys);
}

WebSerializedScriptValue
RendererWebKitClientImpl::injectIDBKeyIntoSerializedValue(const WebIDBKey& key,
    const WebSerializedScriptValue& value,
    const WebString& keyPath) {
  DCHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess));
  return WebIDBKey::injectIDBKeyIntoSerializedValue(
      key, value, WebIDBKeyPath::create(keyPath));
}

//------------------------------------------------------------------------------

WebFileSystem* RendererWebKitClientImpl::fileSystem() {
  if (!web_file_system_.get())
    web_file_system_.reset(new WebFileSystemImpl());
  return web_file_system_.get();
}

//------------------------------------------------------------------------------

WebString RendererWebKitClientImpl::MimeRegistry::mimeTypeForExtension(
    const WebString& file_extension) {
  if (IsPluginProcess())
    return SimpleWebMimeRegistryImpl::mimeTypeForExtension(file_extension);

  // The sandbox restricts our access to the registry, so we need to proxy
  // these calls over to the browser process.
  std::string mime_type;
  RenderThread::current()->Send(
      new MimeRegistryMsg_GetMimeTypeFromExtension(
          webkit_glue::WebStringToFilePathString(file_extension), &mime_type));
  return ASCIIToUTF16(mime_type);

}

WebString RendererWebKitClientImpl::MimeRegistry::mimeTypeFromFile(
    const WebString& file_path) {
  if (IsPluginProcess())
    return SimpleWebMimeRegistryImpl::mimeTypeFromFile(file_path);

  // The sandbox restricts our access to the registry, so we need to proxy
  // these calls over to the browser process.
  std::string mime_type;
  RenderThread::current()->Send(new MimeRegistryMsg_GetMimeTypeFromFile(
      FilePath(webkit_glue::WebStringToFilePathString(file_path)),
      &mime_type));
  return ASCIIToUTF16(mime_type);

}

WebString RendererWebKitClientImpl::MimeRegistry::preferredExtensionForMIMEType(
    const WebString& mime_type) {
  if (IsPluginProcess())
    return SimpleWebMimeRegistryImpl::preferredExtensionForMIMEType(mime_type);

  // The sandbox restricts our access to the registry, so we need to proxy
  // these calls over to the browser process.
  FilePath::StringType file_extension;
  RenderThread::current()->Send(
      new MimeRegistryMsg_GetPreferredExtensionForMimeType(
          UTF16ToASCII(mime_type), &file_extension));
  return webkit_glue::FilePathStringToWebString(file_extension);
}

//------------------------------------------------------------------------------

bool RendererWebKitClientImpl::FileUtilities::getFileSize(const WebString& path,
                                                       long long& result) {
  if (SendSyncMessageFromAnyThread(new FileUtilitiesMsg_GetFileSize(
          webkit_glue::WebStringToFilePath(path),
          reinterpret_cast<int64*>(&result)))) {
    return result >= 0;
  }

  result = -1;
  return false;
}

void RendererWebKitClientImpl::FileUtilities::revealFolderInOS(
    const WebString& path) {
  FilePath file_path(webkit_glue::WebStringToFilePath(path));
  file_util::AbsolutePath(&file_path);
  RenderThread::current()->Send(new ViewHostMsg_RevealFolderInOS(file_path));
}

bool RendererWebKitClientImpl::FileUtilities::getFileModificationTime(
    const WebString& path,
    double& result) {
  base::Time time;
  if (SendSyncMessageFromAnyThread(new FileUtilitiesMsg_GetFileModificationTime(
          webkit_glue::WebStringToFilePath(path), &time))) {
    result = time.ToDoubleT();
    return !time.is_null();
  }

  result = 0;
  return false;
}

base::PlatformFile RendererWebKitClientImpl::FileUtilities::openFile(
    const WebString& path,
    int mode) {
  IPC::PlatformFileForTransit handle = IPC::InvalidPlatformFileForTransit();
  SendSyncMessageFromAnyThread(new FileUtilitiesMsg_OpenFile(
      webkit_glue::WebStringToFilePath(path), mode, &handle));
  return IPC::PlatformFileForTransitToPlatformFile(handle);
}

//------------------------------------------------------------------------------

#if defined(OS_WIN)

bool RendererWebKitClientImpl::SandboxSupport::ensureFontLoaded(HFONT font) {
  LOGFONT logfont;
  GetObject(font, sizeof(LOGFONT), &logfont);
  return RenderThread::current()->Send(new ViewHostMsg_PreCacheFont(logfont));
}

#elif defined(OS_LINUX)

WebString RendererWebKitClientImpl::SandboxSupport::getFontFamilyForCharacters(
    const WebKit::WebUChar* characters,
    size_t num_characters,
    const char* preferred_locale) {
  base::AutoLock lock(unicode_font_families_mutex_);
  const string16 key(characters, num_characters);
  const std::map<string16, std::string>::const_iterator iter =
      unicode_font_families_.find(key);
  if (iter != unicode_font_families_.end())
    return WebString::fromUTF8(iter->second);

  const std::string family_name =
      child_process_sandbox_support::getFontFamilyForCharacters(
          characters,
          num_characters,
          preferred_locale);
  unicode_font_families_.insert(make_pair(key, family_name));
  return WebString::fromUTF8(family_name);
}

void RendererWebKitClientImpl::SandboxSupport::getRenderStyleForStrike(
    const char* family, int sizeAndStyle, WebKit::WebFontRenderStyle* out) {
  child_process_sandbox_support::getRenderStyleForStrike(family, sizeAndStyle,
                                                         out);
}

#elif defined(OS_MACOSX)

bool RendererWebKitClientImpl::SandboxSupport::loadFont(NSFont* srcFont,
    ATSFontContainerRef* out) {
  DCHECK(srcFont);
  DCHECK(out);

  uint32 font_data_size;
  FontDescriptor src_font_descriptor(srcFont);
  base::SharedMemoryHandle font_data;
  if (!RenderThread::current()->Send(new ViewHostMsg_LoadFont(
        src_font_descriptor, &font_data_size, &font_data))) {
    LOG(ERROR) << "Sending ViewHostMsg_LoadFont() IPC failed for " <<
        src_font_descriptor.font_name;
    *out = kATSFontContainerRefUnspecified;
    return false;
  }

  if (font_data_size == 0 || font_data == base::SharedMemory::NULLHandle()) {
    LOG(ERROR) << "Bad response from ViewHostMsg_LoadFont() for " <<
        src_font_descriptor.font_name;
    *out = kATSFontContainerRefUnspecified;
    return false;
  }

  return FontLoader::ATSFontContainerFromBuffer(font_data, font_data_size, out);
}

#endif

//------------------------------------------------------------------------------

WebKitClient::FileHandle RendererWebKitClientImpl::databaseOpenFile(
    const WebString& vfs_file_name, int desired_flags) {
  return DatabaseUtil::databaseOpenFile(vfs_file_name, desired_flags);
}

int RendererWebKitClientImpl::databaseDeleteFile(
    const WebString& vfs_file_name, bool sync_dir) {
  return DatabaseUtil::databaseDeleteFile(vfs_file_name, sync_dir);
}

long RendererWebKitClientImpl::databaseGetFileAttributes(
    const WebString& vfs_file_name) {
  return DatabaseUtil::databaseGetFileAttributes(vfs_file_name);
}

long long RendererWebKitClientImpl::databaseGetFileSize(
    const WebString& vfs_file_name) {
  return DatabaseUtil::databaseGetFileSize(vfs_file_name);
}

WebKit::WebSharedWorkerRepository*
RendererWebKitClientImpl::sharedWorkerRepository() {
  if (!CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableSharedWorkers)) {
    return shared_worker_repository_.get();
  } else {
    return NULL;
  }
}

WebKit::WebGraphicsContext3D*
RendererWebKitClientImpl::createGraphicsContext3D() {
  // The WebGraphicsContext3DInProcessImpl code path is used for
  // layout tests (though not through this code) as well as for
  // debugging and bringing up new ports.
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessWebGL)) {
    return new webkit::gpu::WebGraphicsContext3DInProcessImpl();
  } else {
#if defined(ENABLE_GPU)
    return new WebGraphicsContext3DCommandBufferImpl();
#else
    return NULL;
#endif
  }
}

double RendererWebKitClientImpl::audioHardwareSampleRate() {
    return media::GetAudioHardwareSampleRate();
}

WebAudioDevice*
RendererWebKitClientImpl::createAudioDevice(
    size_t buffer_size,
    unsigned channels,
    double sample_rate,
    WebAudioDevice::RenderCallback* callback) {
  return new RendererWebAudioDeviceImpl(buffer_size,
                                        channels,
                                        sample_rate,
                                        callback);
}

//------------------------------------------------------------------------------

WebKit::WebString RendererWebKitClientImpl::signedPublicKeyAndChallengeString(
    unsigned key_size_index,
    const WebKit::WebString& challenge,
    const WebKit::WebURL& url) {
  std::string signed_public_key;
  RenderThread::current()->Send(new ViewHostMsg_Keygen(
      static_cast<uint32>(key_size_index),
      challenge.utf8(),
      GURL(url),
      &signed_public_key));
  return WebString::fromUTF8(signed_public_key);
}

//------------------------------------------------------------------------------

WebBlobRegistry* RendererWebKitClientImpl::blobRegistry() {
  // RenderThread::current can be NULL when running some tests.
  if (!blob_registry_.get() && RenderThread::current())
    blob_registry_.reset(new WebBlobRegistryImpl(RenderThread::current()));
  return blob_registry_.get();
}
