diff options
-rw-r--r-- | chrome/browser/browser.vcproj | 8 | ||||
-rw-r--r-- | chrome/browser/icon_loader.cc | 243 | ||||
-rw-r--r-- | chrome/browser/icon_loader.h | 72 | ||||
-rw-r--r-- | chrome/browser/icon_loader_win.cc | 80 | ||||
-rw-r--r-- | chrome/browser/icon_loader_win.h | 40 | ||||
-rw-r--r-- | chrome/browser/icon_manager.cc | 11 | ||||
-rw-r--r-- | chrome/browser/icon_manager.h | 2 | ||||
-rw-r--r-- | chrome/chrome.gyp | 4 |
8 files changed, 147 insertions, 313 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 879c790..def66f1 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -378,11 +378,15 @@ > </File> <File - RelativePath=".\icon_loader.cc" + RelativePath=".\icon_loader.h" > </File> <File - RelativePath=".\icon_loader.h" + RelativePath=".\icon_loader_win.cc" + > + </File> + <File + RelativePath=".\icon_loader_win.h" > </File> <File diff --git a/chrome/browser/icon_loader.cc b/chrome/browser/icon_loader.cc deleted file mode 100644 index 99dbe40..0000000 --- a/chrome/browser/icon_loader.cc +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) 2006-2008 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 <windows.h> -#include <shellapi.h> - -#include "app/gfx/icon_util.h" -#include "base/file_util.h" -#include "base/gfx/size.h" -#include "base/message_loop.h" -#include "base/ref_counted.h" -#include "base/string_util.h" -#include "base/task.h" -#include "base/thread.h" -#include "chrome/browser/browser_process.h" - -#include "SkBitmap.h" - -namespace { - -class IconLoaderProcessor : - public base::RefCountedThreadSafe<IconLoaderProcessor> { - public: - explicit IconLoaderProcessor(IconLoader* target) - : target_(target), - bitmap_(NULL), - small_icon_(NULL), - large_icon_(NULL), - loading_from_resource_(target->loading_from_resource_), - icon_size_(target->icon_size_) { - DCHECK(target); - path_ = target->path_; - target_message_loop_ = MessageLoop::current(); - } - - virtual ~IconLoaderProcessor() { - delete bitmap_; - if (small_icon_) - ::DestroyIcon(small_icon_); - if (large_icon_) { - ::DestroyIcon(large_icon_); - } - } - - // Loads the icon with the specified dimensions. - HICON LoadSizedIcon(int width, int height) { - return static_cast<HICON>(LoadImage(NULL, - path_.value().c_str(), - width, height, - IMAGE_ICON, - LR_LOADTRANSPARENT | LR_LOADFROMFILE)); - } - - // Invoked from the original thread. - void Cancel() { - target_ = NULL; - } - - // Invoked in the file thread. Never access target_ from this method. - void ReadIcon() { - if (loading_from_resource_) - ReadIconFromFileResource(); - else - ReadIconFile(); - - target_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( - this, &IconLoaderProcessor::NotifyFetcher)); - } - - // Invoked on the file thread to read a normal .ico file. - void ReadIconFile() { - // We start by loading the same icon image in the two desired dimensions, - // based on the dimensions we get back when we query the system. - int small_width = ::GetSystemMetrics(SM_CXSMICON); - int small_height = ::GetSystemMetrics(SM_CYSMICON); - int large_width = ::GetSystemMetrics(SM_CXICON); - int large_height = ::GetSystemMetrics(SM_CYICON); - small_icon_ = LoadSizedIcon(small_width, small_height); - large_icon_ = LoadSizedIcon(large_width, large_height); - - // TODO(idana): Bug 991356. Currently, if the client asks for the icon in - // the form of an SkBitmap object, then we try converting the large icon - // into an SkBitmap, if the icon was successfully loaded. If the large icon - // is not available, we convert the small icon. The problem with converting - // the small or the large icon is that the resulting image is going to have - // the same dimensions as the icon (for example, 32X32 pixels). This can be - // problematic if, for example, the client tries to display the resulting - // image as a thumbnail. This will result in the client streching the - // bitmap from 32X32 to 128X128 which will decrease the image's quality. - // - // Since it is possible for web applications to define large .PNG images as - // their icons, the resulting .ico files created for these web applications - // contain icon images in sizes much larger the the system default sizes - // for icons. We can solve the aforementioned limitation by allowing the - // client to specify the size of the resulting image, when requesting an - // SkBitmap. The IconLoader code can then load a larger icon from the .ico - // file. - // - // Note that currently the components in Chrome that deal with SkBitmaps - // that represent application icons use the images to display icon size - // images and therefore the limitation above doesn't really manifest - // itself. - HICON icon_to_convert = NULL; - gfx::Size s; - if (large_icon_) { - icon_to_convert = large_icon_; - s.SetSize(large_width, large_height); - } else if (small_icon_) { - icon_to_convert = small_icon_; - s.SetSize(small_width, small_height); - } - - if (icon_to_convert) { - bitmap_ = IconUtil::CreateSkBitmapFromHICON(icon_to_convert, s); - DCHECK(bitmap_); - if (small_icon_) - ::DestroyIcon(small_icon_); - if (large_icon_) - ::DestroyIcon(large_icon_); - - small_icon_ = NULL; - large_icon_ = NULL; - } - } - - void ReadIconFromFileResource() { - int size = 0; - switch (icon_size_) { - case IconLoader::SMALL: - size = SHGFI_SMALLICON; - break; - case IconLoader::NORMAL: - size = 0; - break; - case IconLoader::LARGE: - size = SHGFI_LARGEICON; - break; - default: - NOTREACHED(); - } - SHFILEINFO file_info = { 0 }; - if (!SHGetFileInfo(path_.value().c_str(), FILE_ATTRIBUTE_NORMAL, &file_info, - sizeof(SHFILEINFO), - SHGFI_ICON | size | SHGFI_USEFILEATTRIBUTES)) - return; - - ICONINFO icon_info = { 0 }; - BITMAP bitmap_info = { 0 }; - - BOOL r = ::GetIconInfo(file_info.hIcon, &icon_info); - DCHECK(r); - r = ::GetObject(icon_info.hbmMask, sizeof(bitmap_info), &bitmap_info); - DCHECK(r); - - gfx::Size icon_size(bitmap_info.bmWidth, bitmap_info.bmHeight); - bitmap_ = IconUtil::CreateSkBitmapFromHICON(file_info.hIcon, icon_size); - } - - // Invoked in the target thread. - void NotifyFetcher() { - if (target_ && target_->OnLoadComplete(bitmap_)) { - // Receiver took ownership of the bitmap. - bitmap_ = NULL; - } - } - - private: - // The message loop object of the thread in which we notify the delegate. - MessageLoop* target_message_loop_; - - // The corresponding file fetcher or NULL if this task has been canceled. - IconLoader* target_; - - // The path of the file. - FilePath path_; - - // Fields from IconLoader that we need to copy as we cannot access them - // directly from the target_ in a thread-safe way. - bool loading_from_resource_; - IconLoader::IconSize icon_size_; - - // The result bitmap. - SkBitmap* bitmap_; - - // The result small icon. - HICON small_icon_; - - // The result large icon. - HICON large_icon_; - - DISALLOW_COPY_AND_ASSIGN(IconLoaderProcessor); -}; - -} // namespace - -// static -IconLoader* IconLoader::CreateIconLoaderForFileResource( - const FilePath& path, IconSize size, Delegate* delegate) { - return new IconLoader(path, true, size, delegate); -} - -IconLoader::IconLoader(const FilePath& path, - bool from_resource, - IconSize size, - Delegate* delegate) - : path_(path), - loading_from_resource_(from_resource), - icon_size_(size), - delegate_(delegate), - processor_(NULL) { - DCHECK(delegate_); -} - -IconLoader::~IconLoader() { - Cancel(); -} - -void IconLoader::Start() { - processor_ = new IconLoaderProcessor(this); - processor_->AddRef(); - g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(processor_, &IconLoaderProcessor::ReadIcon)); -} - -void IconLoader::Cancel() { - if (processor_) { - processor_->Cancel(); - processor_->Release(); - processor_ = NULL; - } - delegate_ = NULL; -} - -bool IconLoader::OnLoadComplete(SkBitmap* bitmap) { - if (delegate_) { - return delegate_->OnSkBitmapLoaded(this, bitmap); - // We are likely deleted after this point. - } - return false; -} diff --git a/chrome/browser/icon_loader.h b/chrome/browser/icon_loader.h index ff1c5a4..a02c6ba 100644 --- a/chrome/browser/icon_loader.h +++ b/chrome/browser/icon_loader.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. @@ -9,25 +9,17 @@ #include "base/basictypes.h" #include "base/file_path.h" - -namespace { -class IconLoaderProcessor; -} +#include "base/ref_counted.h" class SkBitmap; //////////////////////////////////////////////////////////////////////////////// // // A facility to read a file containing an icon asynchronously in the IO -// thread. Clients has the option to get the icon in the form of two HICON -// handles (one for a small icon size and one for a large icon) or in the form -// of an SkBitmap. -// -// This class currently only supports reading .ico files. Please extend as -// needed. +// thread. Returns the icon in the form of an SkBitmap. // //////////////////////////////////////////////////////////////////////////////// -class IconLoader { +class IconLoader : public base::RefCountedThreadSafe<IconLoader> { public: enum IconSize { SMALL = 0, // 16x16 @@ -40,61 +32,21 @@ class IconLoader { // Invoked when an icon has been read. |source| is the IconLoader. If the // icon has been successfully loaded, result is non-null. This method must // return true if it is taking ownership of the returned bitmap. - virtual bool OnSkBitmapLoaded(IconLoader* source, SkBitmap* result) = 0; + virtual bool OnBitmapLoaded(IconLoader* source, SkBitmap* result) = 0; }; - // Create a new IconLoader that loads the icon from the data at contained in - // the file at |path|. - static IconLoader* CreateIconLoaderForFile(const FilePath& path, - Delegate* delegate); - - // Create a new IconLoader that loads the icon in the resource of the file - // at |path|. This is used with .exe/.dll files. - // Note that this generates a SkBitmap (and consequently OnSkBitmapLoaded is - // invoked on the delegate once the load has completed). - static IconLoader* CreateIconLoaderForFileResource(const FilePath& path, - IconSize size, - Delegate* delegate); + IconLoader() { } - ~IconLoader(); + virtual ~IconLoader() { } - // Start the read operation - void Start(); + // Start reading the icon on the file thread. + virtual void Start() = 0; - // Cancel the read operation. The delegate will no longer be contacted. Call - // this method if you need to delete the delegate. - void Cancel(); + // Factory method for returning a platform specific IconLoad. + static IconLoader* Create(const FilePath& path, IconSize size, + Delegate* delegate); private: - friend class IconLoaderProcessor; - - // Use the factory methods CreateIconLoader* instead of using this constructor - IconLoader(const FilePath& path, - bool from_resource, - IconSize size, - Delegate* delegate); - - // Invoked by the processor when the file has been read and an SkBitmap - // object was requested. - bool OnLoadComplete(SkBitmap* result); - - // The path. - FilePath path_; - - // The delegate. - Delegate* delegate_; - - // Whether we are loading the icon from the resource in the file (if false, - // the icon is simply loaded from the file content). - bool loading_from_resource_; - - // The size of the icon that should be loaded from the file resource. - // Not used if loading_from_resource_ is false. - IconSize icon_size_; - - // The underlying object performing the read. - IconLoaderProcessor* processor_; - DISALLOW_COPY_AND_ASSIGN(IconLoader); }; diff --git a/chrome/browser/icon_loader_win.cc b/chrome/browser/icon_loader_win.cc new file mode 100644 index 0000000..998faf1 --- /dev/null +++ b/chrome/browser/icon_loader_win.cc @@ -0,0 +1,80 @@ +// Copyright (c) 2009 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_win.h" + +#include <windows.h> +#include <shellapi.h> + +#include "app/gfx/icon_util.h" +#include "base/gfx/size.h" +#include "base/message_loop.h" +#include "base/thread.h" +#include "chrome/browser/browser_process.h" +#include "skia/include/SkBitmap.h" + +IconLoader* IconLoader::Create(const FilePath& path, IconSize size, + Delegate* delegate) { + return new IconLoaderWin(path, size, delegate); +} + +IconLoaderWin::IconLoaderWin(const FilePath& path, IconSize size, + Delegate* delegate) + : path_(path), + icon_size_(size), + bitmap_(NULL), + delegate_(delegate) { +} + +IconLoaderWin::~IconLoaderWin() { + delete bitmap_; +} + +void IconLoaderWin::Start() { + target_message_loop_ = MessageLoop::current(); + + g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &IconLoaderWin::ReadIcon)); +} + +void IconLoaderWin::ReadIcon() { + int size = 0; + switch (icon_size_) { + case IconLoader::SMALL: + size = SHGFI_SMALLICON; + break; + case IconLoader::NORMAL: + size = 0; + break; + case IconLoader::LARGE: + size = SHGFI_LARGEICON; + break; + default: + NOTREACHED(); + } + SHFILEINFO file_info = { 0 }; + if (!SHGetFileInfo(path_.value().c_str(), FILE_ATTRIBUTE_NORMAL, &file_info, + sizeof(SHFILEINFO), + SHGFI_ICON | size | SHGFI_USEFILEATTRIBUTES)) + return; + + ICONINFO icon_info = { 0 }; + BITMAP bitmap_info = { 0 }; + + BOOL r = ::GetIconInfo(file_info.hIcon, &icon_info); + DCHECK(r); + r = ::GetObject(icon_info.hbmMask, sizeof(bitmap_info), &bitmap_info); + DCHECK(r); + + gfx::Size icon_size(bitmap_info.bmWidth, bitmap_info.bmHeight); + bitmap_ = IconUtil::CreateSkBitmapFromHICON(file_info.hIcon, icon_size); + + target_message_loop_->PostTask(FROM_HERE, + NewRunnableMethod(this, &IconLoaderWin::NotifyDelegate)); +} + +void IconLoaderWin::NotifyDelegate() { + delegate_->OnBitmapLoaded(this, bitmap_); + bitmap_ = NULL; +} diff --git a/chrome/browser/icon_loader_win.h b/chrome/browser/icon_loader_win.h new file mode 100644 index 0000000..ca6c96a --- /dev/null +++ b/chrome/browser/icon_loader_win.h @@ -0,0 +1,40 @@ +// Copyright (c) 2009 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_ICON_LOADER_WIN_H_ +#define CHROME_BROWSER_ICON_LOADER_WIN_H_ + +#include "chrome/browser/icon_loader.h" + +class MessageLoop; + +class IconLoaderWin : public IconLoader { + public: + IconLoaderWin(const FilePath& path, IconSize size, Delegate* delegate); + + virtual ~IconLoaderWin(); + + // IconLoader implementation. + virtual void Start(); + + private: + void ReadIcon(); + + void NotifyDelegate(); + + // The message loop object of the thread in which we notify the delegate. + MessageLoop* target_message_loop_; + + FilePath path_; + + IconSize icon_size_; + + SkBitmap* bitmap_; + + Delegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(IconLoaderWin); +}; + +#endif // CHROME_BROWSER_ICON_LOADER_WIN_H_ diff --git a/chrome/browser/icon_manager.cc b/chrome/browser/icon_manager.cc index 4b0c21b..827e0b1 100644 --- a/chrome/browser/icon_manager.cc +++ b/chrome/browser/icon_manager.cc @@ -48,8 +48,8 @@ IconManager::Handle IconManager::LoadIcon( IconRequest* request = new IconRequest(callback); AddRequest(request, consumer); - IconLoader* loader = - IconLoader::CreateIconLoaderForFileResource(path, size, this); + IconLoader* loader = IconLoader::Create(path, size, this); + loader->AddRef(); loader->Start(); ClientRequest client_request = { request, path, size }; requests_[loader] = client_request; @@ -58,11 +58,12 @@ IconManager::Handle IconManager::LoadIcon( // IconLoader::Delegate implementation ----------------------------------------- -bool IconManager::OnSkBitmapLoaded(IconLoader* source, SkBitmap* result) { - scoped_ptr<IconLoader> scoped_source(source); +bool IconManager::OnBitmapLoaded(IconLoader* source, SkBitmap* result) { + ClientRequests::iterator rit = requests_.find(source); + // Balances the AddRef() in LoadIcon(). + source->Release(); // Look up our client state. - ClientRequests::iterator rit = requests_.find(source); if (rit == requests_.end()) { NOTREACHED(); return false; // Return false to indicate result should be deleted. diff --git a/chrome/browser/icon_manager.h b/chrome/browser/icon_manager.h index 4e44cf4..fbd0cd1 100644 --- a/chrome/browser/icon_manager.h +++ b/chrome/browser/icon_manager.h @@ -81,7 +81,7 @@ public: IconRequestCallback* callback); // IconLoader::Delegate interface. - virtual bool OnSkBitmapLoaded(IconLoader* source, SkBitmap* result); + virtual bool OnBitmapLoaded(IconLoader* source, SkBitmap* result); private: struct CacheKey { diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 1bf6af6..e635d89 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -959,8 +959,9 @@ 'browser/history/visitsegment_database.cc', 'browser/history/visitsegment_database.h', 'browser/hung_renderer_dialog.h', - 'browser/icon_loader.cc', 'browser/icon_loader.h', + 'browser/icon_loader_win.cc', + 'browser/icon_loader_win.h', 'browser/icon_manager.cc', 'browser/icon_manager.h', 'browser/ime_input.cc', @@ -1579,7 +1580,6 @@ 'browser/history/history_indexer.idl', 'browser/history_tab_ui.cc', 'browser/history_view.cc', - 'browser/icon_loader.cc', 'browser/icon_manager.cc', 'browser/ime_input.cc', 'browser/importer/ie_importer.cc', |