// 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 "chrome/browser/user_style_sheet_watcher.h"

#include "base/base64.h"
#include "base/bind.h"
#include "base/file_util.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"

using ::base::FilePathWatcher;
using content::BrowserThread;
using content::WebContents;

namespace {

// The subdirectory of the profile that contains the style sheet.
const char kStyleSheetDir[] = "User StyleSheets";
// The filename of the stylesheet.
const char kUserStyleSheetFile[] = "Custom.css";

}  // namespace

// UserStyleSheetLoader is responsible for loading  the user style sheet on the
// file thread and sends a notification when the style sheet is loaded. It is
// a helper to UserStyleSheetWatcher. The reference graph is as follows:
//
// .-----------------------.    owns    .-----------------.
// | UserStyleSheetWatcher |----------->| FilePathWatcher |
// '-----------------------'            '-----------------'
//             |                                 |
//             V                                 |
//  .----------------------.                     |
//  | UserStyleSheetLoader |<--------------------'
//  '----------------------'
//
// FilePathWatcher's reference to UserStyleSheetLoader is used for delivering
// the change notifications. Since they happen asynchronously,
// UserStyleSheetWatcher and its FilePathWatcher may be destroyed while a
// callback to UserStyleSheetLoader is in progress, in which case the
// UserStyleSheetLoader object outlives the watchers.
class UserStyleSheetLoader
    : public base::RefCountedThreadSafe<UserStyleSheetLoader> {
 public:
  UserStyleSheetLoader();

  GURL user_style_sheet() const {
    return user_style_sheet_;
  }

  // Load the user style sheet on the file thread and convert it to a
  // base64 URL.  Posts the base64 URL back to the UI thread.
  void LoadStyleSheet(const base::FilePath& style_sheet_file);

  // Register a callback to be called whenever the stylesheet gets updated.
  scoped_ptr<base::CallbackList<void(void)>::Subscription>
  RegisterOnStyleSheetUpdatedCallback(const base::Closure& callback);

  // Send out a notification if the stylesheet has already been loaded.
  void NotifyLoaded();

  // FilePathWatcher::Callback method:
  void NotifyPathChanged(const base::FilePath& path, bool error);

 private:
  friend class base::RefCountedThreadSafe<UserStyleSheetLoader>;
  ~UserStyleSheetLoader();

  // Called on the UI thread after the stylesheet has loaded.
  void SetStyleSheet(const GURL& url);

  // The user style sheet as a base64 data:// URL.
  GURL user_style_sheet_;

  // Whether the stylesheet has been loaded.
  bool has_loaded_;

  base::CallbackList<void(void)> style_sheet_updated_callbacks_;

  DISALLOW_COPY_AND_ASSIGN(UserStyleSheetLoader);
};

UserStyleSheetLoader::UserStyleSheetLoader()
    : has_loaded_(false) {
}

UserStyleSheetLoader::~UserStyleSheetLoader() {
}

scoped_ptr<base::CallbackList<void(void)>::Subscription>
UserStyleSheetLoader::RegisterOnStyleSheetUpdatedCallback(
    const base::Closure& callback) {
  return style_sheet_updated_callbacks_.Add(callback);
}

void UserStyleSheetLoader::NotifyLoaded() {
  if (has_loaded_) {
    style_sheet_updated_callbacks_.Notify();
  }
}

void UserStyleSheetLoader::NotifyPathChanged(const base::FilePath& path,
                                             bool error) {
  if (!error)
    LoadStyleSheet(path);
}

void UserStyleSheetLoader::LoadStyleSheet(
    const base::FilePath& style_sheet_file) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  // We keep the user style sheet in a subdir so we can watch for changes
  // to the file.
  base::FilePath style_sheet_dir = style_sheet_file.DirName();
  if (!base::DirectoryExists(style_sheet_dir)) {
    if (!file_util::CreateDirectory(style_sheet_dir))
      return;
  }
  // Create the file if it doesn't exist.
  if (!base::PathExists(style_sheet_file))
    file_util::WriteFile(style_sheet_file, "", 0);

  std::string css;
  bool rv = base::ReadFileToString(style_sheet_file, &css);
  GURL style_sheet_url;
  if (rv && !css.empty()) {
    std::string css_base64;
    rv = base::Base64Encode(css, &css_base64);
    if (rv) {
      // WebKit knows about data urls, so convert the file to a data url.
      const char kDataUrlPrefix[] = "data:text/css;charset=utf-8;base64,";
      style_sheet_url = GURL(kDataUrlPrefix + css_base64);
    }
  }
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                          base::Bind(&UserStyleSheetLoader::SetStyleSheet, this,
                                     style_sheet_url));
}

void UserStyleSheetLoader::SetStyleSheet(const GURL& url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  has_loaded_ = true;
  user_style_sheet_ = url;
  NotifyLoaded();
}

UserStyleSheetWatcher::UserStyleSheetWatcher(Profile* profile,
                                             const base::FilePath& profile_path)
    : RefcountedBrowserContextKeyedService(content::BrowserThread::UI),
      profile_(profile),
      profile_path_(profile_path),
      loader_(new UserStyleSheetLoader) {
  // Listen for when the first render view host is created.  If we load
  // too fast, the first tab won't hear the notification and won't get
  // the user style sheet.
  registrar_.Add(this,
                 content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
                 content::NotificationService::AllBrowserContextsAndSources());
}

UserStyleSheetWatcher::~UserStyleSheetWatcher() {
}

void UserStyleSheetWatcher::Init() {
  // Make sure we run on the file thread.
  if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                            base::Bind(&UserStyleSheetWatcher::Init, this));
    return;
  }

  if (!file_watcher_.get()) {
    file_watcher_.reset(new FilePathWatcher);
    base::FilePath style_sheet_file = profile_path_.AppendASCII(kStyleSheetDir)
                                             .AppendASCII(kUserStyleSheetFile);
    if (!file_watcher_->Watch(
            style_sheet_file,
            false,
            base::Bind(&UserStyleSheetLoader::NotifyPathChanged,
                       loader_.get()))) {
      LOG(ERROR) << "Failed to setup watch for " << style_sheet_file.value();
    }
    loader_->LoadStyleSheet(style_sheet_file);
  }
}

GURL UserStyleSheetWatcher::user_style_sheet() const {
  return loader_->user_style_sheet();
}

scoped_ptr<base::CallbackList<void(void)>::Subscription>
UserStyleSheetWatcher::RegisterOnStyleSheetUpdatedCallback(
    const base::Closure& callback) {
  return loader_->RegisterOnStyleSheetUpdatedCallback(callback);
}

void UserStyleSheetWatcher::Observe(int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(type == content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED);
  if (profile_->IsSameProfile(Profile::FromBrowserContext(
          content::Source<WebContents>(source)->GetBrowserContext()))) {
    loader_->NotifyLoaded();
    registrar_.RemoveAll();
  }
}

void UserStyleSheetWatcher::ShutdownOnUIThread() {
  registrar_.RemoveAll();
}
