diff options
author | skerner@chromium.org <skerner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-04 15:08:40 +0000 |
---|---|---|
committer | skerner@chromium.org <skerner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-04 15:08:40 +0000 |
commit | 51dac4e7dc4622b0f0c65c35d992ec8e743cac02 (patch) | |
tree | 58a9f74d4c53bc7163061ef705bae6763fbde03a /chrome/browser/browser.cc | |
parent | 5a9d4ed6f85d345926f6e318f51ab6396124468f (diff) | |
download | chromium_src-51dac4e7dc4622b0f0c65c35d992ec8e743cac02.zip chromium_src-51dac4e7dc4622b0f0c65c35d992ec8e743cac02.tar.gz chromium_src-51dac4e7dc4622b0f0c65c35d992ec8e743cac02.tar.bz2 |
Focus an existing app tab when an app is clicked on the new tab page or invoked using --app-id=...
BUG=none
TEST=BrowserAppRefocusTest.*
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=46208
Review URL: http://codereview.chromium.org/1693006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46347 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/browser.cc')
-rw-r--r-- | chrome/browser/browser.cc | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index fe0648c..f57dab0 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -153,6 +153,112 @@ static bool CompareURLsIgnoreRef(const GURL& url, const GURL& other) { return url_no_ref == other_no_ref; } +// Helper for FindOpenAppInstance(), defined below. Given a browser, test +// if it runs under |profile| and hosts app |extension_app|. If +// |find_panel_or_window| is true, check that |browser| is an app window +// or panel, otherwise check that it is not. Set |out_tab_idx| to +// the index of the tab that hosts the app. If the entire browser hosts +// app, |out_tab_idx| is set to kNoTab. +bool FindOpenAppInstanceInBrowser(Browser* browser, + Profile* profile, + Extension* extension_app, + bool find_panel_or_window, + int* out_tab_idx) { + if (browser->profile() != profile) + return false; + + // If we are looking for an app panel or app window and |browser| is not + // one of those types, or vise-versa, then return. + Browser::Type type = browser->type(); + if (find_panel_or_window != ((type == Browser::TYPE_EXTENSION_APP) || + (type == Browser::TYPE_APP_PANEL))) + return false; + + if (browser->extension_app() && + browser->extension_app() == extension_app) { + DCHECK(find_panel_or_window) << "Non-app window has an extension app?"; + *out_tab_idx = TabStripModel::kNoTab; // The whole window contains the app. + return true; + } + + for (int tab_idx = 0; tab_idx < browser->tab_count(); ++tab_idx) { + TabContents* tab_contents = browser->GetTabContentsAt(tab_idx); + if (!tab_contents) + continue; + + if (tab_contents->app_extension() != extension_app) + continue; + + *out_tab_idx = tab_idx; + return true; + } + return false; +} + +// Find a tab in an open browser window which is running an application +// |extension_app|. The browser must use profile |profile|, and be an +// app window or panel if and only if |find_panel_or_window| is true. +// Sets |out_browser| and |out_tab_idx| to the browser and tab index of +// the matching tab on success. |out_tab_idx| will be kNoTab if the +// browser is an app window. +bool FindOpenAppInstance(Profile* profile, + Extension* extension_app, + bool find_panel_or_window, + Browser** out_browser, + int* out_tab_idx) { + // Test the focused browser first. + Browser* browser = BrowserList::GetLastActive(); + if (browser && FindOpenAppInstanceInBrowser(browser, + profile, + extension_app, + find_panel_or_window, + out_tab_idx)) { + *out_browser = browser; + return true; + } + + BrowserList::const_iterator browser_all; + for (browser_all = BrowserList::begin(); + browser_all != BrowserList::end(); + ++browser_all) { + if (FindOpenAppInstanceInBrowser(*browser_all, + profile, + extension_app, + find_panel_or_window, + out_tab_idx)) { + *out_browser = *browser_all; + return true; + } + } + return false; +} + +// Find an existing browser window running under |profile| and hosting +// the app |extension_app|. Focus it, and return the TabContents of the +// focused tab. +TabContents* FocusExistingAppInstance(Profile* profile, + Extension* extension_app) { + Browser* browser; + int tab_idx; + + // Fist, search for app windows or panels. If none are found, search + // for app tabs. + if (FindOpenAppInstance(profile, extension_app, true, &browser, &tab_idx) || + FindOpenAppInstance(profile, extension_app, false, &browser, &tab_idx)) { + + // If the entire window is owned by the app, then select the first + // tab. TODO(skerner): Does it make more sense to not change the + // focused tab? Reconsider this after using apps for a week or two. + if (tab_idx == TabStripModel::kNoTab) + tab_idx = 0; + + browser->SelectTabContentsAt(tab_idx, false); + browser->window()->Show(); + return browser->GetTabContentsAt(tab_idx); + } + return NULL; +} + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -416,6 +522,12 @@ TabContents* Browser::OpenApplication(Profile* profile, if (!extension) return NULL; + // If the app is loaded in an existing window or tab, Focus it. + TabContents* tab = FocusExistingAppInstance(profile, extension); + if (tab) + return tab; + + // The app is not yet open. Load it. return OpenApplication(profile, extension, extension->launch_container()); } |