| Index: content/browser/font_access/font_access_service_impl.cc
 | 
| diff --git a/content/browser/font_access/font_access_service_impl.cc b/content/browser/font_access/font_access_service_impl.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..6895d44869ae1a18fa8851c0a0c559f9787ff340
 | 
| --- /dev/null
 | 
| +++ b/content/browser/font_access/font_access_service_impl.cc
 | 
| @@ -0,0 +1,184 @@
 | 
| +// Copyright 2016 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/browser/font_access/font_access_service_impl.h"
 | 
| +
 | 
| +#include "base/files/file.h"
 | 
| +#include "base/files/file_path.h"
 | 
| +#include "base/files/file_util.h"
 | 
| +#include "base/sequenced_task_runner.h"
 | 
| +#include "content/browser/font_access/font_getter.h"
 | 
| +#include "content/public/browser/browser_thread.h"
 | 
| +#include "mojo/public/cpp/system/buffer.h"
 | 
| +#include "net/base/mime_util.h"
 | 
| +
 | 
| +namespace content {
 | 
| +
 | 
| +FontAccessServiceImpl::FontAccessServiceImpl(
 | 
| +    base::Callback<scoped_ptr<FontCacheMap>(void)> getter,
 | 
| +    mojo::InterfaceRequest<FontAccessService> request)
 | 
| +    : binding_(this, std::move(request)),
 | 
| +      cache_map_getter_(getter),
 | 
| +      weak_factory_(this) {}
 | 
| +
 | 
| +FontAccessServiceImpl::~FontAccessServiceImpl() {}
 | 
| +
 | 
| +void FontAccessServiceImpl::GetFontList(const GetFontListCallback& callback) {
 | 
| +  ClobberCacheAndReply(base::Bind(&FontAccessServiceImpl::GetFontListFromCache,
 | 
| +                                  weak_factory_.GetWeakPtr(), callback));
 | 
| +}
 | 
| +
 | 
| +void FontAccessServiceImpl::GetFontData(const mojo::String& family,
 | 
| +                                        const mojo::String& style,
 | 
| +                                        const GetFontDataCallback& callback) {
 | 
| +  base::FilePath path = FindPathInCache(family.get(), style.get());
 | 
| +  // If service doesn't exist, or if the cache missed.
 | 
| +  if (path.empty()) {
 | 
| +    ClobberCacheAndReply(base::Bind(&FontAccessServiceImpl::GetFontDataInternal,
 | 
| +                                    weak_factory_.GetWeakPtr(), family.get(),
 | 
| +                                    style.get(), callback));
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  BrowserThread::PostTaskAndReplyWithResult(
 | 
| +      BrowserThread::FILE, FROM_HERE,
 | 
| +      base::Bind(&FontAccessServiceImpl::GetFileInfo, path),
 | 
| +      base::Bind(&FontAccessServiceImpl::GetFileDataCallback,
 | 
| +                 weak_factory_.GetWeakPtr(), callback, path));
 | 
| +}
 | 
| +
 | 
| +void FontAccessServiceImpl::Create(
 | 
| +    mojo::InterfaceRequest<FontAccessService> request) {
 | 
| +  new FontAccessServiceImpl(base::Bind(&content::GetFontCacheMap),
 | 
| +                            std::move(request));
 | 
| +}
 | 
| +
 | 
| +FontAccessServiceImpl::BlobInfo::BlobInfo() : size(0) {}
 | 
| +
 | 
| +FontAccessServiceImpl::BlobInfo::~BlobInfo() {}
 | 
| +
 | 
| +void FontAccessServiceImpl::GetFontListFromCache(
 | 
| +    const GetFontListCallback& callback) {
 | 
| +  FontCacheMap::iterator iter;
 | 
| +  mojo::Array<FontDescriptionPtr> font_infos(0);
 | 
| +  for (auto& entry : *font_cache_map_) {
 | 
| +    for (auto& face_entry : entry.second) {
 | 
| +      FontDescriptionPtr font_ptr = FontDescription::New();
 | 
| +      font_ptr->family = entry.first;
 | 
| +      font_ptr->style = face_entry.first;
 | 
| +      font_ptr->full_name = face_entry.second.full_name;
 | 
| +      font_infos.push_back(std::move(font_ptr));
 | 
| +    }
 | 
| +  }
 | 
| +  callback.Run(std::move(font_infos));
 | 
| +}
 | 
| +
 | 
| +void FontAccessServiceImpl::GetFontDataInternal(
 | 
| +    const std::string& family,
 | 
| +    const std::string& style,
 | 
| +    const GetFontDataCallback& callback) {
 | 
| +  base::FilePath path = FindPathInCache(family, style);
 | 
| +  if (path.empty()) {
 | 
| +    callback.Run(mojo::ScopedHandleBase<mojo::SharedBufferHandle>(), 0);
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  BrowserThread::PostTaskAndReplyWithResult(
 | 
| +      BrowserThread::FILE, FROM_HERE,
 | 
| +      base::Bind(&FontAccessServiceImpl::GetFileInfo, path),
 | 
| +      base::Bind(&FontAccessServiceImpl::GetFileDataCallback,
 | 
| +                 weak_factory_.GetWeakPtr(), callback, path));
 | 
| +}
 | 
| +
 | 
| +base::FilePath FontAccessServiceImpl::FindPathInCache(
 | 
| +    const std::string& family,
 | 
| +    const std::string& style) {
 | 
| +  if (!font_cache_map_.get())
 | 
| +    return base::FilePath();
 | 
| +
 | 
| +  FontCacheMap::iterator iter;
 | 
| +  iter = font_cache_map_->find(family);
 | 
| +  if (iter != font_cache_map_->end()) {
 | 
| +    FontStyleMap::iterator face_iter;
 | 
| +    face_iter = iter->second.find(style);
 | 
| +    if (face_iter != iter->second.end()) {
 | 
| +      return face_iter->second.path;
 | 
| +    }
 | 
| +  }
 | 
| +  return base::FilePath();
 | 
| +}
 | 
| +
 | 
| +void FontAccessServiceImpl::ClobberCacheAndReply(const base::Closure closure) {
 | 
| +  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
 | 
| +  scoped_refptr<base::SequencedTaskRunner> tr = pool->GetSequencedTaskRunner(
 | 
| +      pool->GetNamedSequenceToken(std::string(kFontAccessToken)));
 | 
| +  base::PostTaskAndReplyWithResult(
 | 
| +      tr.get(), FROM_HERE, cache_map_getter_,
 | 
| +      base::Bind(&FontAccessServiceImpl::SwapCacheAndReply,
 | 
| +                 weak_factory_.GetWeakPtr(), closure));
 | 
| +}
 | 
| +
 | 
| +void FontAccessServiceImpl::SwapCacheAndReply(const base::Closure closure,
 | 
| +                                              scoped_ptr<FontCacheMap> cache) {
 | 
| +  font_cache_map_.swap(cache);
 | 
| +  closure.Run();
 | 
| +}
 | 
| +
 | 
| +// static
 | 
| +FontAccessServiceImpl::BlobInfo FontAccessServiceImpl::GetFileInfo(
 | 
| +    const base::FilePath& filepath) {
 | 
| +  DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
 | 
| +  base::File::Info info;
 | 
| +  BlobInfo real_info;
 | 
| +  real_info.is_valid = base::GetFileInfo(filepath, &info);
 | 
| +  if (!real_info.is_valid)
 | 
| +    return real_info;
 | 
| +
 | 
| +  real_info.size = info.size;
 | 
| +  real_info.last_modified = info.last_modified;
 | 
| +  net::GetMimeTypeFromFile(filepath, &real_info.mime);
 | 
| +
 | 
| +  return real_info;
 | 
| +}
 | 
| +
 | 
| +// static
 | 
| +mojo::ScopedSharedBufferHandle FontAccessServiceImpl::GetSharedBuffer(
 | 
| +    const base::FilePath& filepath,
 | 
| +    uint64_t size) {
 | 
| +  mojo::SharedBuffer buffer(size);
 | 
| +  base::File file(filepath, base::File::FLAG_OPEN | base::File::FLAG_READ);
 | 
| +  void* data;
 | 
| +  mojo::MapBuffer(buffer.handle.get(), 0, size, &data,
 | 
| +                  MOJO_MAP_BUFFER_FLAG_NONE);
 | 
| +  bool valid_read = file.Read(0, static_cast<char*>(data), size);
 | 
| +  if (!valid_read)
 | 
| +    return mojo::ScopedHandleBase<mojo::SharedBufferHandle>();
 | 
| +
 | 
| +  return std::move(buffer.handle);
 | 
| +}
 | 
| +
 | 
| +void FontAccessServiceImpl::GetFileDataCallback(
 | 
| +    const FontAccessService::GetFontDataCallback& callback,
 | 
| +    const base::FilePath& path,
 | 
| +    BlobInfo info) {
 | 
| +  if (!info.is_valid) {
 | 
| +    callback.Run(mojo::ScopedHandleBase<mojo::SharedBufferHandle>(), 0);
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  BrowserThread::PostTaskAndReplyWithResult(
 | 
| +      BrowserThread::FILE, FROM_HERE,
 | 
| +      base::Bind(&FontAccessServiceImpl::GetSharedBuffer, path, info.size),
 | 
| +      base::Bind(&FontAccessServiceImpl::PassBufferAndSize, callback,
 | 
| +                 info.size));
 | 
| +}
 | 
| +
 | 
| +void FontAccessServiceImpl::PassBufferAndSize(
 | 
| +    const FontAccessService::GetFontDataCallback& callback,
 | 
| +    uint64_t size,
 | 
| +    mojo::ScopedSharedBufferHandle handle) {
 | 
| +  callback.Run(std::move(handle), size);
 | 
| +}
 | 
| +
 | 
| +}  // content
 | 
| 
 |