diff --git a/chrome/browser/extensions/extension_context_menu_api.cc b/chrome/browser/extensions/extension_context_menu_api.cc index 51e9dfb60b46cba07fb0d376f355abf3a926b2bc..a004b9784aa4e50560ea12993bc21c86221d54ed 100644 --- a/chrome/browser/extensions/extension_context_menu_api.cc +++ b/chrome/browser/extensions/extension_context_menu_api.cc @@ -174,22 +174,21 @@ bool ExtensionContextMenuFunction::SetURLPatterns( return true; } - bool ExtensionContextMenuFunction::GetParent( const DictionaryValue& properties, const ExtensionMenuManager& manager, ExtensionMenuItem** result) { if (!properties.HasKey(kParentIdKey)) return true; - ExtensionMenuItem::Id parent_id(extension_id(), 0); + ExtensionMenuItem::Id parent_id(profile(), extension_id(), 0); if (properties.HasKey(kParentIdKey) && - !properties.GetInteger(kParentIdKey, &parent_id.second)) + !properties.GetInteger(kParentIdKey, &parent_id.uid)) return false; ExtensionMenuItem* parent = manager.GetItemById(parent_id); if (!parent) { error_ = "Cannot find menu item with id " + - base::IntToString(parent_id.second); + base::IntToString(parent_id.uid); return false; } if (parent->type() != ExtensionMenuItem::NORMAL) { @@ -205,9 +204,9 @@ bool CreateContextMenuFunction::RunImpl() { EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &properties)); EXTENSION_FUNCTION_VALIDATE(properties != NULL); - ExtensionMenuItem::Id id(extension_id(), 0); + ExtensionMenuItem::Id id(profile(), extension_id(), 0); EXTENSION_FUNCTION_VALIDATE(properties->GetInteger(kGeneratedIdKey, - &id.second)); + &id.uid)); std::string title; if (properties->HasKey(kTitleKey) && !properties->GetString(kTitleKey, &title)) @@ -241,13 +240,13 @@ bool CreateContextMenuFunction::RunImpl() { bool success = true; if (properties->HasKey(kParentIdKey)) { - ExtensionMenuItem::Id parent_id(extension_id(), 0); + ExtensionMenuItem::Id parent_id(profile(), extension_id(), 0); EXTENSION_FUNCTION_VALIDATE(properties->GetInteger(kParentIdKey, - &parent_id.second)); + &parent_id.uid)); ExtensionMenuItem* parent = menu_manager->GetItemById(parent_id); if (!parent) { error_ = ExtensionErrorUtils::FormatErrorMessage( - kCannotFindItemError, base::IntToString(parent_id.second)); + kCannotFindItemError, base::IntToString(parent_id.uid)); return false; } if (parent->type() != ExtensionMenuItem::NORMAL) { @@ -266,15 +265,15 @@ bool CreateContextMenuFunction::RunImpl() { } bool UpdateContextMenuFunction::RunImpl() { - ExtensionMenuItem::Id item_id(extension_id(), 0); - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &item_id.second)); + ExtensionMenuItem::Id item_id(profile(), extension_id(), 0); + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &item_id.uid)); ExtensionsService* service = profile()->GetExtensionsService(); ExtensionMenuManager* manager = service->menu_manager(); ExtensionMenuItem* item = manager->GetItemById(item_id); if (!item || item->extension_id() != extension_id()) { error_ = ExtensionErrorUtils::FormatErrorMessage( - kCannotFindItemError, base::IntToString(item_id.second)); + kCannotFindItemError, base::IntToString(item_id.uid)); return false; } @@ -333,8 +332,8 @@ bool UpdateContextMenuFunction::RunImpl() { } bool RemoveContextMenuFunction::RunImpl() { - ExtensionMenuItem::Id id(extension_id(), 0); - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &id.second)); + ExtensionMenuItem::Id id(profile(), extension_id(), 0); + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &id.uid)); ExtensionsService* service = profile()->GetExtensionsService(); ExtensionMenuManager* manager = service->menu_manager(); @@ -342,7 +341,7 @@ bool RemoveContextMenuFunction::RunImpl() { // Ensure one extension can't remove another's menu items. if (!item || item->extension_id() != extension_id()) { error_ = ExtensionErrorUtils::FormatErrorMessage( - kCannotFindItemError, base::IntToString(id.second)); + kCannotFindItemError, base::IntToString(id.uid)); return false; } diff --git a/chrome/browser/extensions/extension_context_menu_browsertest.cc b/chrome/browser/extensions/extension_context_menu_browsertest.cc index b0041ad27522b580710bd2812b4b5a30c063945b..73f4acf5d433af1f442e0c47ee5f7fe00a3eff96 100644 --- a/chrome/browser/extensions/extension_context_menu_browsertest.cc +++ b/chrome/browser/extensions/extension_context_menu_browsertest.cc @@ -5,6 +5,7 @@ #include "app/menus/menu_model.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_test_message_listener.h" #include "chrome/browser/extensions/extensions_service.h" @@ -122,9 +123,16 @@ class ExtensionContextMenuBrowserTest : public ExtensionBrowserTest { return LoadExtension(extension_dir); } - TestRenderViewContextMenu* CreateMenu(const GURL& page_url, + bool LoadContextMenuExtensionIncognito(std::string subdirectory) { + FilePath extension_dir = + test_data_dir_.AppendASCII("context_menus").AppendASCII(subdirectory); + return LoadExtensionIncognito(extension_dir); + } + + TestRenderViewContextMenu* CreateMenu(Browser* browser, + const GURL& page_url, const GURL& link_url) { - TabContents* tab_contents = browser()->GetSelectedTabContents(); + TabContents* tab_contents = browser->GetSelectedTabContents(); WebContextMenuData data; ContextMenuParams params(data); params.page_url = page_url; @@ -173,7 +181,8 @@ class ExtensionContextMenuBrowserTest : public ExtensionBrowserTest { bool MenuHasItemWithLabel(const GURL& page_url, const GURL& link_url, const std::string& label) { - scoped_ptr<TestRenderViewContextMenu> menu(CreateMenu(page_url, link_url)); + scoped_ptr<TestRenderViewContextMenu> menu( + CreateMenu(browser(), page_url, link_url)); return menu->HasExtensionItemWithLabel(label); } }; @@ -190,7 +199,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Simple) { GURL page_url("http://www.google.com"); // Create and build our test context menu. - scoped_ptr<TestRenderViewContextMenu> menu(CreateMenu(page_url, GURL())); + scoped_ptr<TestRenderViewContextMenu> menu( + CreateMenu(browser(), page_url, GURL())); // Look for the extension item in the menu, and execute it. int command_id = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST; @@ -249,7 +259,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, LongTitle) { // Create a context menu, then find the item's label. It should be properly // truncated. GURL url("http://foo.com/"); - scoped_ptr<TestRenderViewContextMenu> menu(CreateMenu(url, GURL())); + scoped_ptr<TestRenderViewContextMenu> menu( + CreateMenu(browser(), url, GURL())); string16 label; ASSERT_TRUE(menu->GetItemLabel(item->id(), &label)); @@ -313,7 +324,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Separators) { listener1.WaitUntilSatisfied(); GURL url("http://www.google.com/"); - scoped_ptr<TestRenderViewContextMenu> menu(CreateMenu(url, GURL())); + scoped_ptr<TestRenderViewContextMenu> menu( + CreateMenu(browser(), url, GURL())); // The top-level item should be an "automagic parent" with the extension's // name. @@ -336,7 +348,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Separators) { ui_test_utils::NavigateToURL(browser(), GURL(extension->GetResourceURL("test2.html"))); listener2.WaitUntilSatisfied(); - menu.reset(CreateMenu(url, GURL())); + menu.reset(CreateMenu(browser(), url, GURL())); ASSERT_TRUE(menu->GetMenuModelAndItemIndex( IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST, &model, &index)); EXPECT_EQ(UTF8ToUTF16("parent"), model->GetLabelAt(index)); @@ -368,3 +380,50 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, TargetURLs) { non_google_url, std::string("item1"))); } + +// Tests adding a simple context menu item. +IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, IncognitoSplit) { + ExtensionTestMessageListener created("created item regular", false); + ExtensionTestMessageListener created_incognito("created item incognito", + false); + + ExtensionTestMessageListener onclick("onclick fired regular", false); + ExtensionTestMessageListener onclick_incognito("onclick fired incognito", + false); + + // Open an incognito window. + ui_test_utils::OpenURLOffTheRecord(browser()->profile(), GURL("about:blank")); + + ASSERT_TRUE(LoadContextMenuExtensionIncognito("incognito")); + + // Wait for the extension's processes to tell us they've created an item. + ASSERT_TRUE(created.WaitUntilSatisfied()); + ASSERT_TRUE(created_incognito.WaitUntilSatisfied()); + + GURL page_url("http://www.google.com"); + + // Create and build our test context menu. + Browser* browser_incognito = BrowserList::FindBrowserWithType( + browser()->profile()->GetOffTheRecordProfile(), + Browser::TYPE_NORMAL, false); + ASSERT_TRUE(browser_incognito); + scoped_ptr<TestRenderViewContextMenu> menu( + CreateMenu(browser(), page_url, GURL())); + scoped_ptr<TestRenderViewContextMenu> menu_incognito( + CreateMenu(browser_incognito, page_url, GURL())); + + // Look for the extension item in the menu, and execute it. + int command_id = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST; + ASSERT_TRUE(menu->IsCommandIdEnabled(command_id)); + menu->ExecuteCommand(command_id); + + // Wait for the extension's script to tell us its onclick fired. Ensure + // that the incognito version doesn't fire until we explicitly click the + // incognito menu item. + ASSERT_TRUE(onclick.WaitUntilSatisfied()); + EXPECT_FALSE(onclick_incognito.was_satisfied()); + + ASSERT_TRUE(menu_incognito->IsCommandIdEnabled(command_id)); + menu_incognito->ExecuteCommand(command_id); + ASSERT_TRUE(onclick_incognito.WaitUntilSatisfied()); +} diff --git a/chrome/browser/extensions/extension_event_router.cc b/chrome/browser/extensions/extension_event_router.cc index b1577167774aecacdb6a025791075effdea66302..c03345445ff104262a492037cc24d6a2e13f5db8 100644 --- a/chrome/browser/extensions/extension_event_router.cc +++ b/chrome/browser/extensions/extension_event_router.cc @@ -33,17 +33,6 @@ static void DispatchEvent(RenderProcessHost* renderer, extension_id, kDispatchEvent, args, event_url)); } -static bool CanCrossIncognito(Profile* profile, - const std::string& extension_id) { - // We allow the extension to see events and data from another profile iff it - // uses "spanning" behavior and it has incognito access. "split" mode - // extensions only see events for a matching profile. - const Extension* extension = - profile->GetExtensionsService()->GetExtensionById(extension_id, false); - return (profile->GetExtensionsService()->IsIncognitoEnabled(extension) && - !extension->incognito_split_mode()); -} - } // namespace struct ExtensionEventRouter::EventListener { @@ -63,6 +52,24 @@ struct ExtensionEventRouter::EventListener { } }; +// static +bool ExtensionEventRouter::CanCrossIncognito(Profile* profile, + const std::string& extension_id) { + const Extension* extension = + profile->GetExtensionsService()->GetExtensionById(extension_id, false); + return CanCrossIncognito(profile, extension); +} + +// static +bool ExtensionEventRouter::CanCrossIncognito(Profile* profile, + const Extension* extension) { + // We allow the extension to see events and data from another profile iff it + // uses "spanning" behavior and it has incognito access. "split" mode + // extensions only see events for a matching profile. + return (profile->GetExtensionsService()->IsIncognitoEnabled(extension) && + !extension->incognito_split_mode()); +} + ExtensionEventRouter::ExtensionEventRouter(Profile* profile) : profile_(profile), extension_devtools_manager_(profile->GetExtensionDevToolsManager()) { diff --git a/chrome/browser/extensions/extension_event_router.h b/chrome/browser/extensions/extension_event_router.h index 5e1ca970052c88b878455c9452cde2362ce1c411..c9f1f21e204c9abb3cef53a40b90c4b5f7d19fb4 100644 --- a/chrome/browser/extensions/extension_event_router.h +++ b/chrome/browser/extensions/extension_event_router.h @@ -15,12 +15,19 @@ #include "chrome/common/notification_registrar.h" class GURL; +class Extension; class ExtensionDevToolsManager; class Profile; class RenderProcessHost; class ExtensionEventRouter : public NotificationObserver { public: + // Returns true if the given extension can see events and data from another + // sub-profile (incognito to original profile, or vice versa). + static bool CanCrossIncognito(Profile* profile, + const std::string& extension_id); + static bool CanCrossIncognito(Profile* profile, const Extension* extension); + explicit ExtensionEventRouter(Profile* profile); ~ExtensionEventRouter(); diff --git a/chrome/browser/extensions/extension_menu_manager.cc b/chrome/browser/extensions/extension_menu_manager.cc index 9ddb0f0e051a4a9c8e391e74d5d3f663e347dc99..eae74f6697f65cf3bc81d28c9c1939a8a25be5a3 100644 --- a/chrome/browser/extensions/extension_menu_manager.cc +++ b/chrome/browser/extensions/extension_menu_manager.cc @@ -389,9 +389,9 @@ void ExtensionMenuManager::ExecuteCommand( ListValue args; DictionaryValue* properties = new DictionaryValue(); - properties->SetInteger("menuItemId", item->id().second); + properties->SetInteger("menuItemId", item->id().uid); if (item->parent_id()) - properties->SetInteger("parentMenuItemId", item->parent_id()->second); + properties->SetInteger("parentMenuItemId", item->parent_id()->uid); switch (params.media_type) { case WebKit::WebContextMenuData::MediaTypeImage: @@ -471,3 +471,36 @@ bool ExtensionMenuManager::HasAllowedScheme(const GURL& url) { URLPattern pattern(kAllowedSchemes); return pattern.SetScheme(url.scheme()); } + +ExtensionMenuItem::Id::Id() + : profile(NULL), uid(0) { +} + +ExtensionMenuItem::Id::Id(Profile* profile, std::string extension_id, int uid) + : profile(profile), extension_id(extension_id), uid(uid) { +} + +ExtensionMenuItem::Id::~Id() { +} + +bool ExtensionMenuItem::Id::operator==(const Id& other) const { + return (profile == other.profile && + extension_id == other.extension_id && + uid == other.uid); +} + +bool ExtensionMenuItem::Id::operator!=(const Id& other) const { + return !(*this == other); +} + +bool ExtensionMenuItem::Id::operator<(const Id& other) const { + if (profile < other.profile) + return true; + if (profile == other.profile) { + if (extension_id < other.extension_id) + return true; + if (extension_id == other.extension_id) + return uid < other.uid; + } + return false; +} diff --git a/chrome/browser/extensions/extension_menu_manager.h b/chrome/browser/extensions/extension_menu_manager.h index 4455ee1a16cc6c56d78a8c18b108ada2efb0e9f7..c8224d11dd70d3990bbb94822624b787f68faa83 100644 --- a/chrome/browser/extensions/extension_menu_manager.h +++ b/chrome/browser/extensions/extension_menu_manager.h @@ -33,9 +33,20 @@ class ExtensionMenuItem { // A list of ExtensionMenuItem's. typedef std::vector<ExtensionMenuItem*> List; - // An Id is a pair of |extension id|, |int| where the |int| is unique per - // extension. - typedef std::pair<std::string, int> Id; + // An Id uniquely identifies a context menu item registered by an extension. + struct Id { + Id(); + Id(Profile* profile, std::string extension_id, int uid); + ~Id(); + + bool operator==(const Id& other) const; + bool operator!=(const Id& other) const; + bool operator<(const Id& other) const; + + Profile* profile; + std::string extension_id; + int uid; + }; // For context menus, these are the contexts where an item can appear. enum Context { @@ -93,7 +104,7 @@ class ExtensionMenuItem { virtual ~ExtensionMenuItem(); // Simple accessor methods. - const std::string& extension_id() const { return id_.first; } + const std::string& extension_id() const { return id_.extension_id; } const std::string& title() const { return title_; } const List& children() { return children_; } const Id& id() const { return id_; } diff --git a/chrome/browser/extensions/extension_menu_manager_unittest.cc b/chrome/browser/extensions/extension_menu_manager_unittest.cc index 549c24570338b0ab17e6a90d4db97b7e606f8aa9..cbd9a52835f2da3bb86db16fbff84f6550ae5648 100644 --- a/chrome/browser/extensions/extension_menu_manager_unittest.cc +++ b/chrome/browser/extensions/extension_menu_manager_unittest.cc @@ -37,7 +37,7 @@ class ExtensionMenuManagerTest : public testing::Test { ExtensionMenuItem* CreateTestItem(Extension* extension) { ExtensionMenuItem::Type type = ExtensionMenuItem::NORMAL; ExtensionMenuItem::ContextList contexts(ExtensionMenuItem::ALL); - ExtensionMenuItem::Id id(extension->id(), next_id_++); + ExtensionMenuItem::Id id(NULL, extension->id(), next_id_++); return new ExtensionMenuItem(id, "test", false, type, contexts); } @@ -94,7 +94,7 @@ TEST_F(ExtensionMenuManagerTest, AddGetRemoveItems) { ASSERT_EQ(2u, manager_.MenuItems(extension_id)->size()); // Make sure removing a non-existent item returns false. - ExtensionMenuItem::Id id(extension->id(), id3.second + 50); + ExtensionMenuItem::Id id(NULL, extension->id(), id3.uid + 50); ASSERT_FALSE(manager_.RemoveContextMenuItem(id)); } @@ -461,7 +461,7 @@ TEST_F(ExtensionMenuManagerTest, ExecuteCommand) { int tmp_id = 0; ASSERT_TRUE(info->GetInteger("menuItemId", &tmp_id)); - ASSERT_EQ(id.second, tmp_id); + ASSERT_EQ(id.uid, tmp_id); std::string tmp; ASSERT_TRUE(info->GetString("mediaType", &tmp)); diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc index 35988088c934ec64b66a1db1eac89a0414963f8a..11d5f31a1eadec464057d86ef2616371a810c89a 100644 --- a/chrome/browser/extensions/extension_tabs_module.cc +++ b/chrome/browser/extensions/extension_tabs_module.cc @@ -598,9 +598,10 @@ bool CreateTabFunction::RunImpl() { EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kSelectedKey, &selected)); - // We can't load extension URLs into incognito windows. Special case to - // fall back to a normal window. + // We can't load extension URLs into incognito windows unless the extension + // uses split mode. Special case to fall back to a normal window. if (url.SchemeIs(chrome::kExtensionScheme) && + !GetExtension()->incognito_split_mode() && browser->profile()->IsOffTheRecord()) { Profile* profile = browser->profile()->GetOriginalProfile(); browser = BrowserList::FindBrowserWithType(profile, diff --git a/chrome/browser/extensions/extension_test_message_listener.cc b/chrome/browser/extensions/extension_test_message_listener.cc index 423bf3b10a7feef61c0f4bfc50c388023d54d265..8ba0683461efe4fab6b4bd5e62ba65f70008a55f 100644 --- a/chrome/browser/extensions/extension_test_message_listener.cc +++ b/chrome/browser/extensions/extension_test_message_listener.cc @@ -43,8 +43,8 @@ void ExtensionTestMessageListener::Observe( const NotificationSource& source, const NotificationDetails& details) { const std::string& content = *Details<std::string>(details).ptr(); - function_ = Source<ExtensionTestSendMessageFunction>(source).ptr(); if (!satisfied_ && content == expected_message_) { + function_ = Source<ExtensionTestSendMessageFunction>(source).ptr(); satisfied_ = true; registrar_.RemoveAll(); // Stop listening for more messages. if (!will_reply_) { diff --git a/chrome/browser/extensions/extension_test_message_listener.h b/chrome/browser/extensions/extension_test_message_listener.h index bead446aba608dd7d20f54371cdbe85d38a7da21..86c4cf26ca9e352c9f85a35150d1d8643aad121c 100644 --- a/chrome/browser/extensions/extension_test_message_listener.h +++ b/chrome/browser/extensions/extension_test_message_listener.h @@ -63,6 +63,8 @@ class ExtensionTestMessageListener : public NotificationObserver { const NotificationSource& source, const NotificationDetails& details); + bool was_satisfied() const { return satisfied_; } + private: NotificationRegistrar registrar_; diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc index afd5ccbdc6039d45d026ff66c714b591a170a538..f792b359d7f8e69e85f1cc5e197284c81cec3c2e 100644 --- a/chrome/browser/tab_contents/render_view_context_menu.cc +++ b/chrome/browser/tab_contents/render_view_context_menu.cc @@ -23,6 +23,7 @@ #include "chrome/browser/debugger/devtools_manager.h" #include "chrome/browser/debugger/devtools_window.h" #include "chrome/browser/download/download_manager.h" +#include "chrome/browser/extensions/extension_event_router.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/fonts_languages_window.h" #include "chrome/browser/metrics/user_metrics.h" @@ -150,10 +151,12 @@ static const GURL& GetDocumentURL(const ContextMenuParams& params) { } // Given a list of items, returns the ones that match given the contents -// of |params|. +// of |params| and the profile. static ExtensionMenuItem::List GetRelevantExtensionItems( const ExtensionMenuItem::List& items, - const ContextMenuParams& params) { + const ContextMenuParams& params, + Profile* profile, + bool can_cross_incognito) { ExtensionMenuItem::List result; for (ExtensionMenuItem::List::const_iterator i = items.begin(); i != items.end(); ++i) { @@ -171,7 +174,8 @@ static ExtensionMenuItem::List GetRelevantExtensionItems( if (!ExtensionPatternMatch(item->target_url_patterns(), target_url)) continue; - result.push_back(*i); + if (item->id().profile == profile || can_cross_incognito) + result.push_back(*i); } return result; } @@ -181,6 +185,8 @@ void RenderViewContextMenu::AppendExtensionItems( ExtensionsService* service = profile_->GetExtensionsService(); ExtensionMenuManager* manager = service->menu_manager(); const Extension* extension = service->GetExtensionById(extension_id, false); + bool can_cross_incognito = + ExtensionEventRouter::CanCrossIncognito(profile_, extension); DCHECK_GE(*index, 0); int max_index = IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST - IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST; @@ -192,7 +198,8 @@ void RenderViewContextMenu::AppendExtensionItems( if (!all_items || all_items->empty()) return; ExtensionMenuItem::List items = - GetRelevantExtensionItems(*all_items, params_); + GetRelevantExtensionItems(*all_items, params_, profile_, + can_cross_incognito); if (items.empty()) return; @@ -215,7 +222,8 @@ void RenderViewContextMenu::AppendExtensionItems( extension_item_map_[menu_id] = item->id(); title = item->TitleWithReplacement(PrintableSelectionText(), kMaxExtensionItemTitleLength); - submenu_items = GetRelevantExtensionItems(item->children(), params_); + submenu_items = GetRelevantExtensionItems(item->children(), params_, + profile_, can_cross_incognito); } // Now add our item(s) to the menu_model_. @@ -225,13 +233,15 @@ void RenderViewContextMenu::AppendExtensionItems( menus::SimpleMenuModel* submenu = new menus::SimpleMenuModel(this); extension_menu_models_.push_back(submenu); menu_model_.AddSubMenu(menu_id, title, submenu); - RecursivelyAppendExtensionItems(submenu_items, submenu, index); + RecursivelyAppendExtensionItems(submenu_items, can_cross_incognito, submenu, + index); } SetExtensionIcon(extension_id); } void RenderViewContextMenu::RecursivelyAppendExtensionItems( const ExtensionMenuItem::List& items, + bool can_cross_incognito, menus::SimpleMenuModel* menu_model, int *index) { string16 selection_text = PrintableSelectionText(); @@ -258,14 +268,16 @@ void RenderViewContextMenu::RecursivelyAppendExtensionItems( kMaxExtensionItemTitleLength); if (item->type() == ExtensionMenuItem::NORMAL) { ExtensionMenuItem::List children = - GetRelevantExtensionItems(item->children(), params_); + GetRelevantExtensionItems(item->children(), params_, + profile_, can_cross_incognito); if (children.size() == 0) { menu_model->AddItem(menu_id, title); } else { menus::SimpleMenuModel* submenu = new menus::SimpleMenuModel(this); extension_menu_models_.push_back(submenu); menu_model->AddSubMenu(menu_id, title, submenu); - RecursivelyAppendExtensionItems(children, submenu, index); + RecursivelyAppendExtensionItems(children, can_cross_incognito, + submenu, index); } } else if (item->type() == ExtensionMenuItem::CHECKBOX) { menu_model->AddCheckItem(menu_id, title); diff --git a/chrome/browser/tab_contents/render_view_context_menu.h b/chrome/browser/tab_contents/render_view_context_menu.h index 9fd3108fb22425abe0c754bd1e603422ba45b5d7..2f1a83e899656575d0052744fed8d76ac54a65c2 100644 --- a/chrome/browser/tab_contents/render_view_context_menu.h +++ b/chrome/browser/tab_contents/render_view_context_menu.h @@ -103,6 +103,7 @@ class RenderViewContextMenu : public menus::SimpleMenuModel::Delegate { // Used for recursively adding submenus of extension items. void RecursivelyAppendExtensionItems( const std::vector<ExtensionMenuItem*>& items, + bool can_cross_incognito, menus::SimpleMenuModel* menu_model, int *index); // This will set the icon on the most recently-added item in the menu_model_. diff --git a/chrome/test/data/extensions/context_menus/incognito/background.html b/chrome/test/data/extensions/context_menus/incognito/background.html new file mode 100644 index 0000000000000000000000000000000000000000..46f4d74c30692c8ab193b54683da02bd212ef91f --- /dev/null +++ b/chrome/test/data/extensions/context_menus/incognito/background.html @@ -0,0 +1 @@ +<script src="test.js"></script> diff --git a/chrome/test/data/extensions/context_menus/incognito/manifest.json b/chrome/test/data/extensions/context_menus/incognito/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..560ca1300cc8d6609cd77a018b68cef5c81a51ee --- /dev/null +++ b/chrome/test/data/extensions/context_menus/incognito/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "Tests that context menus work properly in incognito split mode", + "version": "0.1", + "permissions": ["contextMenus"], + "incognito": "split", + "background_page": "background.html" +} diff --git a/chrome/test/data/extensions/context_menus/incognito/test.js b/chrome/test/data/extensions/context_menus/incognito/test.js new file mode 100644 index 0000000000000000000000000000000000000000..c64b01a36adb066af595813c26981945f84d9274 --- /dev/null +++ b/chrome/test/data/extensions/context_menus/incognito/test.js @@ -0,0 +1,19 @@ +// 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. + +var inIncognitoContext = chrome.extension.inIncognitoContext; +var incognitoStr = inIncognitoContext ? "incognito" : "regular"; + +function onclick(info) { + chrome.test.sendMessage("onclick fired " + incognitoStr); +} + +window.onload = function() { + chrome.contextMenus.create({title: "item " + incognitoStr, + onclick: onclick}, function() { + if (!chrome.extension.lastError) { + chrome.test.sendMessage("created item " + incognitoStr); + } + }); +};