summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browser.cc4
-rw-r--r--chrome/browser/cocoa/keyword_editor_cocoa_controller.h14
-rw-r--r--chrome/browser/cocoa/keyword_editor_cocoa_controller.mm62
-rw-r--r--chrome/browser/cocoa/table_row_nsimage_cache.h50
-rw-r--r--chrome/browser/cocoa/table_row_nsimage_cache.mm78
-rw-r--r--chrome/browser/cocoa/table_row_nsimage_cache_unittest.mm61
-rw-r--r--chrome/browser/cocoa/task_manager_mac.h14
-rw-r--r--chrome/browser/cocoa/task_manager_mac.mm55
-rw-r--r--chrome/browser/task_manager_resource_providers.cc10
-rwxr-xr-xchrome/chrome_browser.gypi2
-rwxr-xr-xchrome/chrome_tests.gypi1
-rw-r--r--skia/ext/skia_utils_mac.h3
-rw-r--r--skia/ext/skia_utils_mac.mm5
13 files changed, 298 insertions, 61 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 91f0101..6a0ba3e 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -2557,9 +2557,9 @@ void Browser::InitCommandState() {
command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_CONSOLE, true);
// TODO(viettrungluu): Temporarily disabled on Mac. Must disable here (not in
// BWC) so that it also affects the page menu. http://crbug.com/13156
-#if !defined(OS_MACOSX)
+//#if !defined(OS_MACOSX)
command_updater_.UpdateCommandEnabled(IDC_TASK_MANAGER, true);
-#endif
+//#endif
command_updater_.UpdateCommandEnabled(IDC_SELECT_PROFILE, true);
command_updater_.UpdateCommandEnabled(IDC_SHOW_HISTORY, true);
command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER, true);
diff --git a/chrome/browser/cocoa/keyword_editor_cocoa_controller.h b/chrome/browser/cocoa/keyword_editor_cocoa_controller.h
index 5e84426..9023a15 100644
--- a/chrome/browser/cocoa/keyword_editor_cocoa_controller.h
+++ b/chrome/browser/cocoa/keyword_editor_cocoa_controller.h
@@ -7,6 +7,7 @@
#include "app/table_model_observer.h"
#import "base/cocoa_protocols_mac.h"
#include "base/scoped_ptr.h"
+#include "chrome/browser/cocoa/table_row_nsimage_cache.h"
#include "chrome/browser/search_engines/edit_search_engine_controller.h"
#include "chrome/browser/search_engines/keyword_editor_controller.h"
#include "chrome/browser/search_engines/template_url_model.h"
@@ -18,7 +19,8 @@ class Profile;
// Very thin bridge that simply pushes notifications from C++ to ObjC.
class KeywordEditorModelObserver : public TemplateURLModelObserver,
public EditSearchEngineControllerDelegate,
- public TableModelObserver {
+ public TableModelObserver,
+ public TableRowNSImageCache::Table {
public:
explicit KeywordEditorModelObserver(KeywordEditorCocoaController* controller);
virtual ~KeywordEditorModelObserver();
@@ -42,15 +44,17 @@ class KeywordEditorModelObserver : public TemplateURLModelObserver,
virtual void OnItemsAdded(int start, int length);
virtual void OnItemsRemoved(int start, int length);
- // Lazily converts the image at the given row and caches it in |iconImages_|.
+ // TableRowNSImageCache::Table
+ virtual int RowCount() const;
+ virtual SkBitmap GetIcon(int row) const;
+
+ // Lazily converts the image at the given row and caches it in |icon_cache_|.
NSImage* GetImageForRow(int row);
private:
KeywordEditorCocoaController* controller_;
- // Stores strong NSImage refs for icons. If an entry is NULL, it will be
- // created in GetImageForRow().
- scoped_nsobject<NSPointerArray> iconImages_;
+ TableRowNSImageCache icon_cache_;
DISALLOW_COPY_AND_ASSIGN(KeywordEditorModelObserver);
};
diff --git a/chrome/browser/cocoa/keyword_editor_cocoa_controller.mm b/chrome/browser/cocoa/keyword_editor_cocoa_controller.mm
index d2e1d7a..7440a17 100644
--- a/chrome/browser/cocoa/keyword_editor_cocoa_controller.mm
+++ b/chrome/browser/cocoa/keyword_editor_cocoa_controller.mm
@@ -30,11 +30,7 @@
KeywordEditorModelObserver::KeywordEditorModelObserver(
KeywordEditorCocoaController* controller)
: controller_(controller),
- iconImages_([[NSPointerArray alloc] initWithOptions:
- NSPointerFunctionsStrongMemory |
- NSPointerFunctionsObjectPersonality]) {
- int count = [controller_ controller]->table_model()->RowCount();
- [iconImages_ setCount:count];
+ icon_cache_(this) {
}
KeywordEditorModelObserver::~KeywordEditorModelObserver() {
@@ -59,65 +55,35 @@ void KeywordEditorModelObserver::OnEditedKeyword(
}
void KeywordEditorModelObserver::OnModelChanged() {
- int count = [controller_ controller]->table_model()->RowCount();
- [iconImages_ setCount:0];
- [iconImages_ setCount:count];
+ icon_cache_.OnModelChanged();
[controller_ modelChanged];
}
void KeywordEditorModelObserver::OnItemsChanged(int start, int length) {
- DCHECK_LE(start + length, static_cast<int>([iconImages_ count]));
- for (int i = start; i < (start + length); ++i) {
- [iconImages_ replacePointerAtIndex:i withPointer:NULL];
- }
- DCHECK_EQ([controller_ controller]->table_model()->RowCount(),
- static_cast<int>([iconImages_ count]));
+ icon_cache_.OnItemsChanged(start, length);
[controller_ modelChanged];
}
void KeywordEditorModelObserver::OnItemsAdded(int start, int length) {
- DCHECK_LE(start, static_cast<int>([iconImages_ count]));
-
- // -[NSPointerArray insertPointer:atIndex:] throws if index == count.
- // Instead expand the array with NULLs.
- if (start == static_cast<int>([iconImages_ count])) {
- [iconImages_ setCount:start + length];
- } else {
- for (int i = 0; i < length; ++i) {
- [iconImages_ insertPointer:NULL atIndex:start]; // Values slide up.
- }
- }
- DCHECK_EQ([controller_ controller]->table_model()->RowCount(),
- static_cast<int>([iconImages_ count]));
+ icon_cache_.OnItemsAdded(start, length);
[controller_ modelChanged];
}
void KeywordEditorModelObserver::OnItemsRemoved(int start, int length) {
- DCHECK_LE(start + length, static_cast<int>([iconImages_ count]));
- for (int i = 0; i < length; ++i) {
- [iconImages_ removePointerAtIndex:start]; // Values slide down.
- }
- DCHECK_EQ([controller_ controller]->table_model()->RowCount(),
- static_cast<int>([iconImages_ count]));
+ icon_cache_.OnItemsRemoved(start, length);
[controller_ modelChanged];
}
+int KeywordEditorModelObserver::RowCount() const {
+ return [controller_ controller]->table_model()->RowCount();
+}
+
+SkBitmap KeywordEditorModelObserver::GetIcon(int row) const {
+ return [controller_ controller]->table_model()->GetIcon(row);
+}
+
NSImage* KeywordEditorModelObserver::GetImageForRow(int row) {
- DCHECK_EQ([controller_ controller]->table_model()->RowCount(),
- static_cast<int>([iconImages_ count]));
- DCHECK_GE(row, 0);
- DCHECK_LT(row, static_cast<int>([iconImages_ count]));
- NSImage* image = static_cast<NSImage*>([iconImages_ pointerAtIndex:row]);
- if (!image) {
- const SkBitmap bitmapIcon =
- [controller_ controller]->table_model()->GetIcon(row);
- if (!bitmapIcon.isNull()) {
- image = gfx::SkBitmapToNSImage(bitmapIcon);
- DCHECK(image);
- [iconImages_ replacePointerAtIndex:row withPointer:image];
- }
- }
- return image;
+ return icon_cache_.GetImageForRow(row);
}
// KeywordEditorCocoaController -----------------------------------------------
diff --git a/chrome/browser/cocoa/table_row_nsimage_cache.h b/chrome/browser/cocoa/table_row_nsimage_cache.h
new file mode 100644
index 0000000..04ca13e
--- /dev/null
+++ b/chrome/browser/cocoa/table_row_nsimage_cache.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2010 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_COCOA_TABLE_ROW_NSIMAGE_CACHE_H_
+#define CHROME_BROWSER_COCOA_TABLE_ROW_NSIMAGE_CACHE_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/scoped_nsobject.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+// There are several dialogs that display tabular data with one SkBitmap
+// per row. This class converts these SkBitmaps to NSImages on demand, and
+// caches the results.
+class TableRowNSImageCache {
+ public:
+ // Interface this cache expects for its table model.
+ class Table {
+ public:
+ // Returns the number of rows in the table.
+ virtual int RowCount() const = 0;
+
+ // Returns the icon of the |row|th row.
+ virtual SkBitmap GetIcon(int row) const = 0;
+ };
+
+ // |model| must outlive the cache.
+ explicit TableRowNSImageCache(Table* model);
+
+ // Lazily converts the image at the given row and caches it in |icon_images_|.
+ NSImage* GetImageForRow(int row);
+
+ // Call these functions every time the table changes, to update the cache.
+ void OnModelChanged();
+ void OnItemsChanged(int start, int length);
+ void OnItemsAdded(int start, int length);
+ void OnItemsRemoved(int start, int length);
+
+ private:
+ // The table model we query for row count and icons.
+ Table* model_; // weak
+
+ // Stores strong NSImage refs for icons. If an entry is NULL, it will be
+ // created in GetImageForRow().
+ scoped_nsobject<NSPointerArray> icon_images_;
+};
+
+#endif // CHROME_BROWSER_COCOA_TABLE_ROW_NSIMAGE_CACHE_H_
+
diff --git a/chrome/browser/cocoa/table_row_nsimage_cache.mm b/chrome/browser/cocoa/table_row_nsimage_cache.mm
new file mode 100644
index 0000000..e8ddab3
--- /dev/null
+++ b/chrome/browser/cocoa/table_row_nsimage_cache.mm
@@ -0,0 +1,78 @@
+// Copyright (c) 2010 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/cocoa/table_row_nsimage_cache.h"
+
+#include "base/logging.h"
+#include "skia/ext/skia_utils_mac.h"
+
+TableRowNSImageCache::TableRowNSImageCache(Table* model)
+ : model_(model),
+ icon_images_([[NSPointerArray alloc] initWithOptions:
+ NSPointerFunctionsStrongMemory |
+ NSPointerFunctionsObjectPersonality]) {
+ int count = model_->RowCount();
+ [icon_images_ setCount:count];
+}
+
+void TableRowNSImageCache::OnModelChanged() {
+ int count = model_->RowCount();
+ [icon_images_ setCount:0];
+ [icon_images_ setCount:count];
+}
+
+void TableRowNSImageCache::OnItemsChanged(int start, int length) {
+ DCHECK_LE(start + length, static_cast<int>([icon_images_ count]));
+ for (int i = start; i < (start + length); ++i) {
+ [icon_images_ replacePointerAtIndex:i withPointer:NULL];
+ }
+ DCHECK_EQ(model_->RowCount(),
+ static_cast<int>([icon_images_ count]));
+}
+
+void TableRowNSImageCache::OnItemsAdded(int start, int length) {
+ DCHECK_LE(start, static_cast<int>([icon_images_ count]));
+
+ // -[NSPointerArray insertPointer:atIndex:] throws if index == count.
+ // Instead expand the array with NULLs.
+ if (start == static_cast<int>([icon_images_ count])) {
+ [icon_images_ setCount:start + length];
+ } else {
+ for (int i = 0; i < length; ++i) {
+ [icon_images_ insertPointer:NULL atIndex:start]; // Values slide up.
+ }
+ }
+ DCHECK_EQ(model_->RowCount(),
+ static_cast<int>([icon_images_ count]));
+}
+
+void TableRowNSImageCache::OnItemsRemoved(int start, int length) {
+ DCHECK_LE(start + length, static_cast<int>([icon_images_ count]));
+ for (int i = 0; i < length; ++i) {
+ [icon_images_ removePointerAtIndex:start]; // Values slide down.
+ }
+ DCHECK_EQ(model_->RowCount(),
+ static_cast<int>([icon_images_ count]));
+}
+
+NSImage* TableRowNSImageCache::GetImageForRow(int row) {
+ DCHECK_EQ(model_->RowCount(),
+ static_cast<int>([icon_images_ count]));
+ DCHECK_GE(row, 0);
+ DCHECK_LT(row, static_cast<int>([icon_images_ count]));
+ NSImage* image = static_cast<NSImage*>([icon_images_ pointerAtIndex:row]);
+ if (!image) {
+ const SkBitmap bitmap_icon =
+ model_->GetIcon(row);
+ // This means GetIcon() will get called until it returns a non-empty bitmap.
+ // Empty bitmaps are intentionally not cached.
+ if (!bitmap_icon.isNull()) {
+ image = gfx::SkBitmapToNSImage(bitmap_icon);
+ DCHECK(image);
+ [icon_images_ replacePointerAtIndex:row withPointer:image];
+ }
+ }
+ return image;
+}
+
diff --git a/chrome/browser/cocoa/table_row_nsimage_cache_unittest.mm b/chrome/browser/cocoa/table_row_nsimage_cache_unittest.mm
new file mode 100644
index 0000000..975c065
--- /dev/null
+++ b/chrome/browser/cocoa/table_row_nsimage_cache_unittest.mm
@@ -0,0 +1,61 @@
+// Copyright (c) 2010 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/cocoa/table_row_nsimage_cache.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using ::testing::Return;
+
+class MockTable : public TableRowNSImageCache::Table {
+ public:
+ MOCK_CONST_METHOD0(RowCount, int());
+ MOCK_CONST_METHOD1(GetIcon, SkBitmap(int));
+};
+
+TEST(TableRowNSImageCacheTest, Basics) {
+ SkBitmap first_bitmap;
+ first_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 40, 30);
+ first_bitmap.eraseRGB(255, 0, 0);
+ ASSERT_TRUE(first_bitmap.allocPixels());
+
+ SkBitmap second_bitmap;
+ second_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 20, 10);
+ second_bitmap.eraseRGB(0, 255, 0);
+ ASSERT_TRUE(second_bitmap.allocPixels());
+
+ MockTable table;
+
+ EXPECT_CALL(table, RowCount()).WillRepeatedly(Return(2));
+ TableRowNSImageCache cache(&table);
+
+ // Check both images are only generated once
+ EXPECT_CALL(table, GetIcon(0)).WillOnce(Return(first_bitmap));
+ NSImage* first_image = cache.GetImageForRow(0);
+ EXPECT_EQ(40, [first_image size].width);
+ EXPECT_EQ(30, [first_image size].height);
+ EXPECT_EQ(first_image, cache.GetImageForRow(0));
+
+ EXPECT_CALL(table, GetIcon(1)).WillOnce(Return(second_bitmap));
+ NSImage* second_image = cache.GetImageForRow(1);
+ EXPECT_EQ(20, [second_image size].width);
+ EXPECT_EQ(10, [second_image size].height);
+ EXPECT_EQ(second_image, cache.GetImageForRow(1));
+
+ // Check that invalidating the second icon only invalidates the second icon
+ cache.OnItemsChanged(/* start =*/1, /* length =*/1);
+ EXPECT_EQ(first_image, cache.GetImageForRow(0));
+
+ EXPECT_CALL(table, GetIcon(1)).WillOnce(Return(first_bitmap));
+ NSImage* new_second_image = cache.GetImageForRow(1);
+ EXPECT_EQ(40, [new_second_image size].width);
+ EXPECT_EQ(30, [new_second_image size].height);
+ EXPECT_EQ(new_second_image, cache.GetImageForRow(1));
+ EXPECT_NE(new_second_image, second_image);
+}
+
+} // namespace
diff --git a/chrome/browser/cocoa/task_manager_mac.h b/chrome/browser/cocoa/task_manager_mac.h
index cbcb5d2..5d78cff 100644
--- a/chrome/browser/cocoa/task_manager_mac.h
+++ b/chrome/browser/cocoa/task_manager_mac.h
@@ -7,6 +7,7 @@
#import <Cocoa/Cocoa.h>
#include "base/scoped_nsobject.h"
+#include "chrome/browser/cocoa/table_row_nsimage_cache.h"
#include "chrome/browser/task_manager.h"
class TaskManagerMac;
@@ -39,7 +40,8 @@ class TaskManagerMac;
@end
// This class listens to task changed events sent by chrome.
-class TaskManagerMac : public TaskManagerModelObserver {
+class TaskManagerMac : public TaskManagerModelObserver,
+ public TableRowNSImageCache::Table {
public:
TaskManagerMac();
virtual ~TaskManagerMac();
@@ -54,6 +56,10 @@ class TaskManagerMac : public TaskManagerModelObserver {
// controller destroyed itself. Informs the model to stop updating.
void WindowWasClosed();
+ // TableRowNSImageCache::Table
+ virtual int RowCount() const { return model_->ResourceCount(); }
+ virtual SkBitmap GetIcon(int r) const { return model_->GetResourceIcon(r); }
+
// Creates the task manager if it doesn't exist; otherwise, it activates the
// existing task manager window.
static void Show();
@@ -61,6 +67,9 @@ class TaskManagerMac : public TaskManagerModelObserver {
// Returns the TaskManager observed by |this|.
TaskManager* task_manager() { return task_manager_; }
+ // Lazily converts the image at the given row and caches it in |icon_cache_|.
+ NSImage* GetImageForRow(int row);
+
private:
// The task manager.
TaskManager* const task_manager_; // weak
@@ -72,6 +81,9 @@ class TaskManagerMac : public TaskManagerModelObserver {
// is closed.
TaskManagerWindowController* window_controller_; // weak
+ // Caches favicons for all rows. Needs to be initalized after |model_|.
+ TableRowNSImageCache icon_cache_;
+
// An open task manager window. There can only be one open at a time. This
// is reset to NULL when the window is closed.
static TaskManagerMac* instance_;
diff --git a/chrome/browser/cocoa/task_manager_mac.mm b/chrome/browser/cocoa/task_manager_mac.mm
index 71b24f5..91e8f92 100644
--- a/chrome/browser/cocoa/task_manager_mac.mm
+++ b/chrome/browser/cocoa/task_manager_mac.mm
@@ -13,13 +13,13 @@
#include "grit/generated_resources.h"
// TODO(thakis): Autoremember window size/pos (and selected columns?)
+// TODO(thakis): Better resizing behavior (and think about storing column sizes)
// TODO(thakis): Column sort comparator
// TODO(thakis): Clicking column header doesn't sort
-// TODO(thakis): Favicons in rows
// TODO(thakis): Default sort column
@interface TaskManagerWindowController (Private)
-- (void)addColumnWithId:(int)columnId visible:(BOOL)isVisible;
+- (NSTableColumn*)addColumnWithId:(int)columnId visible:(BOOL)isVisible;
- (void)setUpTableColumns;
- (void)setUpTableHeaderContextMenu;
- (void)toggleColumn:(id)sender;
@@ -79,7 +79,7 @@
// Adds a column which has the given string id as title. |isVisible| specifies
// if the column is initially visible.
-- (void)addColumnWithId:(int)columnId visible:(BOOL)isVisible {
+- (NSTableColumn*)addColumnWithId:(int)columnId visible:(BOOL)isVisible {
scoped_nsobject<NSTableColumn> column([[NSTableColumn alloc]
initWithIdentifier:[NSNumber numberWithInt:columnId]]);
@@ -94,13 +94,23 @@
[column.get() setHidden:!isVisible];
[column.get() setEditable:NO];
[tableView_ addTableColumn:column.get()];
+ return column.get(); // Now retained by |tableView_|.
}
// Adds all the task manager's columns to the table.
- (void)setUpTableColumns {
for (NSTableColumn* column in [tableView_ tableColumns])
[tableView_ removeTableColumn:column];
- [self addColumnWithId:IDS_TASK_MANAGER_PAGE_COLUMN visible:YES];
+ NSTableColumn* nameColumn = [self addColumnWithId:IDS_TASK_MANAGER_PAGE_COLUMN
+ visible:YES];
+ // |nameColumn| displays an icon for every row -- this is done by an
+ // NSButtonCell.
+ scoped_nsobject<NSButtonCell> nameCell(
+ [[NSButtonCell alloc] initTextCell:@""]);
+ [nameCell.get() setImagePosition:NSImageLeft];
+ [nameCell.get() setButtonType:NSSwitchButton];
+ [nameColumn setDataCell:nameCell.get()];
+
[self addColumnWithId:IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN visible:YES];
[self addColumnWithId:IDS_TASK_MANAGER_SHARED_MEM_COLUMN visible:NO];
[self addColumnWithId:IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN visible:NO];
@@ -257,10 +267,36 @@
- (id)tableView:(NSTableView*)tableView
objectValueForTableColumn:(NSTableColumn*)tableColumn
row:(NSInteger)rowIndex {
+ // NSButtonCells expect an on/off state as objectValue. Their title is set
+ // in |tableView:dataCellForTableColumn:row:| below.
+ if ([[tableColumn identifier] intValue] == IDS_TASK_MANAGER_PAGE_COLUMN) {
+ return [NSNumber numberWithInt:NSOffState];
+ }
+
return [self modelTextForRow:rowIndex
column:[[tableColumn identifier] intValue]];
}
+- (NSCell*)tableView:(NSTableView*)tableView
+ dataCellForTableColumn:(NSTableColumn*)tableColumn
+ row:(NSInteger)rowIndex {
+ NSCell* cell = [tableColumn dataCellForRow:rowIndex];
+
+ // Set the favicon and title for the search engine in the name column.
+ if ([[tableColumn identifier] intValue] == IDS_TASK_MANAGER_PAGE_COLUMN) {
+ DCHECK([cell isKindOfClass:[NSButtonCell class]]);
+ NSButtonCell* buttonCell = static_cast<NSButtonCell*>(cell);
+ NSString* title = [self modelTextForRow:rowIndex
+ column:[[tableColumn identifier] intValue]];
+ [buttonCell setTitle:title];
+ [buttonCell setImage:taskManagerObserver_->GetImageForRow(rowIndex)];
+ [buttonCell setRefusesFirstResponder:YES]; // Don't push in like a button.
+ [buttonCell setHighlightsBy:NSNoCellMask];
+ }
+
+ return cell;
+}
+
@end
////////////////////////////////////////////////////////////////////////////////
@@ -268,7 +304,8 @@
TaskManagerMac::TaskManagerMac()
: task_manager_(TaskManager::GetInstance()),
- model_(TaskManager::GetInstance()->model()) {
+ model_(TaskManager::GetInstance()->model()),
+ icon_cache_(this) {
window_controller_ =
[[TaskManagerWindowController alloc] initWithTaskManagerObserver:this];
model_->AddObserver(this);
@@ -286,21 +323,29 @@ TaskManagerMac::~TaskManagerMac() {
// TaskManagerMac, TaskManagerModelObserver implementation:
void TaskManagerMac::OnModelChanged() {
+ icon_cache_.OnModelChanged();
[window_controller_ reloadData];
}
void TaskManagerMac::OnItemsChanged(int start, int length) {
+ icon_cache_.OnItemsChanged(start, length);
[window_controller_ reloadData];
}
void TaskManagerMac::OnItemsAdded(int start, int length) {
+ icon_cache_.OnItemsAdded(start, length);
[window_controller_ reloadData];
}
void TaskManagerMac::OnItemsRemoved(int start, int length) {
+ icon_cache_.OnItemsRemoved(start, length);
[window_controller_ reloadData];
}
+NSImage* TaskManagerMac::GetImageForRow(int row) {
+ return icon_cache_.GetImageForRow(row);
+}
+
////////////////////////////////////////////////////////////////////////////////
// TaskManagerMac, public:
diff --git a/chrome/browser/task_manager_resource_providers.cc b/chrome/browser/task_manager_resource_providers.cc
index 715dd08..57f6b7a 100644
--- a/chrome/browser/task_manager_resource_providers.cc
+++ b/chrome/browser/task_manager_resource_providers.cc
@@ -40,6 +40,10 @@
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#if defined(OS_MACOSX)
+#include "skia/ext/skia_utils_mac.h"
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// TaskManagerTabContentsResource class
////////////////////////////////////////////////////////////////////////////////
@@ -711,6 +715,12 @@ TaskManagerBrowserProcessResource::TaskManagerBrowserProcessResource()
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
default_icon_ = rb.GetBitmapNamed(IDR_PRODUCT_LOGO_16);
}
+#elif defined(OS_MACOSX)
+ if (!default_icon_) {
+ // IDR_PRODUCT_LOGO_16 doesn't quite look like chrome/mac's icns icon. Load
+ // the real app icon (requires a nsimage->skbitmap->nsimage conversion :-().
+ default_icon_ = new SkBitmap(gfx::AppplicationIconAtSize(16));
+ }
#else
// TODO(port): Port icon code.
NOTIMPLEMENTED();
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 2625ca9..ce9f93f 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -561,6 +561,8 @@
'browser/cocoa/tab_view.mm',
'browser/cocoa/tab_window_controller.h',
'browser/cocoa/tab_window_controller.mm',
+ 'browser/cocoa/table_row_nsimage_cache.h',
+ 'browser/cocoa/table_row_nsimage_cache.mm',
'browser/cocoa/task_manager_mac.h',
'browser/cocoa/task_manager_mac.mm',
'browser/cocoa/theme_install_bubble_view.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index d00af61..fc55fe3 100755
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -653,6 +653,7 @@
'browser/cocoa/tab_strip_controller_unittest.mm',
'browser/cocoa/tab_strip_view_unittest.mm',
'browser/cocoa/tab_view_unittest.mm',
+ 'browser/cocoa/table_row_nsimage_cache_unittest.mm',
'browser/cocoa/task_manager_mac_unittest.mm',
'browser/cocoa/test_event_utils.h',
'browser/cocoa/test_event_utils.mm',
diff --git a/skia/ext/skia_utils_mac.h b/skia/ext/skia_utils_mac.h
index 06cb151..5ecd451 100644
--- a/skia/ext/skia_utils_mac.h
+++ b/skia/ext/skia_utils_mac.h
@@ -62,6 +62,9 @@ SkBitmap NSImageToSkBitmap(NSImage* image, NSSize size, bool is_opaque);
NSImage* SkBitmapToNSImage(const SkBitmap& icon);
#endif
+// Returns |[NSImage imageNamed:@"NSApplicationIcon"]| as SkBitmap.
+SkBitmap AppplicationIconAtSize(int size);
+
} // namespace gfx
#endif // SKIA_EXT_SKIA_UTILS_MAC_H_
diff --git a/skia/ext/skia_utils_mac.mm b/skia/ext/skia_utils_mac.mm
index 0a08c75..3568d88 100644
--- a/skia/ext/skia_utils_mac.mm
+++ b/skia/ext/skia_utils_mac.mm
@@ -181,4 +181,9 @@ NSImage* SkBitmapToNSImage(const SkBitmap& skiaBitmap) {
return image;
}
+SkBitmap AppplicationIconAtSize(int size) {
+ NSImage* image = [NSImage imageNamed:@"NSApplicationIcon"];
+ return NSImageToSkBitmap(image, NSMakeSize(size, size), /* is_opaque=*/true);
+}
+
} // namespace gfx