Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: chrome/browser/extensions/image_loading_tracker.cc

Issue 1075006: Eliminate all UI thread decoding of extension images.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/image_loading_tracker.h" 5 #include "chrome/browser/extensions/image_loading_tracker.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/logging.h"
9 #include "base/message_loop.h"
10 #include "base/scoped_ptr.h"
11 #include "base/task.h"
12 #include "base/thread.h"
13 #include "chrome/browser/chrome_thread.h" 8 #include "chrome/browser/chrome_thread.h"
14 #include "chrome/common/extensions/extension_resource.h" 9 #include "chrome/common/extensions/extension_resource.h"
15 #include "gfx/size.h"
16 #include "skia/ext/image_operations.h" 10 #include "skia/ext/image_operations.h"
17 #include "third_party/skia/include/core/SkBitmap.h" 11 #include "third_party/skia/include/core/SkBitmap.h"
18 #include "webkit/glue/image_decoder.h" 12 #include "webkit/glue/image_decoder.h"
19 13
20 //////////////////////////////////////////////////////////////////////////////// 14 ////////////////////////////////////////////////////////////////////////////////
21 // ImageLoadingTracker::LoadImageTask 15 // ImageLoadingTracker::ImageLoader
22 16
23 // The LoadImageTask is for asynchronously loading the image on the file thread. 17 // A RefCounted class for loading images on the File thread and reporting back
24 // If the image is successfully loaded and decoded it will report back on the 18 // on the UI thread.
25 // calling thread to let the caller know the image is done loading. 19 class ImageLoadingTracker::ImageLoader
26 class ImageLoadingTracker::LoadImageTask : public Task { 20 : public base::RefCountedThreadSafe<ImageLoader> {
27 public: 21 public:
28 // Constructor for the LoadImageTask class. |tracker| is the object that 22 explicit ImageLoader(ImageLoadingTracker* tracker)
29 // we use to communicate back to the entity that wants the image after we 23 : tracker_(tracker) {
30 // decode it. |path| is the path to load the image from. |max_size| is the
31 // maximum size for the loaded image. It will be resized to fit this if
32 // larger. |index| is an identifier for the image that we pass back to the
33 // caller.
34 LoadImageTask(ImageLoadingTracker* tracker,
35 const ExtensionResource& resource,
36 const gfx::Size& max_size,
37 size_t index)
38 : tracker_(tracker),
39 resource_(resource),
40 max_size_(max_size),
41 index_(index) {
42 CHECK(ChromeThread::GetCurrentThreadIdentifier(&callback_thread_id_)); 24 CHECK(ChromeThread::GetCurrentThreadIdentifier(&callback_thread_id_));
25 DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
43 } 26 }
44 27
45 void ReportBack(SkBitmap* image) { 28 // Lets this class know that the tracker is no longer interested in the
46 ChromeThread::PostTask( 29 // results.
47 callback_thread_id_, FROM_HERE, 30 void StopTracking() {
48 NewRunnableMethod( 31 tracker_ = NULL;
49 tracker_, &ImageLoadingTracker::OnImageLoaded, image, index_));
50 } 32 }
51 33
52 virtual void Run() { 34 // Instructs the loader to load a task on the File thread.
35 void LoadImage(const ExtensionResource& resource,
36 const gfx::Size& max_size) {
37 DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
38 ChromeThread::PostTask(
39 ChromeThread::FILE, FROM_HERE,
40 NewRunnableMethod(this, &ImageLoader::LoadOnFileThread, resource,
41 max_size));
42 }
43
44 void LoadOnFileThread(ExtensionResource resource,
45 const gfx::Size& max_size) {
46 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
47
53 // Read the file from disk. 48 // Read the file from disk.
54 std::string file_contents; 49 std::string file_contents;
55 FilePath path = resource_.GetFilePath(); 50 FilePath path = resource.GetFilePath();
56 if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) { 51 if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) {
57 ReportBack(NULL); 52 ReportBack(NULL, resource);
58 return; 53 return;
59 } 54 }
60 55
61 // Decode the image using WebKit's image decoder. 56 // Decode the image using WebKit's image decoder.
62 const unsigned char* data = 57 const unsigned char* data =
63 reinterpret_cast<const unsigned char*>(file_contents.data()); 58 reinterpret_cast<const unsigned char*>(file_contents.data());
64 webkit_glue::ImageDecoder decoder; 59 webkit_glue::ImageDecoder decoder;
65 scoped_ptr<SkBitmap> decoded(new SkBitmap()); 60 scoped_ptr<SkBitmap> decoded(new SkBitmap());
66 *decoded = decoder.Decode(data, file_contents.length()); 61 *decoded = decoder.Decode(data, file_contents.length());
67 if (decoded->empty()) { 62 if (decoded->empty()) {
68 ReportBack(NULL); 63 ReportBack(NULL, resource);
69 return; // Unable to decode. 64 return; // Unable to decode.
70 } 65 }
71 66
72 if (decoded->width() > max_size_.width() || 67 if (decoded->width() > max_size.width() ||
73 decoded->height() > max_size_.height()) { 68 decoded->height() > max_size.height()) {
74 // The bitmap is too big, re-sample. 69 // The bitmap is too big, re-sample.
75 *decoded = skia::ImageOperations::Resize( 70 *decoded = skia::ImageOperations::Resize(
76 *decoded, skia::ImageOperations::RESIZE_LANCZOS3, 71 *decoded, skia::ImageOperations::RESIZE_LANCZOS3,
77 max_size_.width(), max_size_.height()); 72 max_size.width(), max_size.height());
78 } 73 }
79 74
80 ReportBack(decoded.release()); 75 ReportBack(decoded.release(), resource);
76 }
77
78 void ReportBack(SkBitmap* image, const ExtensionResource& resource) {
79 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
80
81 ChromeThread::PostTask(
82 callback_thread_id_, FROM_HERE,
83 NewRunnableMethod(this, &ImageLoader::ReportOnUIThread,
84 image, resource));
85 }
86
87 void ReportOnUIThread(SkBitmap* image, ExtensionResource resource) {
88 DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
89
90 if (tracker_)
91 tracker_->OnImageLoaded(image, resource);
92
93 if (image)
94 delete image;
81 } 95 }
82 96
83 private: 97 private:
98 // The tracker we are loading the image for. If NULL, it means the tracker is
99 // no longer interested in the reply.
100 ImageLoadingTracker* tracker_;
101
84 // The thread that we need to call back on to report that we are done. 102 // The thread that we need to call back on to report that we are done.
85 ChromeThread::ID callback_thread_id_; 103 ChromeThread::ID callback_thread_id_;
86 104
87 // The object that is waiting for us to respond back. 105 DISALLOW_COPY_AND_ASSIGN(ImageLoader);
88 ImageLoadingTracker* tracker_;
89
90 // The image resource to load asynchronously.
91 ExtensionResource resource_;
92
93 // The max size for the loaded image.
94 gfx::Size max_size_;
95
96 // The index of the icon being loaded.
97 size_t index_;
98 }; 106 };
99 107
100 //////////////////////////////////////////////////////////////////////////////// 108 ////////////////////////////////////////////////////////////////////////////////
101 // ImageLoadingTracker 109 // ImageLoadingTracker
102 110
103 void ImageLoadingTracker::PostLoadImageTask(const ExtensionResource& resource, 111 ImageLoadingTracker::ImageLoadingTracker(Observer* observer)
104 const gfx::Size& max_size) { 112 : observer_(observer),
105 ChromeThread::PostTask( 113 responses_(0) {
106 ChromeThread::FILE, FROM_HERE,
107 new LoadImageTask(this, resource, max_size, posted_count_++));
108 } 114 }
109 115
110 void ImageLoadingTracker::OnImageLoaded(SkBitmap* image, size_t index) { 116 ImageLoadingTracker::~ImageLoadingTracker() {
111 if (observer_) 117 // The loader is created lazily and is NULL if the tracker is destroyed before
112 observer_->OnImageLoaded(image, index); 118 // any valid image load tasks have been posted.
119 if (loader_)
120 loader_->StopTracking();
121 }
113 122
114 if (image) 123 void ImageLoadingTracker::LoadImage(const ExtensionResource& resource,
115 delete image; 124 gfx::Size max_size) {
125 // If we don't have a path we don't need to do any further work, just respond
126 // back.
127 if (resource.relative_path().empty()) {
128 OnImageLoaded(NULL, resource);
129 return;
130 }
116 131
117 if (--image_count_ == 0) 132 // Instruct the ImageLoader to load this on the File thread. LoadImage does
118 Release(); // We are no longer needed. 133 // not block.
134 if (!loader_)
135 loader_ = new ImageLoader(this);
136 loader_->LoadImage(resource, max_size);
119 } 137 }
138
139 void ImageLoadingTracker::OnImageLoaded(
140 SkBitmap* image, const ExtensionResource& resource) {
141 observer_->OnImageLoaded(image, resource, responses_++);
142 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/image_loading_tracker.h ('k') | chrome/browser/gtk/browser_actions_toolbar_gtk.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698