extension_tab_util.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "apps/shell_window.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/tabs/tabs_constants.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/shell_window_registry.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/window_controller.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/window_controller_list.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/url_fixer_upper.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_id.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_manifest_constants.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/manifest_url_handler.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/permissions/api_permission.h" 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/extensions/permissions/permissions_data.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/favicon_status.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace keys = extensions::tabs_constants; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace tabs = extensions::api::tabs; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing apps::ShellWindow; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::APIPermission; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extensions::WindowController* GetShellWindowController( 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const WebContents* contents) { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ShellWindowRegistry* registry = 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ShellWindowRegistry::Get(profile); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!registry) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShellWindow* shell_window = 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->GetShellWindowForRenderViewHost(contents->GetRenderViewHost()); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!shell_window) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return extensions::WindowControllerList::GetInstance()-> 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FindWindowById(shell_window->session_id().id()); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionTabUtil::GetWindowId(const Browser* browser) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browser->session_id().id(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionTabUtil::GetWindowIdOfTabStripModel( 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TabStripModel* tab_strip_model) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (chrome::BrowserIterator it; !it.done(); it.Next()) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->tab_strip_model() == tab_strip_model) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetWindowId(*it); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionTabUtil::GetTabId(const WebContents* web_contents) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SessionID::IdForTab(web_contents); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ExtensionTabUtil::GetTabStatusText(bool is_loading) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_loading ? keys::kStatusValueLoading : keys::kStatusValueComplete; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionTabUtil::GetWindowIdOfTab(const WebContents* web_contents) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SessionID::IdForWindowContainingTab(web_contents); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DictionaryValue* ExtensionTabUtil::CreateTabValue( 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebContents* contents, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* tab_strip, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_index, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we have a matching ShellWindow with a controller, get the tab value 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from its controller instead. 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::WindowController* controller = GetShellWindowController(contents); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (controller && 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (!extension || controller->IsVisibleToExtension(extension))) { 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return controller->CreateTabValue(extension, tab_index); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DictionaryValue *result = CreateTabValue(contents, tab_strip, tab_index); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScrubTabValueForExtension(contents, extension, result); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return result; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::ListValue* ExtensionTabUtil::CreateTabList( 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Browser* browser, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ListValue* tab_list = new base::ListValue(); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* tab_strip = browser->tab_strip_model(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < tab_strip->count(); ++i) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_list->Append(CreateTabValue(tab_strip->GetWebContentsAt(i), 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension)); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return tab_list; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DictionaryValue* ExtensionTabUtil::CreateTabValue( 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebContents* contents, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* tab_strip, 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int tab_index) { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we have a matching ShellWindow with a controller, get the tab value 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from its controller instead. 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::WindowController* controller = GetShellWindowController(contents); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (controller) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return controller->CreateTabValue(NULL, tab_index); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tab_strip) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* result = new DictionaryValue(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_loading = contents->IsLoading(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetInteger(keys::kIdKey, GetTabId(contents)); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetInteger(keys::kIndexKey, tab_index); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetInteger(keys::kWindowIdKey, GetWindowIdOfTab(contents)); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetString(keys::kStatusKey, GetTabStatusText(is_loading)); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetBoolean(keys::kActiveKey, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip && tab_index == tab_strip->active_index()); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetBoolean(keys::kSelectedKey, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip && tab_index == tab_strip->active_index()); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetBoolean(keys::kHighlightedKey, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip && tab_strip->IsTabSelected(tab_index)); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetBoolean(keys::kPinnedKey, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip && tab_strip->IsTabPinned(tab_index)); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetBoolean(keys::kIncognitoKey, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->GetBrowserContext()->IsOffTheRecord()); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Privacy-sensitive fields: these should be stripped off by 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ScrubTabValueForExtension if the extension should not see them. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->SetString(keys::kUrlKey, contents->GetURL().spec()); 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->SetString(keys::kTitleKey, contents->GetTitle()); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_loading) { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NavigationEntry* entry = contents->GetController().GetActiveEntry(); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry && entry->GetFavicon().valid) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->SetString(keys::kFaviconUrlKey, entry->GetFavicon().url.spec()); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_strip) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* opener = tab_strip->GetOpenerOfWebContentsAt(tab_index); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opener) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetInteger(keys::kOpenerTabIdKey, GetTabId(opener)); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionTabUtil::ScrubTabValueForExtension(const WebContents* contents, 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension, 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DictionaryValue* tab_info) { 17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool has_permission = 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension && 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extensions::PermissionsData::HasAPIPermissionForTab( 17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension, GetTabId(contents), APIPermission::kTab); 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_permission) { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_info->Remove(keys::kUrlKey, NULL); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_info->Remove(keys::kTitleKey, NULL); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_info->Remove(keys::kFaviconUrlKey, NULL); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionTabUtil::ScrubTabForExtension(const Extension* extension, 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tabs::Tab* tab) { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool has_permission = extension && extension->HasAPIPermission( 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) APIPermission::kTab); 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_permission) { 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab->url.reset(); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab->title.reset(); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab->fav_icon_url.reset(); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionTabUtil::GetTabStripModel(const WebContents* web_contents, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel** tab_strip_model, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* tab_index) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(web_contents); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(tab_strip_model); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(tab_index); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (chrome::BrowserIterator it; !it.done(); it.Next()) { 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabStripModel* tab_strip = it->tab_strip_model(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = tab_strip->GetIndexOfWebContents(web_contents); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != -1) { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_strip_model = tab_strip; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_index = index; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionTabUtil::GetDefaultTab(Browser* browser, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents** contents, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* tab_id) { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(browser); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(contents); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *contents = browser->tab_strip_model()->GetActiveWebContents(); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*contents) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_id) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_id = GetTabId(*contents); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionTabUtil::GetTabById(int tab_id, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool include_incognito, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser** browser, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel** tab_strip, 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents** contents, 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* tab_index) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* incognito_profile = 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) include_incognito && profile->HasOffTheRecordProfile() ? 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile->GetOffTheRecordProfile() : NULL; 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (chrome::BrowserIterator it; !it.done(); it.Next()) { 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* target_browser = *it; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target_browser->profile() == profile || 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_browser->profile() == incognito_profile) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* target_tab_strip = target_browser->tab_strip_model(); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < target_tab_strip->count(); ++i) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* target_contents = target_tab_strip->GetWebContentsAt(i); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SessionID::IdForTab(target_contents) == tab_id) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser = target_browser; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_strip) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_strip = target_tab_strip; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *contents = target_contents; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_index) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_index = i; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL ExtensionTabUtil::ResolvePossiblyRelativeURL(const std::string& url_string, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::Extension* extension) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url = GURL(url_string); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.is_valid()) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url = extension->GetResourceURL(url_string); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return url; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionTabUtil::IsCrashURL(const GURL& url) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check a fixed-up URL, to normalize the scheme and parse hosts correctly. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL fixed_url = 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLFixerUpper::FixupURL(url.possibly_invalid_spec(), std::string()); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (fixed_url.SchemeIs(chrome::kChromeUIScheme) && 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (fixed_url.host() == content::kChromeUIBrowserCrashHost || 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fixed_url.host() == chrome::kChromeUICrashHost)); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionTabUtil::CreateTab(WebContents* web_contents, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WindowOpenDisposition disposition, 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& initial_pos, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool user_gesture) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile::FromBrowserContext(web_contents->GetBrowserContext()); 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop(); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* browser = chrome::FindTabbedBrowser(profile, false, active_desktop); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool browser_created = !browser; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!browser) 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser = new Browser(Browser::CreateParams(profile, active_desktop)); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::NavigateParams params(browser, web_contents); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The extension_app_id parameter ends up as app_name in the Browser 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which causes the Browser to return true for is_app(). This affects 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // among other things, whether the location bar gets displayed. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mpcomplete): This seems wrong. What if the extension content is hosted 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in a tab? 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (disposition == NEW_POPUP) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.extension_app_id = extension_id; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.disposition = disposition; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.window_bounds = initial_pos; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.window_action = chrome::NavigateParams::SHOW_WINDOW; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.user_gesture = user_gesture; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::Navigate(¶ms); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close the browser if chrome::Navigate created a new one. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_created && (browser != params.browser)) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser->window()->Close(); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionTabUtil::ForEachTab( 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Callback<void(WebContents*)>& callback) { 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (TabContentsIterator iterator; !iterator.done(); iterator.Next()) 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(*iterator); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extensions::WindowController* ExtensionTabUtil::GetWindowControllerOfTab( 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebContents* web_contents) { 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* browser = chrome::FindBrowserWithWebContents(web_contents); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser != NULL) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browser->extension_window_controller(); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExtensionTabUtil::OpenOptionsPage(const Extension* extension, 333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Browser* browser) { 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!extensions::ManifestURL::GetOptionsPage(extension).is_empty()); 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Force the options page to open in non-OTR window, because it won't be 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // able to save settings from OTR. 338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (browser->profile()->IsOffTheRecord()) { 339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser = chrome::FindOrCreateTabbedBrowser( 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser->profile()->GetOriginalProfile(), browser->host_desktop_type()); 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::OpenURLParams params( 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extensions::ManifestURL::GetOptionsPage(extension), 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::Referrer(), SINGLETON_TAB, 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::PAGE_TRANSITION_LINK, false); 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser->OpenURL(params); 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser->window()->Show(); 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebContents* web_contents = 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser->tab_strip_model()->GetActiveWebContents(); 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) web_contents->GetDelegate()->ActivateContents(web_contents); 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 353