summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/download/download_extension_test.cc20
-rw-r--r--chrome/browser/icon_loader_chromeos.cc207
-rw-r--r--chrome/browser/icon_manager_chromeos.cc12
-rw-r--r--chrome/browser/resources/chromeos/active_downloads.js5
-rw-r--r--chrome/browser/resources/downloads.js3
-rw-r--r--chrome/browser/ui/webui/active_downloads_ui.cc4
-rw-r--r--chrome/browser/ui/webui/downloads_dom_handler.cc10
-rw-r--r--chrome/browser/ui/webui/fileicon_source.cc93
-rw-r--r--chrome/browser/ui/webui/fileicon_source.h17
-rw-r--r--chrome/browser/ui/webui/fileicon_source_chromeos.cc259
-rw-r--r--chrome/browser/ui/webui/fileicon_source_chromeos.h33
-rw-r--r--chrome/browser/ui/webui/fileicon_source_unittest.cc98
-rw-r--r--chrome/chrome_browser.gypi10
-rw-r--r--chrome/chrome_tests.gypi1
14 files changed, 419 insertions, 353 deletions
diff --git a/chrome/browser/download/download_extension_test.cc b/chrome/browser/download/download_extension_test.cc
index 6060520..70a37b6 100644
--- a/chrome/browser/download/download_extension_test.cc
+++ b/chrome/browser/download/download_extension_test.cc
@@ -332,15 +332,7 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_PauseResumeCancel) {
// Test downloads.getFileIcon() on in-progress, finished, cancelled and deleted
// download items.
-// TODO(asanka): Fails on ChromeOS (http://crbug.com/109677)
-#if defined(OS_CHROMEOS)
-#define MAYBE_DownloadsApi_FileIcon_Active \
- FAILS_DownloadsApi_FileIcon_Active
-#else
-#define MAYBE_DownloadsApi_FileIcon_Active DownloadsApi_FileIcon_Active
-#endif
-IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
- MAYBE_DownloadsApi_FileIcon_Active) {
+IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_FileIcon_Active) {
DownloadItem* download_item = CreateSlowTestDownload();
ASSERT_TRUE(download_item);
@@ -439,15 +431,7 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
// whether they exist or not. If the file doesn't exist we should receive a
// generic icon from the OS/toolkit that may or may not be specific to the file
// type.
-// TODO(asanka): Fails on ChromeOS (http://crbug.com/109677)
-#if defined(OS_CHROMEOS)
-#define MAYBE_DownloadsApi_FileIcon_History \
- FAILS_DownloadsApi_FileIcon_History
-#else
-#define MAYBE_DownloadsApi_FileIcon_History DownloadsApi_FileIcon_History
-#endif
-IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
- MAYBE_DownloadsApi_FileIcon_History) {
+IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadsApi_FileIcon_History) {
base::Time current(base::Time::Now());
FilePath real_path(
downloads_directory().Append(FILE_PATH_LITERAL("real.txt")));
diff --git a/chrome/browser/icon_loader_chromeos.cc b/chrome/browser/icon_loader_chromeos.cc
new file mode 100644
index 0000000..e47af46
--- /dev/null
+++ b/chrome/browser/icon_loader_chromeos.cc
@@ -0,0 +1,207 @@
+// 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/icon_loader.h"
+
+#include <map>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/lazy_instance.h"
+#include "base/message_loop.h"
+#include "chrome/browser/icon_loader.h"
+#include "grit/component_extension_resources.h"
+#include "skia/ext/image_operations.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/image/image.h"
+#include "webkit/glue/image_decoder.h"
+
+namespace {
+
+// Used with GenerateBitmapWithSize() to indicate that the image shouldn't be
+// resized.
+const int kDoNotResize = -1;
+
+struct IdrBySize {
+ int idr_small;
+ int idr_normal;
+ int idr_large;
+};
+
+// Performs mapping of <file extension, icon size> to icon resource IDs.
+class IconMapper {
+ public:
+ IconMapper();
+
+ // Lookup icon resource ID for a given filename |extension| and
+ // |icon_size|. Defaults to generic icons if there are no icons for the given
+ // extension.
+ int Lookup(const std::string& extension, IconLoader::IconSize icon_size);
+
+ private:
+ typedef std::map<std::string, IdrBySize> ExtensionIconMap;
+
+ ExtensionIconMap extension_icon_map_;
+};
+
+const IdrBySize kAudioIdrs = {
+ IDR_FILE_MANAGER_IMG_FILETYPE_AUDIO,
+ IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_AUDIO,
+ IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_AUDIO
+};
+const IdrBySize kGenericIdrs = {
+ IDR_FILE_MANAGER_IMG_FILETYPE_GENERIC,
+ IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_GENERIC,
+ IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_GENERIC
+};
+const IdrBySize kHtmlIdrs = {
+ IDR_FILE_MANAGER_IMG_FILETYPE_HTML,
+ IDR_FILE_MANAGER_IMG_FILETYPE_HTML,
+ IDR_FILE_MANAGER_IMG_FILETYPE_HTML
+};
+const IdrBySize kImageIdrs = {
+ IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE,
+ IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE,
+ IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE
+};
+const IdrBySize kPdfIdrs = {
+ IDR_FILE_MANAGER_IMG_FILETYPE_PDF,
+ IDR_FILE_MANAGER_IMG_FILETYPE_PDF,
+ IDR_FILE_MANAGER_IMG_FILETYPE_PDF
+};
+const IdrBySize kTextIdrs = {
+ IDR_FILE_MANAGER_IMG_FILETYPE_TEXT,
+ IDR_FILE_MANAGER_IMG_FILETYPE_TEXT,
+ IDR_FILE_MANAGER_IMG_FILETYPE_TEXT
+};
+const IdrBySize kVideoIdrs = {
+ IDR_FILE_MANAGER_IMG_FILETYPE_VIDEO,
+ IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_VIDEO,
+ IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_VIDEO
+};
+
+IconMapper::IconMapper() {
+ // The code below should match translation in
+ // chrome/browser/resources/file_manager/js/file_manager.js
+ // chrome/browser/resources/file_manager/css/file_manager.css
+ // 'audio': /\.(mp3|m4a|oga|ogg|wav)$/i,
+ // 'html': /\.(html?)$/i,
+ // 'image': /\.(bmp|gif|jpe?g|ico|png|webp)$/i,
+ // 'pdf' : /\.(pdf)$/i,
+ // 'text': /\.(pod|rst|txt|log)$/i,
+ // 'video': /\.(mov|mp4|m4v|mpe?g4?|ogm|ogv|ogx|webm)$/i
+
+ const ExtensionIconMap::value_type kExtensionIdrBySizeData[] = {
+#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
+ std::make_pair(".m4a", kAudioIdrs),
+ std::make_pair(".mp3", kAudioIdrs),
+ std::make_pair(".pdf", kPdfIdrs),
+ std::make_pair(".3gp", kVideoIdrs),
+ std::make_pair(".avi", kVideoIdrs),
+ std::make_pair(".m4v", kVideoIdrs),
+ std::make_pair(".mov", kVideoIdrs),
+ std::make_pair(".mp4", kVideoIdrs),
+ std::make_pair(".mpeg", kVideoIdrs),
+ std::make_pair(".mpg", kVideoIdrs),
+ std::make_pair(".mpeg4", kVideoIdrs),
+ std::make_pair(".mpg4", kVideoIdrs),
+#endif
+ std::make_pair(".flac", kAudioIdrs),
+ std::make_pair(".oga", kAudioIdrs),
+ std::make_pair(".ogg", kAudioIdrs),
+ std::make_pair(".wav", kAudioIdrs),
+ std::make_pair(".htm", kHtmlIdrs),
+ std::make_pair(".html", kHtmlIdrs),
+ std::make_pair(".bmp", kImageIdrs),
+ std::make_pair(".gif", kImageIdrs),
+ std::make_pair(".ico", kImageIdrs),
+ std::make_pair(".jpeg", kImageIdrs),
+ std::make_pair(".jpg", kImageIdrs),
+ std::make_pair(".png", kImageIdrs),
+ std::make_pair(".webp", kImageIdrs),
+ std::make_pair(".log", kTextIdrs),
+ std::make_pair(".pod", kTextIdrs),
+ std::make_pair(".rst", kTextIdrs),
+ std::make_pair(".txt", kTextIdrs),
+ std::make_pair(".ogm", kVideoIdrs),
+ std::make_pair(".ogv", kVideoIdrs),
+ std::make_pair(".ogx", kVideoIdrs),
+ std::make_pair(".webm", kVideoIdrs),
+ };
+
+ const size_t kESize = arraysize(kExtensionIdrBySizeData);
+ ExtensionIconMap source(&kExtensionIdrBySizeData[0],
+ &kExtensionIdrBySizeData[kESize]);
+ extension_icon_map_.swap(source);
+}
+
+int IconMapper::Lookup(const std::string& extension,
+ IconLoader::IconSize icon_size) {
+ DCHECK(icon_size == IconLoader::SMALL ||
+ icon_size == IconLoader::NORMAL ||
+ icon_size == IconLoader::LARGE);
+ ExtensionIconMap::const_iterator it = extension_icon_map_.find(extension);
+ const IdrBySize& idrbysize =
+ ((it == extension_icon_map_.end()) ? kGenericIdrs : it->second);
+ int idr = -1;
+ switch (icon_size) {
+ case IconLoader::SMALL: idr = idrbysize.idr_small; break;
+ case IconLoader::NORMAL: idr = idrbysize.idr_normal; break;
+ case IconLoader::LARGE: idr = idrbysize.idr_large; break;
+ case IconLoader::ALL:
+ default:
+ NOTREACHED();
+ }
+ return idr;
+}
+
+// Returns a copy of |source| that is |pixel_size| in width and height. If
+// |pixel_size| is |kDoNotResize|, returns an unmodified copy of |source|.
+// |source| must be a square image (width == height).
+SkBitmap* GenerateBitmapWithSize(SkBitmap* source, int pixel_size) {
+ DCHECK(source);
+ DCHECK(source->width() == source->height());
+
+ if (pixel_size == kDoNotResize || source->width() == pixel_size)
+ return new SkBitmap(*source);
+
+ return new SkBitmap(skia::ImageOperations::Resize(
+ *source, skia::ImageOperations::RESIZE_BEST, pixel_size, pixel_size));
+}
+
+int IconSizeToPixelSize(IconLoader::IconSize size) {
+ switch (size) {
+ case IconLoader::SMALL: return 16;
+ case IconLoader::NORMAL: return 32;
+ case IconLoader::LARGE: // fallthrough
+ // On ChromeOS, we consider LARGE to mean "the largest image we have."
+ // Since we have already chosen the largest applicable image resource, we
+ // return the image as-is.
+ case IconLoader::ALL: // fallthrough
+ default:
+ return kDoNotResize;
+ }
+}
+
+} // namespace
+
+void IconLoader::ReadIcon() {
+ static base::LazyInstance<IconMapper>::Leaky icon_mapper =
+ LAZY_INSTANCE_INITIALIZER;
+ int idr = icon_mapper.Get().Lookup(group_, icon_size_);
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ scoped_refptr<RefCountedStaticMemory> bytes(rb.LoadDataResourceBytes(idr));
+ DCHECK(bytes.get());
+ SkBitmap bitmap;
+ if (!gfx::PNGCodec::Decode(bytes->front(), bytes->size(), &bitmap))
+ NOTREACHED();
+ image_.reset(new gfx::Image(
+ GenerateBitmapWithSize(&bitmap, IconSizeToPixelSize(icon_size_))));
+ target_message_loop_->PostTask(
+ FROM_HERE, base::Bind(&IconLoader::NotifyDelegate, this));
+}
diff --git a/chrome/browser/icon_manager_chromeos.cc b/chrome/browser/icon_manager_chromeos.cc
new file mode 100644
index 0000000..2f82c8f
--- /dev/null
+++ b/chrome/browser/icon_manager_chromeos.cc
@@ -0,0 +1,12 @@
+// 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/icon_manager.h"
+
+#include "base/file_path.h"
+#include "base/string_util.h"
+
+IconGroupID IconManager::GetGroupIDFromFilepath(const FilePath& filepath) {
+ return StringToLowerASCII(filepath.Extension());
+}
diff --git a/chrome/browser/resources/chromeos/active_downloads.js b/chrome/browser/resources/chromeos/active_downloads.js
index 3615d59..1937c11 100644
--- a/chrome/browser/resources/chromeos/active_downloads.js
+++ b/chrome/browser/resources/chromeos/active_downloads.js
@@ -233,10 +233,11 @@ DownloadRow.prototype = {
},
setDangerousIcon_: function(warning) {
+ var escapedPath = encodeURIComponent(this.path).replace(/'/g,'%27');
this.icon.className = warning ? 'iconwarning' : 'icon';
this.icon.style.background = warning ? '' :
- 'url(chrome://fileicon' + escape(this.path) +
- '?iconsize=small) no-repeat';
+ 'url(\'chrome://fileicon/' + escapedPath +
+ '?iconsize=small\') no-repeat';
},
/**
diff --git a/chrome/browser/resources/downloads.js b/chrome/browser/resources/downloads.js
index ecdba4e..735326c 100644
--- a/chrome/browser/resources/downloads.js
+++ b/chrome/browser/resources/downloads.js
@@ -394,7 +394,8 @@ Download.prototype.update = function(download) {
this.safe_.style.display = 'none';
} else {
downloads.scheduleIconLoad(this.nodeImg_,
- 'chrome://fileicon/' + this.filePath_);
+ 'chrome://fileicon/' +
+ encodeURIComponent(this.filePath_));
if (this.state_ == Download.States.COMPLETE &&
!this.fileExternallyRemoved_) {
diff --git a/chrome/browser/ui/webui/active_downloads_ui.cc b/chrome/browser/ui/webui/active_downloads_ui.cc
index 669a97c..d12bd50 100644
--- a/chrome/browser/ui/webui/active_downloads_ui.cc
+++ b/chrome/browser/ui/webui/active_downloads_ui.cc
@@ -38,7 +38,7 @@
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
-#include "chrome/browser/ui/webui/fileicon_source_chromeos.h"
+#include "chrome/browser/ui/webui/fileicon_source.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
@@ -181,7 +181,7 @@ ActiveDownloadsHandler::~ActiveDownloadsHandler() {
void ActiveDownloadsHandler::RegisterMessages() {
profile_ = Profile::FromWebUI(web_ui());
- profile_->GetChromeURLDataManager()->AddDataSource(new FileIconSourceCros());
+ profile_->GetChromeURLDataManager()->AddDataSource(new FileIconSource());
web_ui()->RegisterMessageCallback("getDownloads",
base::Bind(&ActiveDownloadsHandler::HandleGetDownloads,
diff --git a/chrome/browser/ui/webui/downloads_dom_handler.cc b/chrome/browser/ui/webui/downloads_dom_handler.cc
index d1fc345..d93c50c 100644
--- a/chrome/browser/ui/webui/downloads_dom_handler.cc
+++ b/chrome/browser/ui/webui/downloads_dom_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -27,7 +27,6 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
#include "chrome/browser/ui/webui/fileicon_source.h"
-#include "chrome/browser/ui/webui/fileicon_source_chromeos.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/user_metrics.h"
@@ -128,12 +127,7 @@ DownloadsDOMHandler::DownloadsDOMHandler(DownloadManager* dlm)
download_manager_(dlm) {
// Create our fileicon data source.
Profile::FromBrowserContext(dlm->GetBrowserContext())->
- GetChromeURLDataManager()->AddDataSource(
-#if defined(OS_CHROMEOS)
- new FileIconSourceCros());
-#else
- new FileIconSource());
-#endif // OS_CHROMEOS
+ GetChromeURLDataManager()->AddDataSource(new FileIconSource());
}
DownloadsDOMHandler::~DownloadsDOMHandler() {
diff --git a/chrome/browser/ui/webui/fileicon_source.cc b/chrome/browser/ui/webui/fileicon_source.cc
index 30ee3da..17d10c5 100644
--- a/chrome/browser/ui/webui/fileicon_source.cc
+++ b/chrome/browser/ui/webui/fileicon_source.cc
@@ -1,48 +1,93 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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/ui/webui/fileicon_source.h"
+#include "base/basictypes.h"
#include "base/callback.h"
#include "base/file_path.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/string_split.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/time_format.h"
+#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "net/base/escape.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image.h"
-// The path used in internal URLs to file icon data.
-static const char kFileIconPath[] = "fileicon";
+namespace {
-FileIconSource::FileIconSource()
- : DataSource(kFileIconPath, MessageLoop::current()) {}
+typedef std::map<std::string, IconLoader::IconSize> QueryIconSizeMap;
-FileIconSource::~FileIconSource() {
- cancelable_consumer_.CancelAllRequests();
-}
+// The path used in internal URLs to file icon data.
+const char kFileIconPath[] = "fileicon";
-void FileIconSource::StartDataRequest(const std::string& path,
- bool is_incognito,
- int request_id) {
- std::string escaped_path = net::UnescapeURLComponent(path,
- net::UnescapeRule::SPACES);
+// URL parameter specifying icon size.
+const char kIconSize[] = "iconsize";
+
+// Assuming the url is of the form '/path?query', convert the path portion into
+// a FilePath and return the resulting |file_path| and |query|. The path
+// portion may have been encoded using encodeURIComponent().
+void GetFilePathAndQuery(const std::string& url,
+ FilePath* file_path,
+ std::string* query) {
+ // We receive the url with chrome://fileicon/ stripped but GURL expects it.
+ const GURL gurl("chrome://fileicon/" + url);
+ std::string path =
+ net::UnescapeURLComponent(gurl.path().substr(1),
+ (net::UnescapeRule::URL_SPECIAL_CHARS |
+ net::UnescapeRule::SPACES));
#if defined(OS_WIN)
// The path we receive has the wrong slashes and escaping for what we need;
// this only appears to matter for getting icons from .exe files.
- std::replace(escaped_path.begin(), escaped_path.end(), '/', '\\');
- FilePath escaped_filepath(UTF8ToWide(escaped_path));
+ std::replace(path.begin(), path.end(), '/', '\\');
+ *file_path = FilePath(UTF8ToWide(path));
#elif defined(OS_POSIX)
// The correct encoding on Linux may not actually be UTF8.
- FilePath escaped_filepath(escaped_path);
+ *file_path = FilePath(path);
#endif
+ query->assign(gurl.query());
+}
+
+IconLoader::IconSize SizeStringToIconSize(const std::string& size_string) {
+ if (size_string == "small") return IconLoader::SMALL;
+ if (size_string == "large") return IconLoader::LARGE;
+ // We default to NORMAL if we don't recognize the size_string. Including
+ // size_string=="normal".
+ return IconLoader::NORMAL;
+}
+
+// Simple parser for data on the query.
+IconLoader::IconSize QueryToIconSize(const std::string& query) {
+ typedef std::pair<std::string, std::string> KVPair;
+ std::vector<KVPair> parameters;
+ base::SplitStringIntoKeyValuePairs(query, '=', '&', &parameters);
+ for (std::vector<KVPair>::const_iterator iter = parameters.begin();
+ iter != parameters.end(); ++iter) {
+ if (iter->first == kIconSize)
+ return SizeStringToIconSize(iter->second);
+ }
+ return IconLoader::NORMAL;
+}
+
+} // namespace
+
+FileIconSource::FileIconSource()
+ : DataSource(kFileIconPath, MessageLoop::current()) {}
+
+FileIconSource::~FileIconSource() {
+ cancelable_consumer_.CancelAllRequests();
+}
+void FileIconSource::FetchFileIcon(const FilePath& path,
+ IconLoader::IconSize icon_size,
+ int request_id) {
IconManager* im = g_browser_process->icon_manager();
- gfx::Image* icon = im->LookupIcon(escaped_filepath, IconLoader::NORMAL);
+ gfx::Image* icon = im->LookupIcon(path, icon_size);
if (icon) {
scoped_refptr<RefCountedBytes> icon_data(new RefCountedBytes);
@@ -51,9 +96,8 @@ void FileIconSource::StartDataRequest(const std::string& path,
SendResponse(request_id, icon_data);
} else {
// Icon was not in cache, go fetch it slowly.
- IconManager::Handle h = im->LoadIcon(escaped_filepath,
- IconLoader::NORMAL,
- &cancelable_consumer_,
+ IconManager::Handle h = im->LoadIcon(
+ path, icon_size, &cancelable_consumer_,
base::Bind(&FileIconSource::OnFileIconDataAvailable,
base::Unretained(this)));
@@ -62,6 +106,15 @@ void FileIconSource::StartDataRequest(const std::string& path,
}
}
+void FileIconSource::StartDataRequest(const std::string& url_path,
+ bool is_incognito,
+ int request_id) {
+ std::string query;
+ FilePath file_path;
+ GetFilePathAndQuery(url_path, &file_path, &query);
+ FetchFileIcon(file_path, QueryToIconSize(query), request_id);
+}
+
std::string FileIconSource::GetMimeType(const std::string&) const {
// Rely on image decoder inferring the correct type.
return std::string();
diff --git a/chrome/browser/ui/webui/fileicon_source.h b/chrome/browser/ui/webui/fileicon_source.h
index f42fabf..84858c7 100644
--- a/chrome/browser/ui/webui/fileicon_source.h
+++ b/chrome/browser/ui/webui/fileicon_source.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -8,6 +8,7 @@
#include <string>
+#include "base/file_path.h"
#include "chrome/browser/icon_manager.h"
#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
@@ -36,14 +37,18 @@ class FileIconSource : public ChromeURLDataManager::DataSource {
IconManager::Handle request_handle,
gfx::Image* icon);
- private:
+ protected:
virtual ~FileIconSource();
- CancelableRequestConsumerT<int, 0> cancelable_consumer_;
+ // Once the |path| and |icon_size| has been determined from the request, this
+ // function is called to perform the actual fetch. Declared as virtual for
+ // testing.
+ virtual void FetchFileIcon(const FilePath& path,
+ IconLoader::IconSize icon_size,
+ int request_id);
- // Raw PNG representation of the favicon to show when the favicon
- // database doesn't have a favicon for a webpage.
- scoped_refptr<RefCountedBytes> default_favicon_;
+ private:
+ CancelableRequestConsumerT<int, 0> cancelable_consumer_;
DISALLOW_COPY_AND_ASSIGN(FileIconSource);
};
diff --git a/chrome/browser/ui/webui/fileicon_source_chromeos.cc b/chrome/browser/ui/webui/fileicon_source_chromeos.cc
deleted file mode 100644
index d0dc1d5..0000000
--- a/chrome/browser/ui/webui/fileicon_source_chromeos.cc
+++ /dev/null
@@ -1,259 +0,0 @@
-// 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 "chrome/browser/ui/webui/fileicon_source_chromeos.h"
-
-#include <map>
-#include <utility>
-#include <vector>
-
-#include "base/file_util.h"
-#include "base/memory/singleton.h"
-#include "base/string_split.h"
-#include "base/string_util.h"
-#include "base/threading/thread_restrictions.h"
-#include "chrome/browser/icon_loader.h"
-#include "chrome/browser/io_thread.h"
-#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
-#include "chrome/common/url_constants.h"
-#include "googleurl/src/gurl.h"
-#include "grit/component_extension_resources.h"
-#include "grit/component_extension_resources_map.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "grit/ui_resources.h"
-#include "net/base/escape.h"
-#include "net/base/mime_util.h"
-#include "ui/base/resource/resource_bundle.h"
-
-namespace {
-
-struct IdrBySize {
- int idr_small_;
- int idr_normal_;
- int idr_large_;
-};
-
-typedef std::map<std::string, IconLoader::IconSize> QueryIconSizeMap;
-typedef std::map<std::string, IdrBySize> ExtensionIconSizeMap;
-
-const char *kIconSize = "iconsize";
-
-const IdrBySize kAudioIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_AUDIO,
- IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_AUDIO,
- IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_AUDIO
-};
-const IdrBySize kDeviceIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_DEVICE,
- IDR_FILE_MANAGER_IMG_FILETYPE_DEVICE,
- IDR_FILE_MANAGER_IMG_FILETYPE_DEVICE
-};
-const IdrBySize kDocIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_DOC,
- IDR_FILE_MANAGER_IMG_FILETYPE_DOC,
- IDR_FILE_MANAGER_IMG_FILETYPE_DOC
-};
-const IdrBySize kFolderIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_FOLDER,
- IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_FOLDER,
- IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_FOLDER
-};
-const IdrBySize kGenericIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_GENERIC,
- IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_GENERIC,
- IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_GENERIC
-};
-const IdrBySize kHtmlIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_HTML,
- IDR_FILE_MANAGER_IMG_FILETYPE_HTML,
- IDR_FILE_MANAGER_IMG_FILETYPE_HTML
-};
-const IdrBySize kImageIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE,
- IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE,
- IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE
-};
-const IdrBySize kPdfIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_PDF,
- IDR_FILE_MANAGER_IMG_FILETYPE_PDF,
- IDR_FILE_MANAGER_IMG_FILETYPE_PDF
-};
-const IdrBySize kPresentationIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_PRESENTATION,
- IDR_FILE_MANAGER_IMG_FILETYPE_PRESENTATION,
- IDR_FILE_MANAGER_IMG_FILETYPE_PRESENTATION
-};
-const IdrBySize kSpreadsheetIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_SPREADSHEET,
- IDR_FILE_MANAGER_IMG_FILETYPE_SPREADSHEET,
- IDR_FILE_MANAGER_IMG_FILETYPE_SPREADSHEET
-};
-const IdrBySize kUnreadableDeviceIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_UNREADABLE_DEVICE,
- IDR_FILE_MANAGER_IMG_FILETYPE_UNREADABLE_DEVICE,
- IDR_FILE_MANAGER_IMG_FILETYPE_UNREADABLE_DEVICE
-};
-const IdrBySize kTextIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_TEXT,
- IDR_FILE_MANAGER_IMG_FILETYPE_TEXT,
- IDR_FILE_MANAGER_IMG_FILETYPE_TEXT
-};
-const IdrBySize kVideoIdrs = {
- IDR_FILE_MANAGER_IMG_FILETYPE_VIDEO,
- IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_VIDEO,
- IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_VIDEO
-};
-
-QueryIconSizeMap BuildQueryIconSizeMap() {
- QueryIconSizeMap::value_type kQueryIconSizeData[] = {
- std::make_pair("small", IconLoader::SMALL),
- std::make_pair("normal", IconLoader::NORMAL),
- std::make_pair("large", IconLoader::LARGE)
- };
-
- size_t kQSize = arraysize(kQueryIconSizeData);
- return QueryIconSizeMap(&kQueryIconSizeData[0],
- &kQueryIconSizeData[kQSize]);
-}
-
-// The code below should match translation in
-// chrome/browser/resources/file_manager/js/file_manager.js
-// chrome/browser/resources/file_manager/css/file_manager.css
-// 'audio': /\.(mp3|m4a|oga|ogg|wav)$/i,
-// 'html': /\.(html?)$/i,
-// 'image': /\.(bmp|gif|jpe?g|ico|png|webp)$/i,
-// 'pdf' : /\.(pdf)$/i,
-// 'text': /\.(pod|rst|txt|log)$/i,
-// 'video': /\.(mov|mp4|m4v|mpe?g4?|ogm|ogv|ogx|webm)$/i
-
-ExtensionIconSizeMap BuildExtensionIdrSizeMap() {
- const ExtensionIconSizeMap::value_type kExtensionIdrBySizeData[] = {
-#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
- std::make_pair(".m4a", kAudioIdrs),
- std::make_pair(".mp3", kAudioIdrs),
- std::make_pair(".pdf", kPdfIdrs),
- std::make_pair(".3gp", kVideoIdrs),
- std::make_pair(".avi", kVideoIdrs),
- std::make_pair(".m4v", kVideoIdrs),
- std::make_pair(".mov", kVideoIdrs),
- std::make_pair(".mp4", kVideoIdrs),
- std::make_pair(".mpeg", kVideoIdrs),
- std::make_pair(".mpg", kVideoIdrs),
- std::make_pair(".mpeg4", kVideoIdrs),
- std::make_pair(".mpg4", kVideoIdrs),
-#endif
- std::make_pair(".flac", kAudioIdrs),
- std::make_pair(".oga", kAudioIdrs),
- std::make_pair(".ogg", kAudioIdrs),
- std::make_pair(".wav", kAudioIdrs),
- std::make_pair(".htm", kHtmlIdrs),
- std::make_pair(".html", kHtmlIdrs),
- std::make_pair(".bmp", kImageIdrs),
- std::make_pair(".gif", kImageIdrs),
- std::make_pair(".ico", kImageIdrs),
- std::make_pair(".jpeg", kImageIdrs),
- std::make_pair(".jpg", kImageIdrs),
- std::make_pair(".png", kImageIdrs),
- std::make_pair(".webp", kImageIdrs),
- std::make_pair(".log", kTextIdrs),
- std::make_pair(".pod", kTextIdrs),
- std::make_pair(".rst", kTextIdrs),
- std::make_pair(".txt", kTextIdrs),
- std::make_pair(".ogm", kVideoIdrs),
- std::make_pair(".ogv", kVideoIdrs),
- std::make_pair(".ogx", kVideoIdrs),
- std::make_pair(".webm", kVideoIdrs),
- };
-
- const size_t kESize = arraysize(kExtensionIdrBySizeData);
- return ExtensionIconSizeMap(&kExtensionIdrBySizeData[0],
- &kExtensionIdrBySizeData[kESize]);
-}
-
-// Split on the very first &. The first part is path, the rest query.
-void GetExtensionAndQuery(const std::string& url,
- std::string* extension,
- std::string* query) {
- // We receive the url with chrome://fileicon/ stripped but GURL expects it.
- const GURL gurl("chrome://fileicon/" + net::EscapePath(url));
- const std::string path = gurl.path();
- *extension = StringToLowerASCII(FilePath(path).Extension());
- *query = gurl.query();
-}
-
-// Simple parser for data on the query.
-IconLoader::IconSize QueryToIconSize(const std::string& query) {
- CR_DEFINE_STATIC_LOCAL(
- QueryIconSizeMap, kQueryIconSizeMap, (BuildQueryIconSizeMap()));
- typedef std::pair<std::string, std::string> KVPair;
- std::vector<KVPair> parameters;
- if (base::SplitStringIntoKeyValuePairs(query, '=', '&', &parameters)) {
- for (std::vector<KVPair>::const_iterator itk = parameters.begin();
- itk != parameters.end(); ++itk) {
- if (itk->first == kIconSize) {
- QueryIconSizeMap::const_iterator itq(
- kQueryIconSizeMap.find(itk->second));
- if (itq != kQueryIconSizeMap.end())
- return itq->second;
- }
- }
- }
- return IconLoader::NORMAL;
-}
-
-// Finds matching resource of proper size. Fallback to generic.
-int UrlToIDR(const std::string& url) {
- CR_DEFINE_STATIC_LOCAL(
- ExtensionIconSizeMap, kExtensionIdrSizeMap, (BuildExtensionIdrSizeMap()));
- std::string extension, query;
- int idr = -1;
- GetExtensionAndQuery(url, &extension, &query);
- const IconLoader::IconSize size = QueryToIconSize(query);
- ExtensionIconSizeMap::const_iterator it =
- kExtensionIdrSizeMap.find(extension);
- if (it != kExtensionIdrSizeMap.end()) {
- IdrBySize idrbysize = it->second;
- if (size == IconLoader::SMALL) {
- idr = idrbysize.idr_small_;
- } else if (size == IconLoader::NORMAL) {
- idr = idrbysize.idr_normal_;
- } else if (size == IconLoader::LARGE) {
- idr = idrbysize.idr_large_;
- }
- }
- if (idr == -1) {
- if (size == IconLoader::SMALL) {
- idr = kGenericIdrs.idr_small_;
- } else if (size == IconLoader::NORMAL) {
- idr = kGenericIdrs.idr_normal_;
- } else {
- idr = kGenericIdrs.idr_large_;
- }
- }
- return idr;
-}
-} // namespace
-
-FileIconSourceCros::FileIconSourceCros()
- : DataSource("fileicon", NULL) {
-}
-
-FileIconSourceCros::~FileIconSourceCros() {
-}
-
-void FileIconSourceCros::StartDataRequest(const std::string& url,
- bool is_incognito,
- int request_id) {
- int idr = UrlToIDR(url);
- const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- scoped_refptr<RefCountedStaticMemory> bytes(rb.LoadDataResourceBytes(idr));
- SendResponse(request_id, bytes);
-}
-
-// The mime type refers to the type of the response/icon served.
-std::string FileIconSourceCros::GetMimeType(
- const std::string& url) const {
- return "image/png";
-}
diff --git a/chrome/browser/ui/webui/fileicon_source_chromeos.h b/chrome/browser/ui/webui/fileicon_source_chromeos.h
deleted file mode 100644
index 5471875..0000000
--- a/chrome/browser/ui/webui/fileicon_source_chromeos.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_FILEICON_SOURCE_CHROMEOS_H_
-#define CHROME_BROWSER_UI_WEBUI_FILEICON_SOURCE_CHROMEOS_H_
-#pragma once
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
-
-// A DataSource for chrome://fileicon/ URLs, but reads from
-// resources instead of disk. Allows for parameterization
-// via chrome://fileicon/path.ext?size=[small|medium|large]
-class FileIconSourceCros : public ChromeURLDataManager::DataSource {
- public:
- FileIconSourceCros();
-
- // Overridden from ChromeURLDataManager::DataSource.
- virtual void StartDataRequest(const std::string& url,
- bool is_incognito,
- int request_id) OVERRIDE;
- virtual std::string GetMimeType(const std::string&) const OVERRIDE;
-
- private:
- virtual ~FileIconSourceCros();
-
- DISALLOW_COPY_AND_ASSIGN(FileIconSourceCros);
-};
-
-#endif // CHROME_BROWSER_UI_WEBUI_FILEICON_SOURCE_CHROMEOS_H_
diff --git a/chrome/browser/ui/webui/fileicon_source_unittest.cc b/chrome/browser/ui/webui/fileicon_source_unittest.cc
new file mode 100644
index 0000000..1918709
--- /dev/null
+++ b/chrome/browser/ui/webui/fileicon_source_unittest.cc
@@ -0,0 +1,98 @@
+// 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 "base/memory/ref_counted_memory.h"
+#include "base/message_loop.h"
+#include "chrome/browser/icon_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/fileicon_source.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/test/test_browser_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using content::BrowserThread;
+
+namespace {
+
+class TestFileIconSource : public FileIconSource {
+ public:
+ explicit TestFileIconSource() {}
+
+ MOCK_METHOD3(FetchFileIcon, void(const FilePath& path,
+ IconLoader::IconSize icon_size,
+ int request_id));
+};
+
+class FileIconSourceTest : public testing::Test {
+ public:
+ FileIconSourceTest()
+ : loop_(MessageLoop::TYPE_UI),
+ ui_thread_(BrowserThread::UI, MessageLoop::current()),
+ file_thread_(BrowserThread::FILE, MessageLoop::current()) {}
+
+ static TestFileIconSource* CreateFileIconSource() {
+ return new TestFileIconSource();
+ }
+
+ private:
+ MessageLoop loop_;
+ content::TestBrowserThread ui_thread_;
+ content::TestBrowserThread file_thread_;
+};
+
+const struct FetchFileIconExpectation {
+ const char* request_path;
+ const FilePath::CharType* unescaped_path;
+ IconLoader::IconSize size;
+} kBasicExpectations[] = {
+ { "foo?bar", FILE_PATH_LITERAL("foo"), IconLoader::NORMAL },
+ { "foo?iconsize=small", FILE_PATH_LITERAL("foo"), IconLoader::SMALL },
+ { "foo?iconsize=normal", FILE_PATH_LITERAL("foo"), IconLoader::NORMAL },
+ { "foo?iconsize=large", FILE_PATH_LITERAL("foo"), IconLoader::LARGE },
+ { "foo?iconsize=asdf", FILE_PATH_LITERAL("foo"), IconLoader::NORMAL },
+ { "foo?blah=b&iconsize=small", FILE_PATH_LITERAL("foo"), IconLoader::SMALL },
+ { "foo?blah&iconsize=small", FILE_PATH_LITERAL("foo"), IconLoader::SMALL },
+ { "a%3Fb%26c%3Dd.txt?iconsize=small", FILE_PATH_LITERAL("a?b&c=d.txt"),
+ IconLoader::SMALL },
+ { "a%3Ficonsize%3Dsmall?iconsize=large",
+ FILE_PATH_LITERAL("a?iconsize=small"), IconLoader::LARGE },
+ { "o%40%23%24%25%26*()%20%2B%3D%3F%2C%3A%3B%22.jpg",
+ FILE_PATH_LITERAL("o@#$%&*() +=?,:;\".jpg"), IconLoader::NORMAL },
+#if defined(OS_WIN)
+ { "c:/foo/bar/baz", FILE_PATH_LITERAL("c:\\foo\\bar\\baz"),
+ IconLoader::NORMAL },
+ { "/foo?bar=asdf&asdf", FILE_PATH_LITERAL("\\foo"), IconLoader::NORMAL },
+ { "c%3A%2Fusers%2Ffoo%20user%2Fbar.txt",
+ FILE_PATH_LITERAL("c:\\users\\foo user\\bar.txt"), IconLoader::NORMAL },
+ { "c%3A%2Fusers%2F%C2%A9%202000.pdf",
+ FILE_PATH_LITERAL("c:\\users\\\xa9 2000.pdf"), IconLoader::NORMAL },
+ { "%E0%B6%9A%E0%B6%BB%E0%B7%9D%E0%B6%B8%E0%B7%8A",
+ FILE_PATH_LITERAL("\x0d9a\x0dbb\x0ddd\x0db8\x0dca"), IconLoader::NORMAL },
+ { "%2Ffoo%2Fbar", FILE_PATH_LITERAL("\\foo\\bar"), IconLoader::NORMAL },
+ { "%2Fbaz%20(1).txt?iconsize=small", FILE_PATH_LITERAL("\\baz (1).txt"),
+ IconLoader::SMALL },
+#else
+ { "/foo/bar/baz", FILE_PATH_LITERAL("/foo/bar/baz"), IconLoader::NORMAL },
+ { "/foo?bar", FILE_PATH_LITERAL("/foo"), IconLoader::NORMAL },
+ { "%2Ffoo%2f%E0%B6%9A%E0%B6%BB%E0%B7%9D%E0%B6%B8%E0%B7%8A",
+ FILE_PATH_LITERAL("/foo/\xe0\xb6\x9a\xe0\xb6\xbb\xe0\xb7\x9d")
+ FILE_PATH_LITERAL("\xe0\xb6\xb8\xe0\xb7\x8a"), IconLoader::NORMAL },
+ { "%2Ffoo%2Fbar", FILE_PATH_LITERAL("/foo/bar"), IconLoader::NORMAL },
+ { "%2Fbaz%20(1).txt?iconsize=small", FILE_PATH_LITERAL("/baz (1).txt"),
+ IconLoader::SMALL },
+#endif
+};
+
+} // namespace
+
+TEST_F(FileIconSourceTest, FileIconSource_Parse) {
+ for (unsigned i = 0; i < arraysize(kBasicExpectations); i++) {
+ scoped_refptr<TestFileIconSource> source(CreateFileIconSource());
+ EXPECT_CALL(*source.get(),
+ FetchFileIcon(FilePath(kBasicExpectations[i].unescaped_path),
+ kBasicExpectations[i].size, i));
+ source->StartDataRequest(kBasicExpectations[i].request_path, false, i);
+ }
+}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 7a12bdc..6c06411 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1450,11 +1450,13 @@
'browser/history/visitsegment_database.h',
'browser/icon_loader.cc',
'browser/icon_loader.h',
+ 'browser/icon_loader_chromeos.cc',
'browser/icon_loader_linux.cc',
'browser/icon_loader_mac.mm',
'browser/icon_loader_win.cc',
'browser/icon_manager.cc',
'browser/icon_manager.h',
+ 'browser/icon_manager_chromeos.cc',
'browser/icon_manager_linux.cc',
'browser/icon_manager_mac.mm',
'browser/icon_manager_win.cc',
@@ -3840,8 +3842,6 @@
'browser/ui/webui/favicon_source.h',
'browser/ui/webui/fileicon_source.cc',
'browser/ui/webui/fileicon_source.h',
- 'browser/ui/webui/fileicon_source_chromeos.cc',
- 'browser/ui/webui/fileicon_source_chromeos.h',
'browser/ui/webui/flags_ui.cc',
'browser/ui/webui/flags_ui.h',
'browser/ui/webui/flash_ui.cc',
@@ -4279,6 +4279,8 @@
['exclude', 'browser/extensions/extension_input_method_api.cc'],
['exclude', 'browser/extensions/extension_input_method_api.h'],
['exclude', 'browser/extensions/extension_tts_api_chromeos.cc'],
+ ['exclude', 'browser/icon_loader_chromeos.cc'],
+ ['exclude', 'browser/icon_manager_chromeos.cc'],
['exclude', 'browser/oom_priority_manager.cc'],
['exclude', 'browser/oom_priority_manager.h'],
['exclude', 'browser/policy/auto_enrollment_client.cc'],
@@ -4305,8 +4307,6 @@
['exclude', 'browser/ui/webui/about_page/about_page_ui.cc'],
['exclude', 'browser/ui/webui/about_page/about_page_ui.h'],
['exclude', 'browser/ui/webui/active_downloads_ui.cc'],
- ['exclude', 'browser/ui/webui/fileicon_source_chromeos.cc'],
- ['exclude', 'browser/ui/webui/fileicon_source_chromeos.h'],
],
}],
['chromeos==1', {
@@ -4323,6 +4323,8 @@
'browser/first_run/upgrade_util.cc',
'browser/first_run/upgrade_util.h',
'browser/first_run/upgrade_util_linux.cc',
+ 'browser/icon_loader_linux.cc',
+ 'browser/icon_manager_linux.cc',
'browser/idle_linux.cc',
'browser/password_manager/native_backend_gnome_x.cc',
'browser/password_manager/native_backend_gnome_x.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index ff1a325..deadf16 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1971,6 +1971,7 @@
'browser/ui/views/tabs/fake_base_tab_strip_controller.h',
'browser/ui/views/tabs/tab_strip_unittest.cc',
'browser/ui/webui/chrome_web_ui_data_source_unittest.cc',
+ 'browser/ui/webui/fileicon_source_unittest.cc',
'browser/ui/webui/html_dialog_tab_contents_delegate_unittest.cc',
'browser/ui/webui/options/chromeos/virtual_keyboard_manager_handler_unittest.cc',
'browser/ui/webui/options/language_options_handler_unittest.cc',