| Index: chrome/browser/download/download_extension_api.cc
|
| diff --git a/chrome/browser/download/download_extension_api.cc b/chrome/browser/download/download_extension_api.cc
|
| deleted file mode 100644
|
| index a89332d6da42d98c63fe5f89716f6bab3331481f..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/download/download_extension_api.cc
|
| +++ /dev/null
|
| @@ -1,1121 +0,0 @@
|
| -// 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/download/download_extension_api.h"
|
| -
|
| -#include <algorithm>
|
| -#include <cctype>
|
| -#include <iterator>
|
| -#include <set>
|
| -#include <string>
|
| -
|
| -#include "base/basictypes.h"
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/callback.h"
|
| -#include "base/json/json_writer.h"
|
| -#include "base/lazy_instance.h"
|
| -#include "base/logging.h"
|
| -#include "base/metrics/histogram.h"
|
| -#include "base/stl_util.h"
|
| -#include "base/string16.h"
|
| -#include "base/string_split.h"
|
| -#include "base/string_util.h"
|
| -#include "base/stringprintf.h"
|
| -#include "base/values.h"
|
| -#include "chrome/browser/browser_process.h"
|
| -#include "chrome/browser/download/download_file_icon_extractor.h"
|
| -#include "chrome/browser/download/download_query.h"
|
| -#include "chrome/browser/download/download_service.h"
|
| -#include "chrome/browser/download/download_service_factory.h"
|
| -#include "chrome/browser/download/download_util.h"
|
| -#include "chrome/browser/extensions/extension_event_names.h"
|
| -#include "chrome/browser/extensions/extension_event_router.h"
|
| -#include "chrome/browser/icon_loader.h"
|
| -#include "chrome/browser/icon_manager.h"
|
| -#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
|
| -#include "chrome/browser/ui/browser_list.h"
|
| -#include "chrome/browser/ui/webui/web_ui_util.h"
|
| -#include "content/public/browser/download_interrupt_reasons.h"
|
| -#include "content/public/browser/download_item.h"
|
| -#include "content/public/browser/download_save_info.h"
|
| -#include "content/public/browser/render_process_host.h"
|
| -#include "content/public/browser/render_view_host.h"
|
| -#include "content/public/browser/resource_dispatcher_host.h"
|
| -#include "net/base/load_flags.h"
|
| -#include "net/http/http_util.h"
|
| -#include "net/url_request/url_request.h"
|
| -
|
| -using content::BrowserThread;
|
| -using content::DownloadId;
|
| -using content::DownloadItem;
|
| -using content::DownloadManager;
|
| -
|
| -namespace download_extension_errors {
|
| -
|
| -// Error messages
|
| -const char kGenericError[] = "I'm afraid I can't do that.";
|
| -const char kIconNotFoundError[] = "Icon not found.";
|
| -const char kInvalidDangerTypeError[] = "Invalid danger type";
|
| -const char kInvalidFilterError[] = "Invalid query filter";
|
| -const char kInvalidOperationError[] = "Invalid operation.";
|
| -const char kInvalidOrderByError[] = "Invalid orderBy field";
|
| -const char kInvalidQueryLimit[] = "Invalid query limit";
|
| -const char kInvalidStateError[] = "Invalid state";
|
| -const char kInvalidURLError[] = "Invalid URL.";
|
| -const char kNotImplementedError[] = "NotImplemented.";
|
| -
|
| -} // namespace download_extension_errors
|
| -
|
| -namespace {
|
| -
|
| -// Default icon size for getFileIcon() in pixels.
|
| -const int kDefaultIconSize = 32;
|
| -
|
| -// Parameter keys
|
| -const char kBodyKey[] = "body";
|
| -const char kBytesReceivedKey[] = "bytesReceived";
|
| -const char kDangerAcceptedKey[] = "dangerAccepted";
|
| -const char kDangerContent[] = "content";
|
| -const char kDangerFile[] = "file";
|
| -const char kDangerKey[] = "danger";
|
| -const char kDangerSafe[] = "safe";
|
| -const char kDangerUncommon[] = "uncommon";
|
| -const char kDangerUrl[] = "url";
|
| -const char kEndTimeKey[] = "endTime";
|
| -const char kErrorKey[] = "error";
|
| -const char kFileSizeKey[] = "fileSize";
|
| -const char kFilenameKey[] = "filename";
|
| -const char kFilenameRegexKey[] = "filenameRegex";
|
| -const char kHeaderNameKey[] = "name";
|
| -const char kHeaderValueKey[] = "value";
|
| -const char kHeaderBinaryValueKey[] = "binaryValue";
|
| -const char kHeadersKey[] = "headers";
|
| -const char kIdKey[] = "id";
|
| -const char kIncognito[] = "incognito";
|
| -const char kLimitKey[] = "limit";
|
| -const char kMethodKey[] = "method";
|
| -const char kMimeKey[] = "mime";
|
| -const char kOrderByKey[] = "orderBy";
|
| -const char kPausedKey[] = "paused";
|
| -const char kQueryKey[] = "query";
|
| -const char kSaveAsKey[] = "saveAs";
|
| -const char kSizeKey[] = "size";
|
| -const char kStartTimeKey[] = "startTime";
|
| -const char kStartedAfterKey[] = "startedAfter";
|
| -const char kStartedBeforeKey[] = "startedBefore";
|
| -const char kStateComplete[] = "complete";
|
| -const char kStateInProgress[] = "in_progress";
|
| -const char kStateInterrupted[] = "interrupted";
|
| -const char kStateKey[] = "state";
|
| -const char kTotalBytesKey[] = "totalBytes";
|
| -const char kTotalBytesGreaterKey[] = "totalBytesGreater";
|
| -const char kTotalBytesLessKey[] = "totalBytesLess";
|
| -const char kUrlKey[] = "url";
|
| -const char kUrlRegexKey[] = "urlRegex";
|
| -
|
| -// Note: Any change to the danger type strings, should be accompanied by a
|
| -// corresponding change to {experimental.}downloads.json.
|
| -const char* kDangerStrings[] = {
|
| - kDangerSafe,
|
| - kDangerFile,
|
| - kDangerUrl,
|
| - kDangerContent,
|
| - kDangerSafe,
|
| - kDangerUncommon,
|
| -};
|
| -COMPILE_ASSERT(arraysize(kDangerStrings) == content::DOWNLOAD_DANGER_TYPE_MAX,
|
| - download_danger_type_enum_changed);
|
| -
|
| -// Note: Any change to the state strings, should be accompanied by a
|
| -// corresponding change to {experimental.}downloads.json.
|
| -const char* kStateStrings[] = {
|
| - kStateInProgress,
|
| - kStateComplete,
|
| - kStateInterrupted,
|
| - NULL,
|
| - kStateInterrupted,
|
| -};
|
| -COMPILE_ASSERT(arraysize(kStateStrings) == DownloadItem::MAX_DOWNLOAD_STATE,
|
| - download_item_state_enum_changed);
|
| -
|
| -const char* DangerString(content::DownloadDangerType danger) {
|
| - DCHECK(danger >= 0);
|
| - DCHECK(danger < static_cast<content::DownloadDangerType>(
|
| - arraysize(kDangerStrings)));
|
| - return kDangerStrings[danger];
|
| -}
|
| -
|
| -content::DownloadDangerType DangerEnumFromString(const std::string& danger) {
|
| - for (size_t i = 0; i < arraysize(kDangerStrings); ++i) {
|
| - if (danger == kDangerStrings[i])
|
| - return static_cast<content::DownloadDangerType>(i);
|
| - }
|
| - return content::DOWNLOAD_DANGER_TYPE_MAX;
|
| -}
|
| -
|
| -const char* StateString(DownloadItem::DownloadState state) {
|
| - DCHECK(state >= 0);
|
| - DCHECK(state < static_cast<DownloadItem::DownloadState>(
|
| - arraysize(kStateStrings)));
|
| - DCHECK(state != DownloadItem::REMOVING);
|
| - return kStateStrings[state];
|
| -}
|
| -
|
| -DownloadItem::DownloadState StateEnumFromString(const std::string& state) {
|
| - for (size_t i = 0; i < arraysize(kStateStrings); ++i) {
|
| - if ((kStateStrings[i] != NULL) && (state == kStateStrings[i]))
|
| - return static_cast<DownloadItem::DownloadState>(i);
|
| - }
|
| - return DownloadItem::MAX_DOWNLOAD_STATE;
|
| -}
|
| -
|
| -bool ValidateFilename(const string16& filename) {
|
| - // TODO(benjhayden): More robust validation of filename.
|
| - if ((filename.find('/') != string16::npos) ||
|
| - (filename.find('\\') != string16::npos))
|
| - return false;
|
| - if (filename.size() >= 2u && filename[0] == L'.' && filename[1] == L'.')
|
| - return false;
|
| - return true;
|
| -}
|
| -
|
| -scoped_ptr<base::DictionaryValue> DownloadItemToJSON(DownloadItem* item) {
|
| - base::DictionaryValue* json = new base::DictionaryValue();
|
| - json->SetInteger(kIdKey, item->GetId());
|
| - json->SetString(kUrlKey, item->GetOriginalUrl().spec());
|
| - json->SetString(kFilenameKey, item->GetFullPath().LossyDisplayName());
|
| - json->SetString(kDangerKey, DangerString(item->GetDangerType()));
|
| - if (item->GetDangerType() != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
|
| - json->SetBoolean(kDangerAcceptedKey,
|
| - item->GetSafetyState() == DownloadItem::DANGEROUS_BUT_VALIDATED);
|
| - json->SetString(kStateKey, StateString(item->GetState()));
|
| - json->SetBoolean(kPausedKey, item->IsPaused());
|
| - json->SetString(kMimeKey, item->GetMimeType());
|
| - json->SetInteger(kStartTimeKey,
|
| - (item->GetStartTime() - base::Time::UnixEpoch()).InMilliseconds());
|
| - json->SetInteger(kBytesReceivedKey, item->GetReceivedBytes());
|
| - json->SetInteger(kTotalBytesKey, item->GetTotalBytes());
|
| - json->SetBoolean(kIncognito, item->IsOtr());
|
| - if (item->GetState() == DownloadItem::INTERRUPTED) {
|
| - json->SetInteger(kErrorKey, static_cast<int>(item->GetLastReason()));
|
| - } else if (item->GetState() == DownloadItem::CANCELLED) {
|
| - json->SetInteger(kErrorKey, static_cast<int>(
|
| - content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED));
|
| - }
|
| - // TODO(benjhayden): Implement endTime and fileSize.
|
| - // json->SetInteger(kEndTimeKey, -1);
|
| - json->SetInteger(kFileSizeKey, item->GetTotalBytes());
|
| - return scoped_ptr<base::DictionaryValue>(json);
|
| -}
|
| -
|
| -class DownloadFileIconExtractorImpl : public DownloadFileIconExtractor {
|
| - public:
|
| - DownloadFileIconExtractorImpl() {}
|
| -
|
| - ~DownloadFileIconExtractorImpl() {}
|
| -
|
| - virtual bool ExtractIconURLForPath(const FilePath& path,
|
| - IconLoader::IconSize icon_size,
|
| - IconURLCallback callback) OVERRIDE;
|
| - private:
|
| - void OnIconLoadComplete(IconManager::Handle handle, gfx::Image* icon);
|
| -
|
| - CancelableRequestConsumer cancelable_consumer_;
|
| - IconURLCallback callback_;
|
| -};
|
| -
|
| -bool DownloadFileIconExtractorImpl::ExtractIconURLForPath(
|
| - const FilePath& path,
|
| - IconLoader::IconSize icon_size,
|
| - IconURLCallback callback) {
|
| - callback_ = callback;
|
| - IconManager* im = g_browser_process->icon_manager();
|
| - // The contents of the file at |path| may have changed since a previous
|
| - // request, in which case the associated icon may also have changed.
|
| - // Therefore, for the moment we always call LoadIcon instead of attempting
|
| - // a LookupIcon.
|
| - im->LoadIcon(
|
| - path, icon_size, &cancelable_consumer_,
|
| - base::Bind(&DownloadFileIconExtractorImpl::OnIconLoadComplete,
|
| - base::Unretained(this)));
|
| - return true;
|
| -}
|
| -
|
| -void DownloadFileIconExtractorImpl::OnIconLoadComplete(
|
| - IconManager::Handle handle,
|
| - gfx::Image* icon) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - std::string url;
|
| - if (icon)
|
| - url = web_ui_util::GetImageDataUrl(*icon->ToSkBitmap());
|
| - callback_.Run(url);
|
| -}
|
| -
|
| -IconLoader::IconSize IconLoaderSizeFromPixelSize(int pixel_size) {
|
| - switch (pixel_size) {
|
| - case 16: return IconLoader::SMALL;
|
| - case 32: return IconLoader::NORMAL;
|
| - default:
|
| - NOTREACHED();
|
| - return IconLoader::NORMAL;
|
| - }
|
| -}
|
| -
|
| -typedef base::hash_map<std::string, DownloadQuery::FilterType> FilterTypeMap;
|
| -
|
| -void InitFilterTypeMap(FilterTypeMap& filter_types) {
|
| - filter_types[kBytesReceivedKey] =
|
| - DownloadQuery::FILTER_BYTES_RECEIVED;
|
| - filter_types[kDangerAcceptedKey] =
|
| - DownloadQuery::FILTER_DANGER_ACCEPTED;
|
| - filter_types[kFilenameKey] = DownloadQuery::FILTER_FILENAME;
|
| - filter_types[kFilenameRegexKey] =
|
| - DownloadQuery::FILTER_FILENAME_REGEX;
|
| - filter_types[kMimeKey] = DownloadQuery::FILTER_MIME;
|
| - filter_types[kPausedKey] = DownloadQuery::FILTER_PAUSED;
|
| - filter_types[kQueryKey] = DownloadQuery::FILTER_QUERY;
|
| - filter_types[kStartedAfterKey] = DownloadQuery::FILTER_STARTED_AFTER;
|
| - filter_types[kStartedBeforeKey] =
|
| - DownloadQuery::FILTER_STARTED_BEFORE;
|
| - filter_types[kStartTimeKey] = DownloadQuery::FILTER_START_TIME;
|
| - filter_types[kTotalBytesKey] = DownloadQuery::FILTER_TOTAL_BYTES;
|
| - filter_types[kTotalBytesGreaterKey] =
|
| - DownloadQuery::FILTER_TOTAL_BYTES_GREATER;
|
| - filter_types[kTotalBytesLessKey] =
|
| - DownloadQuery::FILTER_TOTAL_BYTES_LESS;
|
| - filter_types[kUrlKey] = DownloadQuery::FILTER_URL;
|
| - filter_types[kUrlRegexKey] = DownloadQuery::FILTER_URL_REGEX;
|
| -}
|
| -
|
| -typedef base::hash_map<std::string, DownloadQuery::SortType> SortTypeMap;
|
| -
|
| -void InitSortTypeMap(SortTypeMap& sorter_types) {
|
| - sorter_types[kBytesReceivedKey] = DownloadQuery::SORT_BYTES_RECEIVED;
|
| - sorter_types[kDangerKey] = DownloadQuery::SORT_DANGER;
|
| - sorter_types[kDangerAcceptedKey] =
|
| - DownloadQuery::SORT_DANGER_ACCEPTED;
|
| - sorter_types[kFilenameKey] = DownloadQuery::SORT_FILENAME;
|
| - sorter_types[kMimeKey] = DownloadQuery::SORT_MIME;
|
| - sorter_types[kPausedKey] = DownloadQuery::SORT_PAUSED;
|
| - sorter_types[kStartTimeKey] = DownloadQuery::SORT_START_TIME;
|
| - sorter_types[kStateKey] = DownloadQuery::SORT_STATE;
|
| - sorter_types[kTotalBytesKey] = DownloadQuery::SORT_TOTAL_BYTES;
|
| - sorter_types[kUrlKey] = DownloadQuery::SORT_URL;
|
| -}
|
| -
|
| -bool IsNotTemporaryDownloadFilter(const DownloadItem& item) {
|
| - return !item.IsTemporary();
|
| -}
|
| -
|
| -void GetManagers(
|
| - Profile* profile,
|
| - bool include_incognito,
|
| - DownloadManager** manager, DownloadManager** incognito_manager) {
|
| - *manager = DownloadServiceFactory::GetForProfile(profile)->
|
| - GetDownloadManager();
|
| - *incognito_manager = NULL;
|
| - if (include_incognito && profile->HasOffTheRecordProfile())
|
| - *incognito_manager = DownloadServiceFactory::GetForProfile(profile->
|
| - GetOffTheRecordProfile())->GetDownloadManager();
|
| -}
|
| -
|
| -DownloadItem* GetActiveItemInternal(
|
| - Profile* profile,
|
| - bool include_incognito,
|
| - int id) {
|
| - DownloadManager* manager = NULL;
|
| - DownloadManager* incognito_manager = NULL;
|
| - GetManagers(profile, include_incognito, &manager, &incognito_manager);
|
| - DownloadItem* download_item = manager->GetActiveDownloadItem(id);
|
| - if (!download_item && incognito_manager)
|
| - download_item = incognito_manager->GetActiveDownloadItem(id);
|
| - return download_item;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -bool DownloadsFunctionInterface::RunImplImpl(
|
| - DownloadsFunctionInterface* pimpl) {
|
| - CHECK(pimpl);
|
| - if (!pimpl->ParseArgs()) return false;
|
| - UMA_HISTOGRAM_ENUMERATION(
|
| - "Download.ApiFunctions", pimpl->function(), DOWNLOADS_FUNCTION_LAST);
|
| - return pimpl->RunInternal();
|
| -}
|
| -
|
| -SyncDownloadsFunction::SyncDownloadsFunction(
|
| - DownloadsFunctionInterface::DownloadsFunctionName function)
|
| - : function_(function) {
|
| -}
|
| -
|
| -SyncDownloadsFunction::~SyncDownloadsFunction() {}
|
| -
|
| -bool SyncDownloadsFunction::RunImpl() {
|
| - return DownloadsFunctionInterface::RunImplImpl(this);
|
| -}
|
| -
|
| -DownloadsFunctionInterface::DownloadsFunctionName
|
| -SyncDownloadsFunction::function() const {
|
| - return function_;
|
| -}
|
| -
|
| -DownloadItem* SyncDownloadsFunction::GetActiveItem(int download_id) {
|
| - return GetActiveItemInternal(profile(), include_incognito(), download_id);
|
| -}
|
| -
|
| -AsyncDownloadsFunction::AsyncDownloadsFunction(
|
| - DownloadsFunctionInterface::DownloadsFunctionName function)
|
| - : function_(function) {
|
| -}
|
| -
|
| -AsyncDownloadsFunction::~AsyncDownloadsFunction() {}
|
| -
|
| -bool AsyncDownloadsFunction::RunImpl() {
|
| - return DownloadsFunctionInterface::RunImplImpl(this);
|
| -}
|
| -
|
| -DownloadsFunctionInterface::DownloadsFunctionName
|
| -AsyncDownloadsFunction::function() const {
|
| - return function_;
|
| -}
|
| -
|
| -DownloadItem* AsyncDownloadsFunction::GetActiveItem(int download_id) {
|
| - return GetActiveItemInternal(profile(), include_incognito(), download_id);
|
| -}
|
| -
|
| -DownloadsDownloadFunction::DownloadsDownloadFunction()
|
| - : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_DOWNLOAD) {
|
| -}
|
| -
|
| -DownloadsDownloadFunction::~DownloadsDownloadFunction() {}
|
| -
|
| -DownloadsDownloadFunction::IOData::IOData()
|
| - : save_as(false),
|
| - extra_headers(NULL),
|
| - method("GET"),
|
| - rdh(NULL),
|
| - resource_context(NULL),
|
| - render_process_host_id(0),
|
| - render_view_host_routing_id(0) {
|
| -}
|
| -
|
| -DownloadsDownloadFunction::IOData::~IOData() {}
|
| -
|
| -bool DownloadsDownloadFunction::ParseArgs() {
|
| - base::DictionaryValue* options = NULL;
|
| - std::string url;
|
| - iodata_.reset(new IOData());
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));
|
| - EXTENSION_FUNCTION_VALIDATE(options->GetString(kUrlKey, &url));
|
| - iodata_->url = GURL(url);
|
| - if (!iodata_->url.is_valid()) {
|
| - error_ = download_extension_errors::kInvalidURLError;
|
| - return false;
|
| - }
|
| -
|
| - if (!iodata_->url.SchemeIs("data") &&
|
| - iodata_->url.GetOrigin() != GetExtension()->url().GetOrigin() &&
|
| - !GetExtension()->HasHostPermission(iodata_->url)) {
|
| - error_ = download_extension_errors::kInvalidURLError;
|
| - return false;
|
| - }
|
| -
|
| - if (options->HasKey(kFilenameKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(options->GetString(
|
| - kFilenameKey, &iodata_->filename));
|
| - if (!ValidateFilename(iodata_->filename)) {
|
| - error_ = download_extension_errors::kGenericError;
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - if (options->HasKey(kSaveAsKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(options->GetBoolean(
|
| - kSaveAsKey, &iodata_->save_as));
|
| - }
|
| -
|
| - if (options->HasKey(kMethodKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(options->GetString(
|
| - kMethodKey, &iodata_->method));
|
| - }
|
| -
|
| - // It's ok to use a pointer to extra_headers without DeepCopy()ing because
|
| - // |args_| (which owns *extra_headers) is guaranteed to live as long as
|
| - // |this|.
|
| - if (options->HasKey(kHeadersKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(options->GetList(
|
| - kHeadersKey, &iodata_->extra_headers));
|
| - }
|
| -
|
| - if (options->HasKey(kBodyKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(options->GetString(
|
| - kBodyKey, &iodata_->post_body));
|
| - }
|
| -
|
| - if (iodata_->extra_headers != NULL) {
|
| - for (size_t index = 0; index < iodata_->extra_headers->GetSize(); ++index) {
|
| - base::DictionaryValue* header = NULL;
|
| - std::string name;
|
| - EXTENSION_FUNCTION_VALIDATE(iodata_->extra_headers->GetDictionary(
|
| - index, &header));
|
| - EXTENSION_FUNCTION_VALIDATE(header->GetString(
|
| - kHeaderNameKey, &name));
|
| - if (header->HasKey(kHeaderBinaryValueKey)) {
|
| - base::ListValue* binary_value = NULL;
|
| - EXTENSION_FUNCTION_VALIDATE(header->GetList(
|
| - kHeaderBinaryValueKey, &binary_value));
|
| - for (size_t char_i = 0; char_i < binary_value->GetSize(); ++char_i) {
|
| - int char_value = 0;
|
| - EXTENSION_FUNCTION_VALIDATE(binary_value->GetInteger(
|
| - char_i, &char_value));
|
| - }
|
| - } else if (header->HasKey(kHeaderValueKey)) {
|
| - std::string value;
|
| - EXTENSION_FUNCTION_VALIDATE(header->GetString(
|
| - kHeaderValueKey, &value));
|
| - }
|
| - if (!net::HttpUtil::IsSafeHeader(name)) {
|
| - error_ = download_extension_errors::kGenericError;
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| - iodata_->rdh = content::ResourceDispatcherHost::Get();
|
| - iodata_->resource_context = profile()->GetResourceContext();
|
| - iodata_->render_process_host_id = render_view_host()->GetProcess()->GetID();
|
| - iodata_->render_view_host_routing_id = render_view_host()->GetRoutingID();
|
| - return true;
|
| -}
|
| -
|
| -bool DownloadsDownloadFunction::RunInternal() {
|
| - VLOG(1) << __FUNCTION__ << " " << iodata_->url.spec();
|
| - if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
|
| - &DownloadsDownloadFunction::BeginDownloadOnIOThread, this))) {
|
| - error_ = download_extension_errors::kGenericError;
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void DownloadsDownloadFunction::BeginDownloadOnIOThread() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - DVLOG(1) << __FUNCTION__ << " " << iodata_->url.spec();
|
| - content::DownloadSaveInfo save_info;
|
| - // TODO(benjhayden) Ensure that this filename is interpreted as a path
|
| - // relative to the default downloads directory without allowing '..'.
|
| - save_info.suggested_name = iodata_->filename;
|
| - save_info.prompt_for_save_location = iodata_->save_as;
|
| -
|
| - scoped_ptr<net::URLRequest> request(new net::URLRequest(iodata_->url, NULL));
|
| - request->set_method(iodata_->method);
|
| - if (iodata_->extra_headers != NULL) {
|
| - for (size_t index = 0; index < iodata_->extra_headers->GetSize(); ++index) {
|
| - base::DictionaryValue* header = NULL;
|
| - std::string name, value;
|
| - CHECK(iodata_->extra_headers->GetDictionary(index, &header));
|
| - CHECK(header->GetString(kHeaderNameKey, &name));
|
| - if (header->HasKey(kHeaderBinaryValueKey)) {
|
| - base::ListValue* binary_value = NULL;
|
| - CHECK(header->GetList(kHeaderBinaryValueKey, &binary_value));
|
| - for (size_t char_i = 0; char_i < binary_value->GetSize(); ++char_i) {
|
| - int char_value = 0;
|
| - CHECK(binary_value->GetInteger(char_i, &char_value));
|
| - if ((0 <= char_value) &&
|
| - (char_value <= 0xff)) {
|
| - value.push_back(char_value);
|
| - }
|
| - }
|
| - } else if (header->HasKey(kHeaderValueKey)) {
|
| - CHECK(header->GetString(kHeaderValueKey, &value));
|
| - }
|
| - request->SetExtraRequestHeaderByName(name, value, false/*overwrite*/);
|
| - }
|
| - }
|
| - if (!iodata_->post_body.empty()) {
|
| - request->AppendBytesToUpload(iodata_->post_body.data(),
|
| - iodata_->post_body.size());
|
| - }
|
| -
|
| - // Prevent login prompts for 401/407 responses.
|
| - request->set_load_flags(request->load_flags() |
|
| - net::LOAD_DO_NOT_PROMPT_FOR_LOGIN);
|
| -
|
| - net::Error error = iodata_->rdh->BeginDownload(
|
| - request.Pass(),
|
| - false, // is_content_initiated
|
| - iodata_->resource_context,
|
| - iodata_->render_process_host_id,
|
| - iodata_->render_view_host_routing_id,
|
| - false, // prefer_cache
|
| - save_info,
|
| - base::Bind(&DownloadsDownloadFunction::OnStarted, this));
|
| - iodata_.reset();
|
| -
|
| - if (error != net::OK) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&DownloadsDownloadFunction::OnStarted, this,
|
| - DownloadId::Invalid(), error));
|
| - }
|
| -}
|
| -
|
| -void DownloadsDownloadFunction::OnStarted(DownloadId dl_id, net::Error error) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - VLOG(1) << __FUNCTION__ << " " << dl_id << " " << error;
|
| - if (dl_id.local() >= 0) {
|
| - result_.reset(base::Value::CreateIntegerValue(dl_id.local()));
|
| - } else {
|
| - error_ = net::ErrorToString(error);
|
| - }
|
| - SendResponse(error_.empty());
|
| -}
|
| -
|
| -DownloadsSearchFunction::DownloadsSearchFunction()
|
| - : SyncDownloadsFunction(DOWNLOADS_FUNCTION_SEARCH),
|
| - query_(new DownloadQuery()),
|
| - get_id_(0),
|
| - has_get_id_(false) {
|
| -}
|
| -
|
| -DownloadsSearchFunction::~DownloadsSearchFunction() {}
|
| -
|
| -bool DownloadsSearchFunction::ParseArgs() {
|
| - static base::LazyInstance<FilterTypeMap> filter_types =
|
| - LAZY_INSTANCE_INITIALIZER;
|
| - if (filter_types.Get().size() == 0)
|
| - InitFilterTypeMap(filter_types.Get());
|
| -
|
| - base::DictionaryValue* query_json = NULL;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query_json));
|
| - for (base::DictionaryValue::Iterator query_json_field(*query_json);
|
| - query_json_field.HasNext(); query_json_field.Advance()) {
|
| - FilterTypeMap::const_iterator filter_type =
|
| - filter_types.Get().find(query_json_field.key());
|
| -
|
| - if (filter_type != filter_types.Get().end()) {
|
| - if (!query_->AddFilter(filter_type->second, query_json_field.value())) {
|
| - error_ = download_extension_errors::kInvalidFilterError;
|
| - return false;
|
| - }
|
| - } else if (query_json_field.key() == kIdKey) {
|
| - EXTENSION_FUNCTION_VALIDATE(query_json_field.value().GetAsInteger(
|
| - &get_id_));
|
| - has_get_id_ = true;
|
| - } else if (query_json_field.key() == kOrderByKey) {
|
| - if (!ParseOrderBy(query_json_field.value()))
|
| - return false;
|
| - } else if (query_json_field.key() == kDangerKey) {
|
| - std::string danger_str;
|
| - EXTENSION_FUNCTION_VALIDATE(query_json_field.value().GetAsString(
|
| - &danger_str));
|
| - content::DownloadDangerType danger_type =
|
| - DangerEnumFromString(danger_str);
|
| - if (danger_type == content::DOWNLOAD_DANGER_TYPE_MAX) {
|
| - error_ = download_extension_errors::kInvalidDangerTypeError;
|
| - return false;
|
| - }
|
| - query_->AddFilter(danger_type);
|
| - } else if (query_json_field.key() == kStateKey) {
|
| - std::string state_str;
|
| - EXTENSION_FUNCTION_VALIDATE(query_json_field.value().GetAsString(
|
| - &state_str));
|
| - DownloadItem::DownloadState state = StateEnumFromString(state_str);
|
| - if (state == DownloadItem::MAX_DOWNLOAD_STATE) {
|
| - error_ = download_extension_errors::kInvalidStateError;
|
| - return false;
|
| - }
|
| - query_->AddFilter(state);
|
| - } else if (query_json_field.key() == kLimitKey) {
|
| - int limit = 0;
|
| - EXTENSION_FUNCTION_VALIDATE(query_json_field.value().GetAsInteger(
|
| - &limit));
|
| - if (limit < 0) {
|
| - error_ = download_extension_errors::kInvalidQueryLimit;
|
| - return false;
|
| - }
|
| - query_->Limit(limit);
|
| - } else {
|
| - EXTENSION_FUNCTION_VALIDATE(false);
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool DownloadsSearchFunction::ParseOrderBy(const base::Value& order_by_value) {
|
| - static base::LazyInstance<SortTypeMap> sorter_types =
|
| - LAZY_INSTANCE_INITIALIZER;
|
| - if (sorter_types.Get().size() == 0)
|
| - InitSortTypeMap(sorter_types.Get());
|
| -
|
| - std::string order_by_str;
|
| - EXTENSION_FUNCTION_VALIDATE(order_by_value.GetAsString(&order_by_str));
|
| - std::vector<std::string> order_by_strs;
|
| - base::SplitString(order_by_str, ' ', &order_by_strs);
|
| - for (std::vector<std::string>::const_iterator iter = order_by_strs.begin();
|
| - iter != order_by_strs.end(); ++iter) {
|
| - std::string term_str = *iter;
|
| - if (term_str.empty())
|
| - continue;
|
| - DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING;
|
| - if (term_str[0] == '-') {
|
| - direction = DownloadQuery::DESCENDING;
|
| - term_str = term_str.substr(1);
|
| - }
|
| - SortTypeMap::const_iterator sorter_type =
|
| - sorter_types.Get().find(term_str);
|
| - if (sorter_type == sorter_types.Get().end()) {
|
| - error_ = download_extension_errors::kInvalidOrderByError;
|
| - return false;
|
| - }
|
| - query_->AddSorter(sorter_type->second, direction);
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool DownloadsSearchFunction::RunInternal() {
|
| - DownloadManager* manager = NULL;
|
| - DownloadManager* incognito_manager = NULL;
|
| - GetManagers(profile(), include_incognito(), &manager, &incognito_manager);
|
| - DownloadQuery::DownloadVector all_items, cpp_results;
|
| - if (has_get_id_) {
|
| - DownloadItem* item = manager->GetDownloadItem(get_id_);
|
| - if (!item && incognito_manager)
|
| - item = incognito_manager->GetDownloadItem(get_id_);
|
| - if (item)
|
| - all_items.push_back(item);
|
| - } else {
|
| - manager->GetAllDownloads(FilePath(FILE_PATH_LITERAL("")), &all_items);
|
| - if (incognito_manager)
|
| - incognito_manager->GetAllDownloads(
|
| - FilePath(FILE_PATH_LITERAL("")), &all_items);
|
| - }
|
| - query_->Search(all_items.begin(), all_items.end(), &cpp_results);
|
| - base::ListValue* json_results = new base::ListValue();
|
| - for (DownloadManager::DownloadVector::const_iterator it = cpp_results.begin();
|
| - it != cpp_results.end(); ++it) {
|
| - scoped_ptr<base::DictionaryValue> item(DownloadItemToJSON(*it));
|
| - json_results->Append(item.release());
|
| - }
|
| - result_.reset(json_results);
|
| - return true;
|
| -}
|
| -
|
| -DownloadsPauseFunction::DownloadsPauseFunction()
|
| - : SyncDownloadsFunction(DOWNLOADS_FUNCTION_PAUSE),
|
| - download_id_(DownloadId::Invalid().local()) {
|
| -}
|
| -
|
| -DownloadsPauseFunction::~DownloadsPauseFunction() {}
|
| -
|
| -bool DownloadsPauseFunction::ParseArgs() {
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &download_id_));
|
| - return true;
|
| -}
|
| -
|
| -bool DownloadsPauseFunction::RunInternal() {
|
| - DownloadItem* download_item = GetActiveItem(download_id_);
|
| - if ((download_item == NULL) || !download_item->IsInProgress()) {
|
| - // This could be due to an invalid download ID, or it could be due to the
|
| - // download not being currently active.
|
| - error_ = download_extension_errors::kInvalidOperationError;
|
| - } else if (!download_item->IsPaused()) {
|
| - // If download_item->IsPaused() already then we treat it as a success.
|
| - download_item->TogglePause();
|
| - }
|
| - return error_.empty();
|
| -}
|
| -
|
| -DownloadsResumeFunction::DownloadsResumeFunction()
|
| - : SyncDownloadsFunction(DOWNLOADS_FUNCTION_RESUME),
|
| - download_id_(DownloadId::Invalid().local()) {
|
| -}
|
| -
|
| -DownloadsResumeFunction::~DownloadsResumeFunction() {}
|
| -
|
| -bool DownloadsResumeFunction::ParseArgs() {
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &download_id_));
|
| - return true;
|
| -}
|
| -
|
| -bool DownloadsResumeFunction::RunInternal() {
|
| - DownloadItem* download_item = GetActiveItem(download_id_);
|
| - if (download_item == NULL) {
|
| - // This could be due to an invalid download ID, or it could be due to the
|
| - // download not being currently active.
|
| - error_ = download_extension_errors::kInvalidOperationError;
|
| - } else if (download_item->IsPaused()) {
|
| - // If !download_item->IsPaused() already, then we treat it as a success.
|
| - download_item->TogglePause();
|
| - }
|
| - return error_.empty();
|
| -}
|
| -
|
| -DownloadsCancelFunction::DownloadsCancelFunction()
|
| - : SyncDownloadsFunction(DOWNLOADS_FUNCTION_CANCEL),
|
| - download_id_(DownloadId::Invalid().local()) {
|
| -}
|
| -
|
| -DownloadsCancelFunction::~DownloadsCancelFunction() {}
|
| -
|
| -bool DownloadsCancelFunction::ParseArgs() {
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &download_id_));
|
| - return true;
|
| -}
|
| -
|
| -bool DownloadsCancelFunction::RunInternal() {
|
| - DownloadItem* download_item = GetActiveItem(download_id_);
|
| - if (download_item != NULL)
|
| - download_item->Cancel(true);
|
| - // |download_item| can be NULL if the download ID was invalid or if the
|
| - // download is not currently active. Either way, we don't consider it a
|
| - // failure.
|
| - return error_.empty();
|
| -}
|
| -
|
| -DownloadsEraseFunction::DownloadsEraseFunction()
|
| - : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_ERASE) {
|
| -}
|
| -
|
| -DownloadsEraseFunction::~DownloadsEraseFunction() {}
|
| -
|
| -bool DownloadsEraseFunction::ParseArgs() {
|
| - base::DictionaryValue* query_json = NULL;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query_json));
|
| - error_ = download_extension_errors::kNotImplementedError;
|
| - return false;
|
| -}
|
| -
|
| -bool DownloadsEraseFunction::RunInternal() {
|
| - NOTIMPLEMENTED();
|
| - return false;
|
| -}
|
| -
|
| -DownloadsSetDestinationFunction::DownloadsSetDestinationFunction()
|
| - : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_SET_DESTINATION) {
|
| -}
|
| -
|
| -DownloadsSetDestinationFunction::~DownloadsSetDestinationFunction() {}
|
| -
|
| -bool DownloadsSetDestinationFunction::ParseArgs() {
|
| - int dl_id = 0;
|
| - std::string path;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &path));
|
| - VLOG(1) << __FUNCTION__ << " " << dl_id << " " << &path;
|
| - error_ = download_extension_errors::kNotImplementedError;
|
| - return false;
|
| -}
|
| -
|
| -bool DownloadsSetDestinationFunction::RunInternal() {
|
| - NOTIMPLEMENTED();
|
| - return false;
|
| -}
|
| -
|
| -DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction()
|
| - : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_ACCEPT_DANGER) {
|
| -}
|
| -
|
| -DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {}
|
| -
|
| -bool DownloadsAcceptDangerFunction::ParseArgs() {
|
| - int dl_id = 0;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
|
| - VLOG(1) << __FUNCTION__ << " " << dl_id;
|
| - error_ = download_extension_errors::kNotImplementedError;
|
| - return false;
|
| -}
|
| -
|
| -bool DownloadsAcceptDangerFunction::RunInternal() {
|
| - NOTIMPLEMENTED();
|
| - return false;
|
| -}
|
| -
|
| -DownloadsShowFunction::DownloadsShowFunction()
|
| - : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_SHOW) {
|
| -}
|
| -
|
| -DownloadsShowFunction::~DownloadsShowFunction() {}
|
| -
|
| -bool DownloadsShowFunction::ParseArgs() {
|
| - int dl_id = 0;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
|
| - VLOG(1) << __FUNCTION__ << " " << dl_id;
|
| - error_ = download_extension_errors::kNotImplementedError;
|
| - return false;
|
| -}
|
| -
|
| -bool DownloadsShowFunction::RunInternal() {
|
| - NOTIMPLEMENTED();
|
| - return false;
|
| -}
|
| -
|
| -DownloadsDragFunction::DownloadsDragFunction()
|
| - : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_DRAG) {
|
| -}
|
| -
|
| -DownloadsDragFunction::~DownloadsDragFunction() {}
|
| -
|
| -bool DownloadsDragFunction::ParseArgs() {
|
| - int dl_id = 0;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
|
| - VLOG(1) << __FUNCTION__ << " " << dl_id;
|
| - error_ = download_extension_errors::kNotImplementedError;
|
| - return false;
|
| -}
|
| -
|
| -bool DownloadsDragFunction::RunInternal() {
|
| - NOTIMPLEMENTED();
|
| - return false;
|
| -}
|
| -
|
| -DownloadsGetFileIconFunction::DownloadsGetFileIconFunction()
|
| - : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_GET_FILE_ICON),
|
| - icon_size_(kDefaultIconSize),
|
| - icon_extractor_(new DownloadFileIconExtractorImpl()) {
|
| -}
|
| -
|
| -DownloadsGetFileIconFunction::~DownloadsGetFileIconFunction() {}
|
| -
|
| -void DownloadsGetFileIconFunction::SetIconExtractorForTesting(
|
| - DownloadFileIconExtractor* extractor) {
|
| - DCHECK(extractor);
|
| - icon_extractor_.reset(extractor);
|
| -}
|
| -
|
| -bool DownloadsGetFileIconFunction::ParseArgs() {
|
| - int dl_id = 0;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
|
| -
|
| - base::DictionaryValue* options = NULL;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options));
|
| - if (options->HasKey(kSizeKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(options->GetInteger(kSizeKey, &icon_size_));
|
| - // We only support 16px and 32px icons. This is enforced in
|
| - // experimental.downloads.json.
|
| - DCHECK(icon_size_ == 16 || icon_size_ == 32);
|
| - }
|
| -
|
| - DownloadManager* manager = NULL;
|
| - DownloadManager* incognito_manager = NULL;
|
| - GetManagers(profile(), include_incognito(), &manager, &incognito_manager);
|
| - DownloadItem* download_item = manager->GetDownloadItem(dl_id);
|
| - if (!download_item && incognito_manager)
|
| - download_item = incognito_manager->GetDownloadItem(dl_id);
|
| - if (!download_item) {
|
| - // The DownloadItem is is added to history when the path is determined. If
|
| - // the download is not in history, then we don't have a path / final
|
| - // filename and no icon.
|
| - error_ = download_extension_errors::kInvalidOperationError;
|
| - return false;
|
| - }
|
| - // In-progress downloads return the intermediate filename for GetFullPath()
|
| - // which doesn't have the final extension. Therefore we won't be able to
|
| - // derive a good file icon for it. So we use GetTargetFilePath() instead.
|
| - path_ = download_item->GetTargetFilePath();
|
| - DCHECK(!path_.empty());
|
| - return true;
|
| -}
|
| -
|
| -bool DownloadsGetFileIconFunction::RunInternal() {
|
| - DCHECK(!path_.empty());
|
| - DCHECK(icon_extractor_.get());
|
| - EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath(
|
| - path_, IconLoaderSizeFromPixelSize(icon_size_),
|
| - base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this)));
|
| - return true;
|
| -}
|
| -
|
| -void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - if (url.empty())
|
| - error_ = download_extension_errors::kIconNotFoundError;
|
| - else
|
| - result_.reset(base::Value::CreateStringValue(url));
|
| - SendResponse(error_.empty());
|
| -}
|
| -
|
| -ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter(Profile* profile)
|
| - : profile_(profile),
|
| - manager_(NULL),
|
| - delete_item_jsons_(&item_jsons_),
|
| - delete_on_changed_stats_(&on_changed_stats_) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DCHECK(profile_);
|
| - // Register a callback with the DownloadService for this profile to be called
|
| - // when it creates the DownloadManager, or now if the manager already exists.
|
| - DownloadServiceFactory::GetForProfile(profile)->OnManagerCreated(base::Bind(
|
| - &ExtensionDownloadsEventRouter::Init, base::Unretained(this)));
|
| -}
|
| -
|
| -// The only public methods on this class are ModelChanged() and
|
| -// ManagerGoingDown(), and they are only called by DownloadManager, so
|
| -// there's no way for any methods on this class to be called before
|
| -// DownloadService calls Init() via the OnManagerCreated Callback above.
|
| -void ExtensionDownloadsEventRouter::Init(DownloadManager* manager) {
|
| - DCHECK(manager_ == NULL);
|
| - manager_ = manager;
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - manager_->AddObserver(this);
|
| -}
|
| -
|
| -ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() {
|
| - if (manager_ != NULL)
|
| - manager_->RemoveObserver(this);
|
| - for (ItemMap::const_iterator iter = downloads_.begin();
|
| - iter != downloads_.end(); ++iter) {
|
| - if (iter->second != NULL)
|
| - iter->second->RemoveObserver(this);
|
| - }
|
| -}
|
| -
|
| -ExtensionDownloadsEventRouter::OnChangedStat::OnChangedStat()
|
| - : fires(0),
|
| - total(0) {
|
| -}
|
| -
|
| -ExtensionDownloadsEventRouter::OnChangedStat::~OnChangedStat() {
|
| - if (total > 0)
|
| - UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", (fires * 100 / total));
|
| -}
|
| -
|
| -void ExtensionDownloadsEventRouter::OnDownloadUpdated(DownloadItem* item) {
|
| - int download_id = item->GetId();
|
| - if (item->GetState() == DownloadItem::REMOVING) {
|
| - // The REMOVING state indicates that this item is being erased.
|
| - // Let's unregister as an observer so that we don't see any more updates
|
| - // from it, dispatch the onErased event, and remove its json and is
|
| - // OnChangedStat from our maps.
|
| - downloads_.erase(download_id);
|
| - item->RemoveObserver(this);
|
| - DispatchEvent(extension_event_names::kOnDownloadErased,
|
| - base::Value::CreateIntegerValue(download_id));
|
| - delete item_jsons_[download_id];
|
| - item_jsons_.erase(download_id);
|
| - delete on_changed_stats_[download_id];
|
| - on_changed_stats_.erase(download_id);
|
| - return;
|
| - }
|
| -
|
| - base::DictionaryValue* old_json = item_jsons_[download_id];
|
| - scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON(item));
|
| - scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue());
|
| - delta->SetInteger(kIdKey, download_id);
|
| - std::set<std::string> new_fields;
|
| - bool changed = false;
|
| -
|
| - // For each field in the new json representation of the item except the
|
| - // bytesReceived field, if the field has changed from the previous old json,
|
| - // set the differences in the |delta| object and remember that something
|
| - // significant changed.
|
| - for (base::DictionaryValue::Iterator iter(*new_json.get());
|
| - iter.HasNext(); iter.Advance()) {
|
| - new_fields.insert(iter.key());
|
| - if (iter.key() != kBytesReceivedKey) {
|
| - base::Value* old_value = NULL;
|
| - if (!old_json->HasKey(iter.key()) ||
|
| - (old_json->Get(iter.key(), &old_value) &&
|
| - !iter.value().Equals(old_value))) {
|
| - delta->Set(iter.key() + ".new", iter.value().DeepCopy());
|
| - if (old_value)
|
| - delta->Set(iter.key() + ".old", old_value->DeepCopy());
|
| - changed = true;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // If a field was in the previous json but is not in the new json, set the
|
| - // difference in |delta|.
|
| - for (base::DictionaryValue::Iterator iter(*old_json);
|
| - iter.HasNext(); iter.Advance()) {
|
| - if (new_fields.find(iter.key()) == new_fields.end()) {
|
| - delta->Set(iter.key() + ".old", iter.value().DeepCopy());
|
| - changed = true;
|
| - }
|
| - }
|
| -
|
| - // Update the OnChangedStat and dispatch the event if something significant
|
| - // changed. Replace the stored json with the new json.
|
| - ++(on_changed_stats_[download_id]->total);
|
| - if (changed) {
|
| - DispatchEvent(extension_event_names::kOnDownloadChanged, delta.release());
|
| - ++(on_changed_stats_[download_id]->fires);
|
| - }
|
| - item_jsons_[download_id]->Swap(new_json.get());
|
| -}
|
| -
|
| -void ExtensionDownloadsEventRouter::OnDownloadOpened(DownloadItem* item) {
|
| -}
|
| -
|
| -void ExtensionDownloadsEventRouter::ModelChanged(DownloadManager* manager) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DCHECK(manager_ == manager);
|
| - typedef std::set<int> DownloadIdSet;
|
| -
|
| - // Get all the download items.
|
| - DownloadManager::DownloadVector current_vec;
|
| - manager_->SearchDownloads(string16(), ¤t_vec);
|
| -
|
| - // Populate set<>s of download item identifiers so that we can find
|
| - // differences between the old and the new set of download items.
|
| - DownloadIdSet current_set, prev_set;
|
| - for (ItemMap::const_iterator iter = downloads_.begin();
|
| - iter != downloads_.end(); ++iter) {
|
| - prev_set.insert(iter->first);
|
| - }
|
| - ItemMap current_map;
|
| - for (DownloadManager::DownloadVector::const_iterator iter =
|
| - current_vec.begin();
|
| - iter != current_vec.end(); ++iter) {
|
| - DownloadItem* item = *iter;
|
| - int item_id = item->GetId();
|
| - CHECK(item_id >= 0);
|
| - DCHECK(current_map.find(item_id) == current_map.end());
|
| - current_set.insert(item_id);
|
| - current_map[item_id] = item;
|
| - }
|
| - DownloadIdSet new_set; // current_set - prev_set;
|
| - std::set_difference(current_set.begin(), current_set.end(),
|
| - prev_set.begin(), prev_set.end(),
|
| - std::insert_iterator<DownloadIdSet>(
|
| - new_set, new_set.begin()));
|
| -
|
| - // For each download that was not in the old set of downloads but is in the
|
| - // new set of downloads, fire an onCreated event, register as an Observer of
|
| - // the item, store a json representation of the item so that we can easily
|
| - // find changes in that json representation, and make an OnChangedStat.
|
| - for (DownloadIdSet::const_iterator iter = new_set.begin();
|
| - iter != new_set.end(); ++iter) {
|
| - scoped_ptr<base::DictionaryValue> item(
|
| - DownloadItemToJSON(current_map[*iter]));
|
| - DispatchEvent(extension_event_names::kOnDownloadCreated, item->DeepCopy());
|
| - DCHECK(item_jsons_.find(*iter) == item_jsons_.end());
|
| - on_changed_stats_[*iter] = new OnChangedStat();
|
| - current_map[*iter]->AddObserver(this);
|
| - item_jsons_[*iter] = item.release();
|
| - }
|
| - downloads_.swap(current_map);
|
| -
|
| - // Dispatching onErased is handled in OnDownloadUpdated when an item
|
| - // transitions to the REMOVING state.
|
| -}
|
| -
|
| -void ExtensionDownloadsEventRouter::ManagerGoingDown(
|
| - DownloadManager* manager) {
|
| - manager_->RemoveObserver(this);
|
| - manager_ = NULL;
|
| -}
|
| -
|
| -void ExtensionDownloadsEventRouter::DispatchEvent(
|
| - const char* event_name, base::Value* arg) {
|
| - ListValue args;
|
| - args.Append(arg);
|
| - std::string json_args;
|
| - base::JSONWriter::Write(&args, &json_args);
|
| - profile_->GetExtensionEventRouter()->DispatchEventToRenderers(
|
| - event_name,
|
| - json_args,
|
| - profile_,
|
| - GURL());
|
| -}
|
|
|