blob: 98ec18b5ca5e3988b455dc4d57e3e9c248351b8b [file] [log] [blame]
// 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.
// Defines the Chrome Extensions Clear API functions, which entail
// clearing browsing data, and clearing the browser's cache (which, let's be
// honest, are the same thing), as specified in the extension API JSON.
#include "chrome/browser/extensions/extension_clear_api.h"
#include <string>
#include "base/values.h"
#include "chrome/browser/browsing_data_remover.h"
#include "chrome/browser/plugin_data_remover_helper.h"
#include "chrome/browser/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_error_utils.h"
#include "content/public/browser/browser_thread.h"
using content::BrowserThread;
namespace extension_clear_api_constants {
// Keys.
const char kAppCacheKey[] = "appcache";
const char kCacheKey[] = "cache";
const char kCookiesKey[] = "cookies";
const char kDownloadsKey[] = "downloads";
const char kFileSystemsKey[] = "fileSystems";
const char kFormDataKey[] = "formData";
const char kHistoryKey[] = "history";
const char kIndexedDBKey[] = "indexedDB";
const char kPluginDataKey[] = "pluginData";
const char kLocalStorageKey[] = "localStorage";
const char kPasswordsKey[] = "passwords";
const char kWebSQLKey[] = "webSQL";
// Errors!
const char kOneAtATimeError[] = "Only one 'clear' API call can run at a time.";
} // namespace extension_clear_api_constants
namespace {
// Converts the JavaScript API's numeric input (miliseconds since epoch) into an
// appropriate base::Time that we can pass into the BrowsingDataRemove.
bool ParseTimeFromValue(const double& ms_since_epoch, base::Time* time) {
return true;
}
// Given a DictionaryValue |dict|, returns either the value stored as |key|, or
// false, if the given key doesn't exist in the dictionary.
bool DataRemovalRequested(base::DictionaryValue* dict, const std::string& key) {
bool value = false;
if (!dict->GetBoolean(key, &value))
return false;
else
return value;
}
// Convert the JavaScript API's object input ({ cookies: true }) into the
// appropriate removal mask for the BrowsingDataRemover object.
int ParseRemovalMask(base::DictionaryValue* value) {
int GetRemovalMask = 0;
if (DataRemovalRequested(value, extension_clear_api_constants::kAppCacheKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_APPCACHE;
if (DataRemovalRequested(value, extension_clear_api_constants::kCacheKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_CACHE;
if (DataRemovalRequested(value, extension_clear_api_constants::kCookiesKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_COOKIES;
if (DataRemovalRequested(value, extension_clear_api_constants::kDownloadsKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_DOWNLOADS;
if (DataRemovalRequested(value, extension_clear_api_constants::kPasswordsKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_FILE_SYSTEMS;
if (DataRemovalRequested(value, extension_clear_api_constants::kFormDataKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_FORM_DATA;
if (DataRemovalRequested(value, extension_clear_api_constants::kHistoryKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_HISTORY;
if (DataRemovalRequested(value, extension_clear_api_constants::kPasswordsKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_INDEXEDDB;
if (DataRemovalRequested(value, extension_clear_api_constants::kPasswordsKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_LOCAL_STORAGE;
if (DataRemovalRequested(value, extension_clear_api_constants::kPasswordsKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_PLUGIN_DATA;
if (DataRemovalRequested(value, extension_clear_api_constants::kPasswordsKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_PASSWORDS;
if (DataRemovalRequested(value, extension_clear_api_constants::kPasswordsKey))
GetRemovalMask |= BrowsingDataRemover::REMOVE_WEBSQL;
return GetRemovalMask;
}
} // Namespace.
void BrowsingDataExtensionFunction::OnBrowsingDataRemoverDone() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
this->SendResponse(true);
Release(); // Balanced in RunImpl.
}
bool BrowsingDataExtensionFunction::RunImpl() {
if (BrowsingDataRemover::is_removing()) {
error_ = extension_clear_api_constants::kOneAtATimeError;
return false;
}
double ms_since_epoch;
EXTENSION_FUNCTION_VALIDATE(args_->GetDouble(0, &ms_since_epoch));
// base::Time takes a double that represents seconds since epoch. JavaScript
// gives developers milliseconds, so do a quick conversion before populating
// the object. Also, Time::FromDoubleT converts double time 0 to empty Time
// object. So we need to do special handling here.
remove_since_ = (ms_since_epoch == 0) ?
base::Time::UnixEpoch() :
base::Time::FromDoubleT(ms_since_epoch / 1000.0);
removal_mask_ = GetRemovalMask();
if (removal_mask_ & BrowsingDataRemover::REMOVE_PLUGIN_DATA) {
// If we're being asked to remove plugin data, check whether it's actually
// supported.
Profile* profile = GetCurrentBrowser()->profile();
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(
&BrowsingDataExtensionFunction::CheckRemovingPluginDataSupported,
this,
make_scoped_refptr(PluginPrefs::GetForProfile(profile))));
} else {
StartRemoving();
}
// Will finish asynchronously.
return true;
}
void BrowsingDataExtensionFunction::CheckRemovingPluginDataSupported(
scoped_refptr<PluginPrefs> plugin_prefs) {
if (!PluginDataRemoverHelper::IsSupported(plugin_prefs))
removal_mask_ &= ~BrowsingDataRemover::REMOVE_PLUGIN_DATA;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&BrowsingDataExtensionFunction::StartRemoving, this));
}
void BrowsingDataExtensionFunction::StartRemoving() {
// If we're good to go, add a ref (Balanced in OnBrowsingDataRemoverDone)
AddRef();
// Create a BrowsingDataRemover, set the current object as an observer (so
// that we're notified after removal) and call remove() with the arguments
// we've generated above. We can use a raw pointer here, as the browsing data
// remover is responsible for deleting itself once data removal is complete.
BrowsingDataRemover* remover = new BrowsingDataRemover(
GetCurrentBrowser()->profile(), remove_since_, base::Time::Now());
remover->AddObserver(this);
remover->Remove(removal_mask_);
}
int ClearBrowsingDataFunction::GetRemovalMask() const {
// Parse the |dataToRemove| argument to generate the removal mask.
base::DictionaryValue* data_to_remove;
if (args_->GetDictionary(1, &data_to_remove))
return ParseRemovalMask(data_to_remove);
else
return 0;
}
int ClearAppCacheFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_APPCACHE;
}
int ClearCacheFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_CACHE;
}
int ClearCookiesFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_COOKIES;
}
int ClearDownloadsFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_DOWNLOADS;
}
int ClearFileSystemsFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_FILE_SYSTEMS;
}
int ClearFormDataFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_FORM_DATA;
}
int ClearHistoryFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_HISTORY;
}
int ClearIndexedDBFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_INDEXEDDB;
}
int ClearLocalStorageFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_LOCAL_STORAGE;
}
int ClearPluginDataFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_PLUGIN_DATA;
}
int ClearPasswordsFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_PASSWORDS;
}
int ClearWebSQLFunction::GetRemovalMask() const {
return BrowsingDataRemover::REMOVE_WEBSQL;
}