Logo Search packages:      
Sourcecode: chromium-browser version File versions  Download package

history_menu_bridge_unittest.mm

// 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.

#import <Cocoa/Cocoa.h>
#include <vector>

#include "base/ref_counted_memory.h"
#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/cancelable_request.h"
#include "chrome/browser/cocoa/cocoa_test_helper.h"
#include "chrome/browser/cocoa/history_menu_bridge.h"
#include "chrome/browser/cocoa/browser_test_helper.h"
#include "gfx/codec/png_codec.h"
#include "testing/gtest/include/gtest/gtest.h"

class HistoryMenuBridgeTest : public CocoaTest {
 public:

  virtual void SetUp() {
    CocoaTest::SetUp();
    browser_test_helper_.profile()->CreateFaviconService();
  }

  // We are a friend of HistoryMenuBridge (and have access to
  // protected methods), but none of the classes generated by TEST_F()
  // are. Wraps common commands.
  void ClearMenuSection(HistoryMenuBridge* bridge,
                        NSMenu* menu,
                        NSInteger tag,
                        unsigned int count) {
    bridge->ClearMenuSection(menu, tag, count);
  }

  void AddItemToBridgeMenu(HistoryMenuBridge* bridge,
                           HistoryMenuBridge::HistoryItem* item,
                           NSMenu* menu,
                           NSInteger tag,
                           NSInteger index) {
    bridge->AddItemToMenu(item, menu, tag, index);
  }

  NSMenuItem* AddItemToMenu(NSMenu* menu,
                            NSString* title,
                            SEL selector,
                            int tag) {
    NSMenuItem* item = [[[NSMenuItem alloc] initWithTitle:title action:NULL
                                            keyEquivalent:@""] autorelease];
    [item setTag:tag];
    if (selector)
      [item setAction:selector];
    [menu addItem:item];
    return item;
  }

  HistoryMenuBridge::HistoryItem* CreateItem(const string16& title) {
    HistoryMenuBridge::HistoryItem* item =
        new HistoryMenuBridge::HistoryItem();
    item->title = title;
    item->url = GURL(title);
    return item;
  }

  void GetFaviconForHistoryItem(HistoryMenuBridge* bridge,
                                HistoryMenuBridge::HistoryItem* item) {
    bridge->GetFaviconForHistoryItem(item);
  }

  void GotFaviconData(HistoryMenuBridge* bridge,
                      FaviconService::Handle handle,
                      bool know_favicon,
                      scoped_refptr<RefCountedBytes> data,
                      bool expired,
                      GURL url) {
    bridge->GotFaviconData(handle, know_favicon, data, expired, url);
  }

  CancelableRequestConsumerTSimple<HistoryMenuBridge::HistoryItem*>&
      favicon_consumer(HistoryMenuBridge* bridge) {
    return bridge->favicon_consumer_;
  }

  BrowserTestHelper browser_test_helper_;
};

// Edge case test for clearing until the end of a menu.
TEST_F(HistoryMenuBridgeTest, ClearHistoryMenuUntilEnd) {
  scoped_ptr<HistoryMenuBridge> bridge(
      new HistoryMenuBridge(browser_test_helper_.profile()));
  EXPECT_TRUE(bridge.get());

  NSMenu* menu = [[[NSMenu alloc] initWithTitle:@"history foo"] autorelease];
  NSInteger tag = IDC_HISTORY_MENU_VISITED;
  AddItemToMenu(menu, @"HEADER", NULL, tag);

  AddItemToMenu(menu, @"alpha", @selector(openHistoryMenuItem:), ++tag);
  AddItemToMenu(menu, @"bravo", @selector(openHistoryMenuItem:), ++tag);
  AddItemToMenu(menu, @"charlie", @selector(openHistoryMenuItem:), ++tag);
  AddItemToMenu(menu, @"delta", @selector(openHistoryMenuItem:), ++tag);

  ClearMenuSection(bridge.get(), menu, IDC_HISTORY_MENU_VISITED, 4);

  EXPECT_EQ(1, [menu numberOfItems]);
  EXPECT_EQ(@"HEADER", [[menu itemWithTag:IDC_HISTORY_MENU_VISITED] title]);
}

// Skip menu items that are not hooked up to |-openHistoryMenuItem:|.
TEST_F(HistoryMenuBridgeTest, ClearHistoryMenuSkipping) {
  scoped_ptr<HistoryMenuBridge> bridge(
      new HistoryMenuBridge(browser_test_helper_.profile()));
  EXPECT_TRUE(bridge.get());

  NSMenu* menu = [[[NSMenu alloc] initWithTitle:@"history foo"] autorelease];
  NSInteger section_tag = IDC_HISTORY_MENU_VISITED;
  AddItemToMenu(menu, @"HEADER", NULL, section_tag);
  NSInteger tag = section_tag;

  AddItemToMenu(menu, @"alpha", @selector(openHistoryMenuItem:), ++tag);
  AddItemToMenu(menu, @"bravo", @selector(openHistoryMenuItem:), ++tag);
  AddItemToMenu(menu, @"unhooked", NULL, ++tag);
  AddItemToMenu(menu, @"charlie", @selector(openHistoryMenuItem:), ++tag);

  ClearMenuSection(bridge.get(), menu, section_tag, 4);

  EXPECT_EQ(2, [menu numberOfItems]);
  EXPECT_EQ(@"HEADER", [[menu itemWithTag:section_tag] title]);
  EXPECT_EQ(@"unhooked", [[menu itemAtIndex:1] title]);
}

// Edge case test for clearing an empty menu.
TEST_F(HistoryMenuBridgeTest, ClearHistoryMenuEmpty) {
  scoped_ptr<HistoryMenuBridge> bridge(
      new HistoryMenuBridge(browser_test_helper_.profile()));
  EXPECT_TRUE(bridge.get());

  NSMenu* menu = [[[NSMenu alloc] initWithTitle:@"history foo"] autorelease];
  AddItemToMenu(menu, @"HEADER", NULL, IDC_HISTORY_MENU_VISITED);

  ClearMenuSection(bridge.get(), menu, IDC_HISTORY_MENU_VISITED, 1);

  EXPECT_EQ(1, [menu numberOfItems]);
  EXPECT_EQ(@"HEADER", [[menu itemWithTag:IDC_HISTORY_MENU_VISITED] title]);
}

// Test that AddItemToMenu() properly adds HistoryItem objects as menus.
TEST_F(HistoryMenuBridgeTest, AddItemToMenu) {
  scoped_ptr<HistoryMenuBridge> bridge(
      new HistoryMenuBridge(browser_test_helper_.profile()));
  EXPECT_TRUE(bridge.get());

  NSMenu* menu = [[[NSMenu alloc] initWithTitle:@"history foo"] autorelease];

  const string16 short_url = ASCIIToUTF16("http://foo/");
  const string16 long_url = ASCIIToUTF16("http://super-duper-long-url--."
      "that.cannot.possibly.fit.even-in-80-columns"
      "or.be.reasonably-displayed-in-a-menu"
      "without.looking-ridiculous.com/"); // 140 chars total

  scoped_ptr<HistoryMenuBridge::HistoryItem> item1(CreateItem(short_url));
  AddItemToBridgeMenu(bridge.get(), item1.get(), menu, 100, 0);

  scoped_ptr<HistoryMenuBridge::HistoryItem> item2(CreateItem(long_url));
  AddItemToBridgeMenu(bridge.get(), item2.get(), menu, 101, 1);

  EXPECT_EQ(2, [menu numberOfItems]);

  EXPECT_EQ(@selector(openHistoryMenuItem:), [[menu itemAtIndex:0] action]);
  EXPECT_EQ(@selector(openHistoryMenuItem:), [[menu itemAtIndex:1] action]);

  EXPECT_EQ(100, [[menu itemAtIndex:0] tag]);
  EXPECT_EQ(101, [[menu itemAtIndex:1] tag]);

  // Make sure a short title looks fine
  NSString* s = [[menu itemAtIndex:0] title];
  EXPECT_EQ(base::SysNSStringToUTF16(s), short_url);

  // Make sure a super-long title gets trimmed
  s = [[menu itemAtIndex:0] title];
  EXPECT_TRUE([s length] < long_url.length());

  // Confirm tooltips and confirm they are not trimmed (like the item
  // name might be).  Add tolerance for URL fixer-upping;
  // e.g. http://foo becomes http://foo/)
  EXPECT_GE([[[menu itemAtIndex:0] toolTip] length], (2*short_url.length()-5));
  EXPECT_GE([[[menu itemAtIndex:1] toolTip] length], (2*long_url.length()-5));
}

// Tests that we properly request an icon from the FaviconService.
TEST_F(HistoryMenuBridgeTest, GetFaviconForHistoryItem) {
  TestingProfile* profile = browser_test_helper_.profile();
  HistoryMenuBridge bridge(profile);

  // Create a fake item.
  HistoryMenuBridge::HistoryItem item;
  item.title = ASCIIToUTF16("Title");
  item.url = GURL("http://google.com");

  // Request the icon.
  GetFaviconForHistoryItem(&bridge, &item);

  // Make sure that there is ClientData for the request.
  std::vector<HistoryMenuBridge::HistoryItem*> data;
  favicon_consumer(&bridge).GetAllClientData(&data);
  ASSERT_EQ(data.size(), 1U);
  EXPECT_EQ(&item, data[0]);

  // Make sure the item was modified properly.
  EXPECT_TRUE(item.icon_requested);
  EXPECT_GT(item.icon_handle, 0);
}

TEST_F(HistoryMenuBridgeTest, GotFaviconData) {
  TestingProfile* profile = browser_test_helper_.profile();
  HistoryMenuBridge bridge(profile);

  // Create a dummy bitmap.
  SkBitmap bitmap;
  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 25, 25);
  bitmap.allocPixels();
  bitmap.eraseRGB(255, 0, 0);

  // Convert it to raw PNG bytes. We totally ignore color order here because
  // we just want to test the roundtrip through the Bridge, not that we can
  // make icons look pretty.
  std::vector<unsigned char> raw;
  gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &raw);
  scoped_refptr<RefCountedBytes> bytes(new RefCountedBytes(raw));

  // Set up the HistoryItem.
  HistoryMenuBridge::HistoryItem item;
  scoped_nsobject<NSMenuItem> menu_item([[NSMenuItem alloc] init]);
  item.menu_item = menu_item.get();
  GetFaviconForHistoryItem(&bridge, &item);

  // Pretend to be called back.
  GotFaviconData(&bridge, item.icon_handle, true, bytes, false, GURL());

  // Make sure the callback works.
  EXPECT_EQ(false, item.icon_requested);
  EXPECT_TRUE(item.icon.get());
  EXPECT_TRUE([item.menu_item image]);
}

Generated by  Doxygen 1.6.0   Back to index