extension_tab_util.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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" 8ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "apps/shell_window_registry.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/tabs/tabs_constants.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/profiles/profile.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_id.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/manifest_url_handler.h" 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/extensions/permissions/permissions_data.h" 24558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/common/net/url_fixer_upper.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/favicon_status.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/browser/web_contents_view.h" 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h" 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "extensions/common/permissions/api_permission.h" 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace keys = extensions::tabs_constants; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace tabs = extensions::api::tabs; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing apps::ShellWindow; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::APIPermission; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extensions::WindowController* GetShellWindowController( 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const WebContents* contents) { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 48ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch apps::ShellWindowRegistry* registry = 49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch apps::ShellWindowRegistry::Get(profile); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!registry) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShellWindow* shell_window = 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->GetShellWindowForRenderViewHost(contents->GetRenderViewHost()); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!shell_window) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return extensions::WindowControllerList::GetInstance()-> 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FindWindowById(shell_window->session_id().id()); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionTabUtil::GetWindowId(const Browser* browser) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browser->session_id().id(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionTabUtil::GetWindowIdOfTabStripModel( 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TabStripModel* tab_strip_model) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (chrome::BrowserIterator it; !it.done(); it.Next()) { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->tab_strip_model() == tab_strip_model) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetWindowId(*it); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionTabUtil::GetTabId(const WebContents* web_contents) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SessionID::IdForTab(web_contents); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ExtensionTabUtil::GetTabStatusText(bool is_loading) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_loading ? keys::kStatusValueLoading : keys::kStatusValueComplete; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionTabUtil::GetWindowIdOfTab(const WebContents* web_contents) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SessionID::IdForWindowContainingTab(web_contents); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DictionaryValue* ExtensionTabUtil::CreateTabValue( 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebContents* contents, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* tab_strip, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_index, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we have a matching ShellWindow with a controller, get the tab value 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from its controller instead. 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::WindowController* controller = GetShellWindowController(contents); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (controller && 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (!extension || controller->IsVisibleToExtension(extension))) { 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return controller->CreateTabValue(extension, tab_index); 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DictionaryValue *result = CreateTabValue(contents, tab_strip, tab_index); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScrubTabValueForExtension(contents, extension, result); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return result; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::ListValue* ExtensionTabUtil::CreateTabList( 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Browser* browser, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ListValue* tab_list = new base::ListValue(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* tab_strip = browser->tab_strip_model(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < tab_strip->count(); ++i) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_list->Append(CreateTabValue(tab_strip->GetWebContentsAt(i), 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension)); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return tab_list; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DictionaryValue* ExtensionTabUtil::CreateTabValue( 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebContents* contents, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* tab_strip, 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int tab_index) { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we have a matching ShellWindow with a controller, get the tab value 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from its controller instead. 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::WindowController* controller = GetShellWindowController(contents); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (controller) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return controller->CreateTabValue(NULL, tab_index); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tab_strip) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* result = new DictionaryValue(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_loading = contents->IsLoading(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetInteger(keys::kIdKey, GetTabId(contents)); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetInteger(keys::kIndexKey, tab_index); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetInteger(keys::kWindowIdKey, GetWindowIdOfTab(contents)); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetString(keys::kStatusKey, GetTabStatusText(is_loading)); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetBoolean(keys::kActiveKey, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip && tab_index == tab_strip->active_index()); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetBoolean(keys::kSelectedKey, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip && tab_index == tab_strip->active_index()); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetBoolean(keys::kHighlightedKey, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip && tab_strip->IsTabSelected(tab_index)); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetBoolean(keys::kPinnedKey, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_strip && tab_strip->IsTabPinned(tab_index)); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetBoolean(keys::kIncognitoKey, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->GetBrowserContext()->IsOffTheRecord()); 1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) result->SetInteger(keys::kWidthKey, 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) contents->GetView()->GetContainerSize().width()); 1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) result->SetInteger(keys::kHeightKey, 1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) contents->GetView()->GetContainerSize().height()); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Privacy-sensitive fields: these should be stripped off by 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ScrubTabValueForExtension if the extension should not see them. 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->SetString(keys::kUrlKey, contents->GetURL().spec()); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->SetString(keys::kTitleKey, contents->GetTitle()); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_loading) { 1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NavigationEntry* entry = contents->GetController().GetVisibleEntry(); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry && entry->GetFavicon().valid) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->SetString(keys::kFaviconUrlKey, entry->GetFavicon().url.spec()); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_strip) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* opener = tab_strip->GetOpenerOfWebContentsAt(tab_index); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opener) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetInteger(keys::kOpenerTabIdKey, GetTabId(opener)); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionTabUtil::ScrubTabValueForExtension(const WebContents* contents, 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension, 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DictionaryValue* tab_info) { 17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool has_permission = 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension && 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extensions::PermissionsData::HasAPIPermissionForTab( 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension, GetTabId(contents), APIPermission::kTab); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_permission) { 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_info->Remove(keys::kUrlKey, NULL); 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_info->Remove(keys::kTitleKey, NULL); 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_info->Remove(keys::kFaviconUrlKey, NULL); 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionTabUtil::ScrubTabForExtension(const Extension* extension, 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tabs::Tab* tab) { 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool has_permission = extension && extension->HasAPIPermission( 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) APIPermission::kTab); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_permission) { 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab->url.reset(); 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab->title.reset(); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab->fav_icon_url.reset(); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionTabUtil::GetTabStripModel(const WebContents* web_contents, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel** tab_strip_model, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* tab_index) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(web_contents); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(tab_strip_model); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(tab_index); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (chrome::BrowserIterator it; !it.done(); it.Next()) { 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabStripModel* tab_strip = it->tab_strip_model(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = tab_strip->GetIndexOfWebContents(web_contents); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != -1) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_strip_model = tab_strip; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_index = index; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionTabUtil::GetDefaultTab(Browser* browser, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents** contents, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* tab_id) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(browser); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(contents); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *contents = browser->tab_strip_model()->GetActiveWebContents(); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*contents) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_id) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_id = GetTabId(*contents); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionTabUtil::GetTabById(int tab_id, 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool include_incognito, 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser** browser, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel** tab_strip, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents** contents, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* tab_index) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* incognito_profile = 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) include_incognito && profile->HasOffTheRecordProfile() ? 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile->GetOffTheRecordProfile() : NULL; 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (chrome::BrowserIterator it; !it.done(); it.Next()) { 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* target_browser = *it; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target_browser->profile() == profile || 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_browser->profile() == incognito_profile) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* target_tab_strip = target_browser->tab_strip_model(); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < target_tab_strip->count(); ++i) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* target_contents = target_tab_strip->GetWebContentsAt(i); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SessionID::IdForTab(target_contents) == tab_id) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser = target_browser; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_strip) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_strip = target_tab_strip; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *contents = target_contents; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_index) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_index = i; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL ExtensionTabUtil::ResolvePossiblyRelativeURL(const std::string& url_string, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::Extension* extension) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url = GURL(url_string); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.is_valid()) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url = extension->GetResourceURL(url_string); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return url; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionTabUtil::IsCrashURL(const GURL& url) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check a fixed-up URL, to normalize the scheme and parse hosts correctly. 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL fixed_url = 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLFixerUpper::FixupURL(url.possibly_invalid_spec(), std::string()); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (fixed_url.SchemeIs(chrome::kChromeUIScheme) && 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (fixed_url.host() == content::kChromeUIBrowserCrashHost || 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fixed_url.host() == chrome::kChromeUICrashHost)); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionTabUtil::CreateTab(WebContents* web_contents, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WindowOpenDisposition disposition, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& initial_pos, 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool user_gesture) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile::FromBrowserContext(web_contents->GetBrowserContext()); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop(); 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* browser = chrome::FindTabbedBrowser(profile, false, active_desktop); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool browser_created = !browser; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!browser) 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser = new Browser(Browser::CreateParams(profile, active_desktop)); 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::NavigateParams params(browser, web_contents); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The extension_app_id parameter ends up as app_name in the Browser 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which causes the Browser to return true for is_app(). This affects 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // among other things, whether the location bar gets displayed. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mpcomplete): This seems wrong. What if the extension content is hosted 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in a tab? 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (disposition == NEW_POPUP) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.extension_app_id = extension_id; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.disposition = disposition; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.window_bounds = initial_pos; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.window_action = chrome::NavigateParams::SHOW_WINDOW; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.user_gesture = user_gesture; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::Navigate(¶ms); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close the browser if chrome::Navigate created a new one. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_created && (browser != params.browser)) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser->window()->Close(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionTabUtil::ForEachTab( 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Callback<void(WebContents*)>& callback) { 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (TabContentsIterator iterator; !iterator.done(); iterator.Next()) 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(*iterator); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extensions::WindowController* ExtensionTabUtil::GetWindowControllerOfTab( 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebContents* web_contents) { 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* browser = chrome::FindBrowserWithWebContents(web_contents); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser != NULL) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browser->extension_window_controller(); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExtensionTabUtil::OpenOptionsPage(const Extension* extension, 338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Browser* browser) { 339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!extensions::ManifestURL::GetOptionsPage(extension).is_empty()); 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Force the options page to open in non-OTR window, because it won't be 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // able to save settings from OTR. 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (browser->profile()->IsOffTheRecord()) { 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser = chrome::FindOrCreateTabbedBrowser( 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser->profile()->GetOriginalProfile(), browser->host_desktop_type()); 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::OpenURLParams params( 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extensions::ManifestURL::GetOptionsPage(extension), 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::Referrer(), SINGLETON_TAB, 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::PAGE_TRANSITION_LINK, false); 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser->OpenURL(params); 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser->window()->Show(); 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebContents* web_contents = 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) browser->tab_strip_model()->GetActiveWebContents(); 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) web_contents->GetDelegate()->ActivateContents(web_contents); 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 358