extension_tab_util.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/extensions/extension_tab_util.h" 6 7#include "chrome/browser/extensions/api/tabs/tabs_constants.h" 8#include "chrome/browser/extensions/tab_helper.h" 9#include "chrome/browser/extensions/window_controller.h" 10#include "chrome/browser/net/url_fixer_upper.h" 11#include "chrome/browser/profiles/profile.h" 12#include "chrome/browser/sessions/session_id.h" 13#include "chrome/browser/ui/browser.h" 14#include "chrome/browser/ui/browser_finder.h" 15#include "chrome/browser/ui/browser_list.h" 16#include "chrome/browser/ui/browser_tabstrip.h" 17#include "chrome/browser/ui/browser_window.h" 18#include "chrome/browser/ui/tab_contents/tab_contents.h" 19#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" 20#include "chrome/browser/ui/tabs/tab_strip_model.h" 21#include "chrome/common/extensions/extension.h" 22#include "chrome/common/extensions/extension_manifest_constants.h" 23#include "chrome/common/extensions/permissions/api_permission.h" 24#include "chrome/common/url_constants.h" 25#include "content/public/browser/favicon_status.h" 26#include "content/public/browser/navigation_entry.h" 27#include "content/public/browser/web_contents.h" 28#include "googleurl/src/gurl.h" 29 30namespace keys = extensions::tabs_constants; 31 32using content::NavigationEntry; 33using content::WebContents; 34using extensions::APIPermission; 35using extensions::Extension; 36 37int ExtensionTabUtil::GetWindowId(const Browser* browser) { 38 return browser->session_id().id(); 39} 40 41int ExtensionTabUtil::GetWindowIdOfTabStripModel( 42 const TabStripModel* tab_strip_model) { 43 for (BrowserList::const_iterator it = BrowserList::begin(); 44 it != BrowserList::end(); ++it) { 45 if ((*it)->tab_strip_model() == tab_strip_model) 46 return GetWindowId(*it); 47 } 48 return -1; 49} 50 51int ExtensionTabUtil::GetTabId(const WebContents* web_contents) { 52 return SessionID::IdForTab(web_contents); 53} 54 55std::string ExtensionTabUtil::GetTabStatusText(bool is_loading) { 56 return is_loading ? keys::kStatusValueLoading : keys::kStatusValueComplete; 57} 58 59int ExtensionTabUtil::GetWindowIdOfTab(const WebContents* web_contents) { 60 return SessionID::IdForWindowContainingTab(web_contents); 61} 62 63DictionaryValue* ExtensionTabUtil::CreateTabValue( 64 const WebContents* contents, 65 TabStripModel* tab_strip, 66 int tab_index, 67 const Extension* extension) { 68 // Only add privacy-sensitive data if the requesting extension has the tabs 69 // permission. 70 bool has_permission = extension && extension->HasAPIPermissionForTab( 71 GetTabId(contents), APIPermission::kTab); 72 73 return CreateTabValue(contents, tab_strip, tab_index, 74 has_permission ? INCLUDE_PRIVACY_SENSITIVE_FIELDS : 75 OMIT_PRIVACY_SENSITIVE_FIELDS); 76} 77 78ListValue* ExtensionTabUtil::CreateTabList( 79 const Browser* browser, 80 const Extension* extension) { 81 ListValue* tab_list = new ListValue(); 82 TabStripModel* tab_strip = browser->tab_strip_model(); 83 for (int i = 0; i < tab_strip->count(); ++i) { 84 tab_list->Append(CreateTabValue(tab_strip->GetWebContentsAt(i), 85 tab_strip, 86 i, 87 extension)); 88 } 89 90 return tab_list; 91} 92 93DictionaryValue* ExtensionTabUtil::CreateTabValue( 94 const WebContents* contents, 95 TabStripModel* tab_strip, 96 int tab_index, 97 IncludePrivacySensitiveFields include_privacy_sensitive_fields) { 98 if (!tab_strip) 99 ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index); 100 101 DictionaryValue* result = new DictionaryValue(); 102 bool is_loading = contents->IsLoading(); 103 result->SetInteger(keys::kIdKey, GetTabId(contents)); 104 result->SetInteger(keys::kIndexKey, tab_index); 105 result->SetInteger(keys::kWindowIdKey, GetWindowIdOfTab(contents)); 106 result->SetString(keys::kStatusKey, GetTabStatusText(is_loading)); 107 result->SetBoolean(keys::kActiveKey, 108 tab_strip && tab_index == tab_strip->active_index()); 109 result->SetBoolean(keys::kSelectedKey, 110 tab_strip && tab_index == tab_strip->active_index()); 111 result->SetBoolean(keys::kHighlightedKey, 112 tab_strip && tab_strip->IsTabSelected(tab_index)); 113 result->SetBoolean(keys::kPinnedKey, 114 tab_strip && tab_strip->IsTabPinned(tab_index)); 115 result->SetBoolean(keys::kIncognitoKey, 116 contents->GetBrowserContext()->IsOffTheRecord()); 117 118 if (include_privacy_sensitive_fields == INCLUDE_PRIVACY_SENSITIVE_FIELDS) { 119 result->SetString(keys::kUrlKey, contents->GetURL().spec()); 120 result->SetString(keys::kTitleKey, contents->GetTitle()); 121 if (!is_loading) { 122 NavigationEntry* entry = contents->GetController().GetActiveEntry(); 123 if (entry && entry->GetFavicon().valid) 124 result->SetString(keys::kFaviconUrlKey, entry->GetFavicon().url.spec()); 125 } 126 } 127 128 if (tab_strip) { 129 WebContents* opener = tab_strip->GetOpenerOfWebContentsAt(tab_index); 130 if (opener) 131 result->SetInteger(keys::kOpenerTabIdKey, GetTabId(opener)); 132 } 133 134 return result; 135} 136 137bool ExtensionTabUtil::GetTabStripModel(const WebContents* web_contents, 138 TabStripModel** tab_strip_model, 139 int* tab_index) { 140 DCHECK(web_contents); 141 DCHECK(tab_strip_model); 142 DCHECK(tab_index); 143 144 for (BrowserList::const_iterator it = BrowserList::begin(); 145 it != BrowserList::end(); ++it) { 146 TabStripModel* tab_strip = (*it)->tab_strip_model(); 147 int index = tab_strip->GetIndexOfWebContents(web_contents); 148 if (index != -1) { 149 *tab_strip_model = tab_strip; 150 *tab_index = index; 151 return true; 152 } 153 } 154 155 return false; 156} 157 158bool ExtensionTabUtil::GetDefaultTab(Browser* browser, 159 WebContents** contents, 160 int* tab_id) { 161 DCHECK(browser); 162 DCHECK(contents); 163 164 *contents = chrome::GetActiveWebContents(browser); 165 if (*contents) { 166 if (tab_id) 167 *tab_id = GetTabId(*contents); 168 return true; 169 } 170 171 return false; 172} 173 174bool ExtensionTabUtil::GetTabById(int tab_id, 175 Profile* profile, 176 bool include_incognito, 177 Browser** browser, 178 TabStripModel** tab_strip, 179 WebContents** contents, 180 int* tab_index) { 181 Profile* incognito_profile = 182 include_incognito && profile->HasOffTheRecordProfile() ? 183 profile->GetOffTheRecordProfile() : NULL; 184 for (BrowserList::const_iterator iter = BrowserList::begin(); 185 iter != BrowserList::end(); ++iter) { 186 Browser* target_browser = *iter; 187 if (target_browser->profile() == profile || 188 target_browser->profile() == incognito_profile) { 189 TabStripModel* target_tab_strip = target_browser->tab_strip_model(); 190 for (int i = 0; i < target_tab_strip->count(); ++i) { 191 WebContents* target_contents = target_tab_strip->GetWebContentsAt(i); 192 if (SessionID::IdForTab(target_contents) == tab_id) { 193 if (browser) 194 *browser = target_browser; 195 if (tab_strip) 196 *tab_strip = target_tab_strip; 197 if (contents) 198 *contents = target_contents; 199 if (tab_index) 200 *tab_index = i; 201 return true; 202 } 203 } 204 } 205 } 206 return false; 207} 208 209GURL ExtensionTabUtil::ResolvePossiblyRelativeURL(const std::string& url_string, 210 const extensions::Extension* extension) { 211 GURL url = GURL(url_string); 212 if (!url.is_valid()) 213 url = extension->GetResourceURL(url_string); 214 215 return url; 216} 217 218bool ExtensionTabUtil::IsCrashURL(const GURL& url) { 219 // Check a fixed-up URL, to normalize the scheme and parse hosts correctly. 220 GURL fixed_url = 221 URLFixerUpper::FixupURL(url.possibly_invalid_spec(), std::string()); 222 return (fixed_url.SchemeIs(chrome::kChromeUIScheme) && 223 (fixed_url.host() == chrome::kChromeUIBrowserCrashHost || 224 fixed_url.host() == chrome::kChromeUICrashHost)); 225} 226 227void ExtensionTabUtil::CreateTab(WebContents* web_contents, 228 const std::string& extension_id, 229 WindowOpenDisposition disposition, 230 const gfx::Rect& initial_pos, 231 bool user_gesture) { 232 Profile* profile = 233 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 234 Browser* browser = browser::FindTabbedBrowserDeprecated(profile, false); 235 const bool browser_created = !browser; 236 if (!browser) 237 browser = new Browser(Browser::CreateParams(profile)); 238 TabContents* tab_contents = 239 TabContents::Factory::CreateTabContents(web_contents); 240 chrome::NavigateParams params(browser, tab_contents); 241 242 // The extension_app_id parameter ends up as app_name in the Browser 243 // which causes the Browser to return true for is_app(). This affects 244 // among other things, whether the location bar gets displayed. 245 // TODO(mpcomplete): This seems wrong. What if the extension content is hosted 246 // in a tab? 247 if (disposition == NEW_POPUP) 248 params.extension_app_id = extension_id; 249 250 params.disposition = disposition; 251 params.window_bounds = initial_pos; 252 params.window_action = chrome::NavigateParams::SHOW_WINDOW; 253 params.user_gesture = user_gesture; 254 chrome::Navigate(¶ms); 255 256 // Close the browser if chrome::Navigate created a new one. 257 if (browser_created && (browser != params.browser)) 258 browser->window()->Close(); 259} 260 261// static 262void ExtensionTabUtil::ForEachTab( 263 const base::Callback<void(WebContents*)>& callback) { 264 for (TabContentsIterator iterator; !iterator.done(); ++iterator) 265 callback.Run((*iterator)->web_contents()); 266} 267 268// static 269extensions::WindowController* ExtensionTabUtil::GetWindowControllerOfTab( 270 const WebContents* web_contents) { 271 Browser* browser = browser::FindBrowserWithWebContents(web_contents); 272 if (browser != NULL) 273 return browser->extension_window_controller(); 274 275 return NULL; 276} 277