diff options
author | jochen <jochen@chromium.org> | 2015-10-26 04:19:29 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-26 11:20:14 +0000 |
commit | 3917ff9e77c4da3d2d56398cebdc52312b2b63d3 (patch) | |
tree | ec6fe8230d089183e788a118665169dd27a52392 | |
parent | 27af50fa8c583cce01ef87827df4fd1ac98480b5 (diff) | |
download | chromium_src-3917ff9e77c4da3d2d56398cebdc52312b2b63d3.zip chromium_src-3917ff9e77c4da3d2d56398cebdc52312b2b63d3.tar.gz chromium_src-3917ff9e77c4da3d2d56398cebdc52312b2b63d3.tar.bz2 |
Implement "open link as user" context menu entry
The menu entry is only present if multiple profiles are defined, and
only displays those that currently have open windows.
If only a single other profile has an open window, no sub-menu is
created
BUG=103073
R=pkasting@chromium.org
TEST=ContextMenuBrowserTest.OpenLinkInProfile*
Review URL: https://codereview.chromium.org/1191453002
Cr-Commit-Position: refs/heads/master@{#356023}
12 files changed, 297 insertions, 20 deletions
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index 850903f..7b13dd3 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h @@ -277,6 +277,7 @@ #define IDC_CONTENT_CONTEXT_COPYEMAILADDRESS 50105 #define IDC_CONTENT_CONTEXT_OPENLINKWITH 50106 #define IDC_CONTENT_CONTEXT_COPYLINKTEXT 50107 +#define IDC_CONTENT_CONTEXT_OPENLINKINPROFILE 50108 // Image items. #define IDC_CONTENT_CONTEXT_SAVEIMAGEAS 50110 #define IDC_CONTENT_CONTEXT_COPYIMAGELOCATION 50111 @@ -367,6 +368,10 @@ #define IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_LAST 52199 #define IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS 52200 +// Open link in profile entries +#define IDC_OPEN_LINK_IN_PROFILE_FIRST 52300 +#define IDC_OPEN_LINK_IN_PROFILE_LAST 52399 + // NOTE: The last valid command value is 57343 (0xDFFF) // See http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 09316a1..d2e5c61 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -719,6 +719,12 @@ Psst! Incognito mode <ph name="SHORTCUT_KEY">$1<ex>(Ctrl+Shift+N)</ex></ph> may <message name="IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD" desc="The name of the open a link in incognito window command"> Open link in inco&gnito window </message> + <message name="IDS_CONTENT_CONTEXT_OPENLINKINPROFILES" desc="The name of the open a link as a different user context menu"> + Open link as + </message> + <message name="IDS_CONTENT_CONTEXT_OPENLINKINPROFILE" desc="The name of the open a link as a different user command"> + Open link as <ph name="USER">$1<ex>user@gmail.com</ex></ph> + </message> <message name="IDS_CONTENT_CONTEXT_SAVELINKAS" desc="The name of the Save Link As command in the content area context menu"> Save lin&k as... @@ -929,6 +935,12 @@ Psst! Incognito mode <ph name="SHORTCUT_KEY">$1<ex>(Ctrl+Shift+N)</ex></ph> may <message name="IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD" desc="In Title Case: The name of the open a link in incognito window command"> Open Link in Inco&gnito Window </message> + <message name="IDS_CONTENT_CONTEXT_OPENLINKINPROFILES" desc="In Title Case: The name of the open a link as a different user context menu"> + Open Link as + </message> + <message name="IDS_CONTENT_CONTEXT_OPENLINKINPROFILE" desc="In Title Case: The name of the open a link as a different user command"> + Open Link as <ph name="USER">$1<ex>user@gmail.com</ex></ph> + </message> <message name="IDS_CONTENT_CONTEXT_SAVELINKAS" desc="In Title Case: The name of the Save Link As command in the content area context menu"> Save Lin&k As... diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc index f7e8b2b..fd71e17 100644 --- a/chrome/browser/profiles/profile_info_cache.cc +++ b/chrome/browser/profiles/profile_info_cache.cc @@ -324,7 +324,7 @@ base::string16 ProfileInfoCache::GetUserNameOfProfileAtIndex( } const gfx::Image& ProfileInfoCache::GetAvatarIconOfProfileAtIndex( - size_t index) { + size_t index) const { if (IsUsingGAIAPictureOfProfileAtIndex(index)) { const gfx::Image* image = GetGAIAPictureOfProfileAtIndex(index); if (image) diff --git a/chrome/browser/profiles/profile_info_cache.h b/chrome/browser/profiles/profile_info_cache.h index 9aff678..fb99042 100644 --- a/chrome/browser/profiles/profile_info_cache.h +++ b/chrome/browser/profiles/profile_info_cache.h @@ -74,7 +74,7 @@ class ProfileInfoCache : public ProfileInfoInterface, base::FilePath GetPathOfProfileAtIndex(size_t index) const override; base::Time GetProfileActiveTimeAtIndex(size_t index) const override; base::string16 GetUserNameOfProfileAtIndex(size_t index) const override; - const gfx::Image& GetAvatarIconOfProfileAtIndex(size_t index) override; + const gfx::Image& GetAvatarIconOfProfileAtIndex(size_t index) const override; std::string GetLocalAuthCredentialsOfProfileAtIndex( size_t index) const override; std::string GetPasswordChangeDetectionTokenAtIndex( diff --git a/chrome/browser/profiles/profile_info_interface.h b/chrome/browser/profiles/profile_info_interface.h index c1f3ec5..48a26e8 100644 --- a/chrome/browser/profiles/profile_info_interface.h +++ b/chrome/browser/profiles/profile_info_interface.h @@ -39,7 +39,8 @@ class ProfileInfoInterface { virtual base::string16 GetUserNameOfProfileAtIndex(size_t index) const = 0; - virtual const gfx::Image& GetAvatarIconOfProfileAtIndex(size_t index) = 0; + virtual const gfx::Image& GetAvatarIconOfProfileAtIndex( + size_t index) const = 0; virtual std::string GetLocalAuthCredentialsOfProfileAtIndex( size_t index) const = 0; diff --git a/chrome/browser/profiles/profile_metrics.h b/chrome/browser/profiles/profile_metrics.h index d9c4975..0b3c71f 100644 --- a/chrome/browser/profiles/profile_metrics.h +++ b/chrome/browser/profiles/profile_metrics.h @@ -62,15 +62,16 @@ class ProfileMetrics { // Enum for counting the ways user profiles and menus were opened. enum ProfileOpen { - NTP_AVATAR_BUBBLE = 0, // User opens avatar menu from NTP - ICON_AVATAR_BUBBLE, // User opens the avatar menu from button - SWITCH_PROFILE_ICON, // User switches profiles from icon menu - SWITCH_PROFILE_MENU, // User switches profiles from menu bar - SWITCH_PROFILE_DOCK, // User switches profiles from dock (Mac-only) - OPEN_USER_MANAGER, // User opens the User Manager - SWITCH_PROFILE_MANAGER, // User switches profiles from the User Manager - SWITCH_PROFILE_UNLOCK, // User switches to lockd profile via User Manager - SWITCH_PROFILE_GUEST, // User switches to guest profile + NTP_AVATAR_BUBBLE = 0, // User opens avatar menu from NTP + ICON_AVATAR_BUBBLE, // User opens the avatar menu from button + SWITCH_PROFILE_ICON, // User switches profiles from icon menu + SWITCH_PROFILE_MENU, // User switches profiles from menu bar + SWITCH_PROFILE_DOCK, // User switches profiles from dock (Mac-only) + OPEN_USER_MANAGER, // User opens the User Manager + SWITCH_PROFILE_MANAGER, // User switches profiles from the User Manager + SWITCH_PROFILE_UNLOCK, // User switches to locked profile via User Manager + SWITCH_PROFILE_GUEST, // User switches to guest profile + SWITCH_PROFILE_CONTEXT_MENU, // User switches profiles from context menu NUM_PROFILE_OPEN_METRICS }; diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 5cc3c5e0..455ee81 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc @@ -37,7 +37,11 @@ #include "chrome/browser/plugins/chrome_plugin_service_filter.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_avatar_icon_util.h" +#include "chrome/browser/profiles/profile_info_cache.h" #include "chrome/browser/profiles/profile_io_data.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/profiles/profile_window.h" #include "chrome/browser/renderer_context_menu/context_menu_content_type_factory.h" #include "chrome/browser/renderer_context_menu/spelling_menu_observer.h" #include "chrome/browser/search/search.h" @@ -51,6 +55,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/tab_contents/core_tab_helper.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -123,6 +128,10 @@ #endif // defined(ENABLE_PRINT_PREVIEW) #endif // defined(ENABLE_PRINTING) +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#endif + using base::UserMetricsAction; using blink::WebContextMenuData; using blink::WebMediaPlayerAction; @@ -242,9 +251,11 @@ const struct UmaEnumCommandIdPair { {67, -1, IDC_CONTENT_CONTEXT_FORCESAVEPASSWORD}, {68, -1, IDC_ROUTE_MEDIA}, {69, -1, IDC_CONTENT_CONTEXT_COPYLINKTEXT}, + {70, -1, IDC_CONTENT_CONTEXT_OPENLINKINPROFILE}, + {71, -1, IDC_OPEN_LINK_IN_PROFILE_FIRST}, // Add new items here and use |enum_id| from the next line. // Also, add new items to RenderViewContextMenuItem enum in histograms.xml. - {70, -1, 0}, // Must be the last. Increment |enum_id| when new IDC + {72, -1, 0}, // Must be the last. Increment |enum_id| when new IDC // was added. }; @@ -268,6 +279,11 @@ int CollapseCommandsForUMA(int id) { return IDC_SPELLCHECK_SUGGESTION_0; } + if (id >= IDC_OPEN_LINK_IN_PROFILE_FIRST && + id <= IDC_OPEN_LINK_IN_PROFILE_LAST) { + return IDC_OPEN_LINK_IN_PROFILE_FIRST; + } + return id; } @@ -323,9 +339,8 @@ const GURL& GetDocumentURL(const content::ContextMenuParams& params) { return params.frame_url.is_empty() ? params.page_url : params.frame_url; } -content::Referrer CreateSaveAsReferrer( - const GURL& url, - const content::ContextMenuParams& params) { +content::Referrer CreateReferrer(const GURL& url, + const content::ContextMenuParams& params) { const GURL& referring_url = GetDocumentURL(params); return content::Referrer::SanitizeForRequest( url, @@ -369,6 +384,30 @@ void WriteTextToClipboard(const base::string16& text) { bool g_custom_id_ranges_initialized = false; +void AddIconToLastMenuItem(gfx::Image icon, ui::SimpleMenuModel* menu) { + int width = icon.Width(); + int height = icon.Height(); + gfx::CalculateFaviconTargetSize(&width, &height); + menu->SetIcon(menu->GetItemCount() - 1, + profiles::GetSizedAvatarIcon(icon, true, width, height)); +} + +void OnProfileCreated(chrome::HostDesktopType desktop_type, + const GURL& link_url, + const content::Referrer& referrer, + Profile* profile, + Profile::CreateStatus status) { + if (status == Profile::CREATE_STATUS_INITIALIZED) { + Browser* browser = chrome::FindLastActiveWithProfile(profile, desktop_type); + chrome::NavigateParams nav_params(browser, link_url, + ui::PAGE_TRANSITION_LINK); + nav_params.disposition = NEW_FOREGROUND_TAB; + nav_params.referrer = referrer; + nav_params.window_action = chrome::NavigateParams::SHOW_WINDOW; + chrome::Navigate(&nav_params); + } +} + } // namespace // static @@ -410,6 +449,7 @@ RenderViewContextMenu::RenderViewContextMenu( this, &menu_model_, base::Bind(MenuItemMatchesParams, params_)), + profile_link_submenu_model_(this), protocol_handler_submenu_model_(this), protocol_handler_registry_( ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile())), @@ -812,6 +852,65 @@ void RenderViewContextMenu::AppendLinkItems() { menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD, IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD); + + // g_browser_process->profile_manager() is null during unit tests. + if (g_browser_process->profile_manager() && + GetProfile()->GetProfileType() == Profile::REGULAR_PROFILE) { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + const ProfileInfoCache& profile_info_cache = + profile_manager->GetProfileInfoCache(); + + // Find all regular profiles other than the current one which have at + // least one open window. + std::vector<size_t> target_profiles; + const size_t profile_count = profile_info_cache.GetNumberOfProfiles(); + for (size_t profile_index = 0; profile_index < profile_count; + ++profile_index) { + base::FilePath profile_path = + profile_info_cache.GetPathOfProfileAtIndex(profile_index); +#if defined(OS_CHROMEOS) + if (profile_path == chromeos::ProfileHelper::GetSigninProfileDir()) + continue; +#endif + Profile* profile = profile_manager->GetProfileByPath(profile_path); + if ((profile != GetProfile()) && + !profile_info_cache.IsOmittedProfileAtIndex(profile_index)) { + target_profiles.push_back(profile_index); + } + } + + if (target_profiles.size() == 1) { + size_t profile_index = target_profiles[0]; + menu_model_.AddItem( + IDC_OPEN_LINK_IN_PROFILE_FIRST + profile_index, + l10n_util::GetStringFUTF16( + IDS_CONTENT_CONTEXT_OPENLINKINPROFILE, + profile_info_cache.GetNameOfProfileAtIndex(profile_index))); + AddIconToLastMenuItem( + profile_info_cache.GetAvatarIconOfProfileAtIndex(profile_index), + &menu_model_); + } else if (target_profiles.size() > 1) { + for (size_t profile_index : target_profiles) { + // In extreme cases, we might have more profiles than available + // command ids. In that case, just stop creating new entries - the + // menu is probably useless at this point already. + if (IDC_OPEN_LINK_IN_PROFILE_FIRST + profile_index > + IDC_OPEN_LINK_IN_PROFILE_LAST) + break; + profile_link_submenu_model_.AddItem( + IDC_OPEN_LINK_IN_PROFILE_FIRST + profile_index, + profile_info_cache.GetNameOfProfileAtIndex(profile_index)); + AddIconToLastMenuItem( + profile_info_cache.GetAvatarIconOfProfileAtIndex(profile_index), + &profile_link_submenu_model_); + } + menu_model_.AddSubMenuWithStringId( + IDC_CONTENT_CONTEXT_OPENLINKINPROFILE, + IDS_CONTENT_CONTEXT_OPENLINKINPROFILES, + &profile_link_submenu_model_); + } + } + menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVELINKAS, IDS_CONTENT_CONTEXT_SAVELINKAS); } @@ -1147,6 +1246,11 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { return true; } + if (id >= IDC_OPEN_LINK_IN_PROFILE_FIRST && + id <= IDC_OPEN_LINK_IN_PROFILE_LAST) { + return params_.link_url.is_valid(); + } + IncognitoModePrefs::Availability incognito_avail = IncognitoModePrefs::GetAvailability(prefs); switch (id) { @@ -1223,6 +1327,7 @@ bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB: case IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW: + case IDC_CONTENT_CONTEXT_OPENLINKINPROFILE: return params_.link_url.is_valid(); case IDC_CONTENT_CONTEXT_COPYLINKLOCATION: @@ -1494,6 +1599,26 @@ void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) { return; } + if (id >= IDC_OPEN_LINK_IN_PROFILE_FIRST && + id <= IDC_OPEN_LINK_IN_PROFILE_LAST) { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + const ProfileInfoCache& profile_info_cache = + profile_manager->GetProfileInfoCache(); + + base::FilePath profile_path = profile_info_cache.GetPathOfProfileAtIndex( + id - IDC_OPEN_LINK_IN_PROFILE_FIRST); + chrome::HostDesktopType desktop_type = + chrome::GetHostDesktopTypeForNativeView( + source_web_contents_->GetNativeView()); + + profiles::SwitchToProfile( + profile_path, desktop_type, false, + base::Bind(OnProfileCreated, desktop_type, params_.link_url, + CreateReferrer(params_.link_url, params_)), + ProfileMetrics::SWITCH_PROFILE_CONTEXT_MENU); + return; + } + switch (id) { case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB: { Browser* browser = @@ -1520,7 +1645,7 @@ void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) { case IDC_CONTENT_CONTEXT_SAVELINKAS: { RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU); const GURL& url = params_.link_url; - content::Referrer referrer = CreateSaveAsReferrer(url, params_); + content::Referrer referrer = CreateReferrer(url, params_); DownloadManager* dlm = BrowserContext::GetDownloadManager(browser_context_); scoped_ptr<DownloadUrlParameters> dl_params( @@ -1545,7 +1670,7 @@ void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) { } else { RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU); const GURL& url = params_.src_url; - content::Referrer referrer = CreateSaveAsReferrer(url, params_); + content::Referrer referrer = CreateReferrer(url, params_); std::string headers; DataReductionProxyChromeSettings* settings = diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h index e198d4f..8312397 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.h +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h @@ -168,6 +168,7 @@ class RenderViewContextMenu : public RenderViewContextMenuBase { // a text selection. GURL selection_navigation_url_; + ui::SimpleMenuModel profile_link_submenu_model_; ui::SimpleMenuModel protocol_handler_submenu_model_; ProtocolHandlerRegistry* protocol_handler_registry_; diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc index 18e41b1..3891232 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc @@ -10,9 +10,12 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/profiles/profile_window.h" #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h" #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h" @@ -44,6 +47,11 @@ #include "third_party/WebKit/public/web/WebContextMenuData.h" #include "third_party/WebKit/public/web/WebInputEvent.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "components/user_manager/user_manager.h" +#endif + using content::WebContents; namespace { @@ -94,6 +102,23 @@ class ContextMenuBrowserTest : public InProcessBrowserTest { menu->Init(); return menu; } + + Profile* CreateSecondaryProfile(int profile_num) { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + base::FilePath profile_path = profile_manager->user_data_dir(); +#if defined(OS_CHROMEOS) + std::string profile_name = base::StringPrintf("NewProfile%d", profile_num); + user_manager::UserManager::Get()->UserLoggedIn( + base::StringPrintf("user%d@test.com", profile_num), profile_name, + false); + profile_path = profile_path.Append( + chromeos::ProfileHelper::GetUserProfileDir(profile_name).BaseName()); +#else + profile_path = profile_path.AppendASCII( + base::StringPrintf("New Profile %d", profile_num)); +#endif + return profile_manager->GetProfile(profile_path); + } }; IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, @@ -104,6 +129,9 @@ IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB)); ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW)); ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_COPYLINKLOCATION)); + ASSERT_FALSE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKINPROFILE)); + ASSERT_FALSE(menu->IsItemInRangePresent(IDC_OPEN_LINK_IN_PROFILE_FIRST, + IDC_OPEN_LINK_IN_PROFILE_LAST)); } IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, @@ -114,6 +142,9 @@ IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, ASSERT_FALSE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB)); ASSERT_FALSE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW)); ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_COPYLINKLOCATION)); + ASSERT_FALSE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKINPROFILE)); + ASSERT_FALSE(menu->IsItemInRangePresent(IDC_OPEN_LINK_IN_PROFILE_FIRST, + IDC_OPEN_LINK_IN_PROFILE_LAST)); } IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, ContextMenuForCanvas) { @@ -397,6 +428,87 @@ IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, OpenImageInNewTab) { ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB)); } +IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, OpenLinkInProfileEntryPresent) { + { + scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenuMediaTypeNone( + GURL("http://www.google.com/"), GURL("http://www.google.com/"))); + + ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB)); + ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW)); + ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_COPYLINKLOCATION)); + // With only one profile exists, we don't add any items to the context menu + // for opening links in other profiles. + ASSERT_FALSE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKINPROFILE)); + ASSERT_FALSE(menu->IsItemInRangePresent(IDC_OPEN_LINK_IN_PROFILE_FIRST, + IDC_OPEN_LINK_IN_PROFILE_LAST)); + } + + // Create one additional profile, but do not yet open windows in it. + CreateSecondaryProfile(1); + + { + scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenuMediaTypeNone( + GURL("http://www.google.com/"), GURL("http://www.google.com/"))); + + ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB)); + ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW)); + ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_COPYLINKLOCATION)); + // With two profiles (the current and another profile), no submenu is + // created. Instead, a single item is added to the main context menu. + ASSERT_FALSE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKINPROFILE)); + ASSERT_TRUE(menu->IsItemInRangePresent(IDC_OPEN_LINK_IN_PROFILE_FIRST, + IDC_OPEN_LINK_IN_PROFILE_LAST)); + } + + CreateSecondaryProfile(2); + + { + scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenuMediaTypeNone( + GURL("http://www.google.com/"), GURL("http://www.google.com/"))); + + ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB)); + ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW)); + ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_COPYLINKLOCATION)); + // As soon as at least three profiles exist, we show all profiles in a + // submenu. + ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKINPROFILE)); + ASSERT_FALSE(menu->IsItemInRangePresent(IDC_OPEN_LINK_IN_PROFILE_FIRST, + IDC_OPEN_LINK_IN_PROFILE_LAST)); + } +} + +IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, OpenLinkInProfile) { + Profile* other_profile = CreateSecondaryProfile(1); + profiles::FindOrCreateNewWindowForProfile( + other_profile, chrome::startup::IS_NOT_PROCESS_STARTUP, + chrome::startup::IS_NOT_FIRST_RUN, chrome::GetActiveDesktop(), false); + + ui_test_utils::WindowedTabAddedNotificationObserver tab_observer( + content::NotificationService::AllSources()); + + ASSERT_TRUE(test_server()->Start()); + GURL url(test_server()->GetURL(std::string())); + + scoped_ptr<TestRenderViewContextMenu> menu( + CreateContextMenuMediaTypeNone(url, url)); + + menu->ExecuteCommand( + IDC_OPEN_LINK_IN_PROFILE_FIRST + + g_browser_process->profile_manager() + ->GetProfileInfoCache() + .GetIndexOfProfileWithPath(other_profile->GetPath()), + 0); + + tab_observer.Wait(); + content::WebContents* tab = tab_observer.GetTab(); + content::WaitForLoadStop(tab); + + // Verify that it's the correct tab and profile. + ASSERT_EQ(url, tab->GetURL()); + ASSERT_EQ(other_profile, + Profile::FromBrowserContext(tab->GetBrowserContext())); +} + class ThumbnailResponseWatcher : public content::NotificationObserver { public: enum QuitReason { diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc index 0465a71..e197c23 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc @@ -42,6 +42,17 @@ bool TestRenderViewContextMenu::IsItemPresent(int command_id) { return menu_model_.GetIndexOfCommandId(command_id) != -1; } +bool TestRenderViewContextMenu::IsItemInRangePresent(int command_id_first, + int command_id_last) { + DCHECK_LE(command_id_first, command_id_last); + for (int command_id = command_id_first; command_id <= command_id_last; + ++command_id) { + if (IsItemPresent(command_id)) + return true; + } + return false; +} + bool TestRenderViewContextMenu::GetMenuModelAndItemIndex( int command_id, MenuModel** found_model, diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h index 52cb904..c0fc272 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h @@ -41,11 +41,16 @@ class TestRenderViewContextMenu : public RenderViewContextMenu { bool GetAcceleratorForCommandId(int command_id, ui::Accelerator* accelerator) override; - // Returns true if command specified by |command_id| is present + // Returns true if the command specified by |command_id| is present // in the menu. - // List of command ids can be found in chrome/app/chrome_command_ids.h. + // A list of command ids can be found in chrome/app/chrome_command_ids.h. bool IsItemPresent(int command_id); + // Returns true if a command specified by any command id between + // |command_id_first| and |command_id_last| (inclusive) is present in the + // menu. + bool IsItemInRangePresent(int command_id_first, int command_id_last); + // Searches for an menu item with |command_id|. If it's found, the return // value is true and the model and index where it appears in that model are // returned in |found_model| and |found_index|. Otherwise returns false. diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 4ad8984..f792d40 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -69907,6 +69907,7 @@ To add a new entry, add it with any value and run test to compute valid value. <int value="6" label="Switch to profile via User Manager"/> <int value="7" label="Switch to locked profile via User Manager"/> <int value="8" label="Switch to Guest profile"/> + <int value="9" label="Switch to profile from context menu"/> </enum> <enum name="ProfileSigninStatus" type="int"> @@ -70747,7 +70748,10 @@ To add a new entry, add it with any value and run test to compute valid value. <int value="65" label="IDC_WRITING_DIRECTION_RTL"/> <int value="66" label="IDC_CONTENT_CONTEXT_LOAD_ORIGINAL_IMAGE"/> <int value="67" label="IDC_CONTENT_CONTEXT_FORCESAVEPASSWORD"/> + <int value="68" label="IDC_ROUTE_MEDIA"/> <int value="69" label="IDC_CONTENT_CONTEXT_COPYLINKTEXT"/> + <int value="70" label="IDC_CONTENT_CONTEXT_OPENLINKINPROFILE"/> + <int value="71" label="IDC_OPEN_LINK_IN_PROFILE_FIRST"/> </enum> <enum name="ReportProcessingResult" type="int"> |