blob: a5602ac1e8e43635a713db3c05f95697e1ef6357 [file] [log] [blame]
[email protected]327640a2012-01-24 21:57:591// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ac84431b2011-09-27 17:26:112// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]ac84431b2011-09-27 17:26:115#include "chrome/browser/extensions/extension_tab_util.h"
[email protected]41d9faf2012-02-28 23:46:026
[email protected]98528302014-05-02 00:34:087#include "base/strings/string_number_conversions.h"
ericzengf97b7c22014-08-26 03:07:308#include "base/strings/stringprintf.h"
[email protected]b19451b2012-06-08 17:36:199#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
[email protected]98528302014-05-02 00:34:0810#include "chrome/browser/extensions/chrome_extension_function.h"
[email protected]e9570fdf2012-07-18 20:01:2111#include "chrome/browser/extensions/tab_helper.h"
12#include "chrome/browser/extensions/window_controller.h"
[email protected]f1c102b2013-02-15 07:44:1213#include "chrome/browser/extensions/window_controller_list.h"
[email protected]b56e2e32012-05-11 21:18:0414#include "chrome/browser/profiles/profile.h"
[email protected]e3f90c602014-08-18 12:41:5915#include "chrome/browser/sessions/session_tab_helper.h"
[email protected]b56e2e32012-05-11 21:18:0416#include "chrome/browser/ui/browser.h"
[email protected]73c1a6842012-07-13 17:39:0417#include "chrome/browser/ui/browser_finder.h"
[email protected]3539929f2013-02-01 05:59:1418#include "chrome/browser/ui/browser_iterator.h"
[email protected]b56e2e32012-05-11 21:18:0419#include "chrome/browser/ui/browser_window.h"
[email protected]0edcdec2013-10-31 06:43:0820#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
ericzengf97b7c22014-08-26 03:07:3021#include "chrome/browser/ui/singleton_tabs.h"
[email protected]44e329a2012-07-14 01:13:0622#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
[email protected]b56e2e32012-05-11 21:18:0423#include "chrome/browser/ui/tabs/tab_strip_model.h"
[email protected]760f6032014-06-30 23:18:1924#include "chrome/common/extensions/api/tabs.h"
[email protected]695089782013-04-09 16:03:1725#include "chrome/common/extensions/manifest_url_handler.h"
[email protected]45c75e62012-03-21 19:56:3526#include "chrome/common/url_constants.h"
[email protected]9b5b1d602014-06-12 14:29:0227#include "components/url_fixer/url_fixer.h"
[email protected]ad23a092011-12-28 07:02:0428#include "content/public/browser/favicon_status.h"
29#include "content/public/browser/navigation_entry.h"
[email protected]6acde6352012-01-04 16:52:2030#include "content/public/browser/web_contents.h"
hashimotoad3c6872014-08-29 09:46:5731#include "extensions/browser/app_window/app_window.h"
32#include "extensions/browser/app_window/app_window_registry.h"
[email protected]98528302014-05-02 00:34:0833#include "extensions/common/constants.h"
34#include "extensions/common/error_utils.h"
[email protected]e4452d32013-11-15 23:07:4135#include "extensions/common/extension.h"
ericzengf97b7c22014-08-26 03:07:3036#include "extensions/common/feature_switch.h"
[email protected]0c3c9732013-09-16 08:53:4137#include "extensions/common/manifest_constants.h"
[email protected]98528302014-05-02 00:34:0838#include "extensions/common/manifest_handlers/incognito_info.h"
[email protected]793964a2013-10-08 00:47:1939#include "extensions/common/permissions/api_permission.h"
[email protected]e4452d32013-11-15 23:07:4140#include "extensions/common/permissions/permissions_data.h"
[email protected]a6483d22013-07-03 22:11:0041#include "url/gurl.h"
[email protected]ac84431b2011-09-27 17:26:1142
[email protected]10f417c52011-12-28 21:04:2343using content::NavigationEntry;
[email protected]26b5e322011-12-23 01:36:4744using content::WebContents;
[email protected]1c4fbc02013-11-13 02:52:4245
46namespace extensions {
[email protected]26b5e322011-12-23 01:36:4747
[email protected]f1c102b2013-02-15 07:44:1248namespace {
49
[email protected]1c4fbc02013-11-13 02:52:4250namespace keys = tabs_constants;
51
[email protected]dbb03fb2014-02-15 05:36:3352WindowController* GetAppWindowController(const WebContents* contents) {
[email protected]f1c102b2013-02-15 07:44:1253 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
hashimotoad3c6872014-08-29 09:46:5754 AppWindowRegistry* registry = AppWindowRegistry::Get(profile);
[email protected]f1c102b2013-02-15 07:44:1255 if (!registry)
56 return NULL;
[email protected]dbb03fb2014-02-15 05:36:3357 AppWindow* app_window =
58 registry->GetAppWindowForRenderViewHost(contents->GetRenderViewHost());
59 if (!app_window)
[email protected]f1c102b2013-02-15 07:44:1260 return NULL;
[email protected]44424542014-01-29 12:10:3161 return WindowControllerList::GetInstance()->FindWindowById(
[email protected]dbb03fb2014-02-15 05:36:3362 app_window->session_id().id());
[email protected]f1c102b2013-02-15 07:44:1263}
64
[email protected]98528302014-05-02 00:34:0865// |error_message| can optionally be passed in and will be set with an
66// appropriate message if the window cannot be found by id.
67Browser* GetBrowserInProfileWithId(Profile* profile,
68 const int window_id,
69 bool include_incognito,
70 std::string* error_message) {
71 Profile* incognito_profile =
72 include_incognito && profile->HasOffTheRecordProfile()
73 ? profile->GetOffTheRecordProfile()
74 : NULL;
75 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
76 Browser* browser = *it;
77 if ((browser->profile() == profile ||
78 browser->profile() == incognito_profile) &&
79 ExtensionTabUtil::GetWindowId(browser) == window_id &&
80 browser->window()) {
81 return browser;
82 }
83 }
84
85 if (error_message)
86 *error_message = ErrorUtils::FormatErrorMessage(
87 keys::kWindowNotFoundError, base::IntToString(window_id));
88
89 return NULL;
90}
91
[email protected]a0c91a9f2014-05-03 03:41:4392Browser* CreateBrowser(ChromeUIThreadExtensionFunction* function,
[email protected]98528302014-05-02 00:34:0893 int window_id,
94 std::string* error) {
95 content::WebContents* web_contents = function->GetAssociatedWebContents();
96 DCHECK(web_contents);
[email protected]fc2b46b2014-05-03 16:33:4597 DCHECK(web_contents->GetNativeView());
[email protected]98528302014-05-02 00:34:0898 DCHECK(!chrome::FindBrowserWithWebContents(web_contents));
99
100 chrome::HostDesktopType desktop_type =
[email protected]fc2b46b2014-05-03 16:33:45101 chrome::GetHostDesktopTypeForNativeView(web_contents->GetNativeView());
[email protected]98528302014-05-02 00:34:08102 Browser::CreateParams params(
103 Browser::TYPE_TABBED, function->GetProfile(), desktop_type);
104 Browser* browser = new Browser(params);
105 browser->window()->Show();
106 return browser;
107}
108
[email protected]f1c102b2013-02-15 07:44:12109} // namespace
110
[email protected]98528302014-05-02 00:34:08111ExtensionTabUtil::OpenTabParams::OpenTabParams()
112 : create_browser_if_needed(false) {
113}
114
115ExtensionTabUtil::OpenTabParams::~OpenTabParams() {
116}
117
118// Opens a new tab for a given extension. Returns NULL and sets |error| if an
119// error occurs.
120base::DictionaryValue* ExtensionTabUtil::OpenTab(
[email protected]a0c91a9f2014-05-03 03:41:43121 ChromeUIThreadExtensionFunction* function,
[email protected]98528302014-05-02 00:34:08122 const OpenTabParams& params,
123 std::string* error) {
124 // windowId defaults to "current" window.
125 int window_id = extension_misc::kCurrentWindowId;
126 if (params.window_id.get())
127 window_id = *params.window_id;
128
129 Browser* browser = GetBrowserFromWindowID(function, window_id, error);
130 if (!browser) {
131 if (!params.create_browser_if_needed) {
132 return NULL;
133 }
134 browser = CreateBrowser(function, window_id, error);
135 if (!browser)
136 return NULL;
137 }
138
139 // Ensure the selected browser is tabbed.
140 if (!browser->is_type_tabbed() && browser->IsAttemptingToCloseBrowser())
141 browser = chrome::FindTabbedBrowser(function->GetProfile(),
142 function->include_incognito(),
143 browser->host_desktop_type());
144
145 if (!browser || !browser->window()) {
146 // TODO(rpaquay): Error message?
147 return NULL;
148 }
149
150 // TODO(jstritar): Add a constant, chrome.tabs.TAB_ID_ACTIVE, that
151 // represents the active tab.
152 WebContents* opener = NULL;
153 if (params.opener_tab_id.get()) {
154 int opener_id = *params.opener_tab_id;
155
156 if (!ExtensionTabUtil::GetTabById(opener_id,
157 function->GetProfile(),
158 function->include_incognito(),
159 NULL,
160 NULL,
161 &opener,
162 NULL)) {
163 // TODO(rpaquay): Error message?
164 return NULL;
165 }
166 }
167
168 // TODO(rafaelw): handle setting remaining tab properties:
169 // -title
170 // -favIconUrl
171
[email protected]98528302014-05-02 00:34:08172 GURL url;
173 if (params.url.get()) {
[email protected]f5ec3c922014-05-22 15:04:03174 std::string url_string= *params.url;
[email protected]eba8f7d2014-07-28 22:09:23175 url = ExtensionTabUtil::ResolvePossiblyRelativeURL(url_string,
176 function->extension());
[email protected]98528302014-05-02 00:34:08177 if (!url.is_valid()) {
178 *error =
179 ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, url_string);
180 return NULL;
181 }
[email protected]f5ec3c922014-05-22 15:04:03182 } else {
183 url = GURL(chrome::kChromeUINewTabURL);
[email protected]98528302014-05-02 00:34:08184 }
185
186 // Don't let extensions crash the browser or renderers.
187 if (ExtensionTabUtil::IsCrashURL(url)) {
188 *error = keys::kNoCrashBrowserError;
189 return NULL;
190 }
191
192 // Default to foreground for the new tab. The presence of 'active' property
193 // will override this default.
194 bool active = true;
195 if (params.active.get())
196 active = *params.active;
197
198 // Default to not pinning the tab. Setting the 'pinned' property to true
199 // will override this default.
200 bool pinned = false;
201 if (params.pinned.get())
202 pinned = *params.pinned;
203
204 // We can't load extension URLs into incognito windows unless the extension
205 // uses split mode. Special case to fall back to a tabbed window.
206 if (url.SchemeIs(kExtensionScheme) &&
[email protected]eba8f7d2014-07-28 22:09:23207 !IncognitoInfo::IsSplitMode(function->extension()) &&
[email protected]98528302014-05-02 00:34:08208 browser->profile()->IsOffTheRecord()) {
209 Profile* profile = browser->profile()->GetOriginalProfile();
210 chrome::HostDesktopType desktop_type = browser->host_desktop_type();
211
212 browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
213 if (!browser) {
214 browser = new Browser(
215 Browser::CreateParams(Browser::TYPE_TABBED, profile, desktop_type));
216 browser->window()->Show();
217 }
218 }
219
220 // If index is specified, honor the value, but keep it bound to
221 // -1 <= index <= tab_strip->count() where -1 invokes the default behavior.
222 int index = -1;
223 if (params.index.get())
224 index = *params.index;
225
226 TabStripModel* tab_strip = browser->tab_strip_model();
227
228 index = std::min(std::max(index, -1), tab_strip->count());
229
230 int add_types = active ? TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE;
231 add_types |= TabStripModel::ADD_FORCE_INDEX;
232 if (pinned)
233 add_types |= TabStripModel::ADD_PINNED;
234 chrome::NavigateParams navigate_params(
235 browser, url, content::PAGE_TRANSITION_LINK);
236 navigate_params.disposition =
237 active ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
238 navigate_params.tabstrip_index = index;
239 navigate_params.tabstrip_add_types = add_types;
240 chrome::Navigate(&navigate_params);
241
242 // The tab may have been created in a different window, so make sure we look
243 // at the right tab strip.
244 tab_strip = navigate_params.browser->tab_strip_model();
245 int new_index =
246 tab_strip->GetIndexOfWebContents(navigate_params.target_contents);
247 if (opener)
248 tab_strip->SetOpenerOfWebContentsAt(new_index, opener);
249
250 if (active)
[email protected]fc2b46b2014-05-03 16:33:45251 navigate_params.target_contents->SetInitialFocus();
[email protected]98528302014-05-02 00:34:08252
253 // Return data about the newly created tab.
254 return ExtensionTabUtil::CreateTabValue(navigate_params.target_contents,
255 tab_strip,
256 new_index,
[email protected]eba8f7d2014-07-28 22:09:23257 function->extension());
[email protected]98528302014-05-02 00:34:08258}
259
260Browser* ExtensionTabUtil::GetBrowserFromWindowID(
[email protected]a0c91a9f2014-05-03 03:41:43261 ChromeUIThreadExtensionFunction* function,
[email protected]98528302014-05-02 00:34:08262 int window_id,
263 std::string* error) {
264 if (window_id == extension_misc::kCurrentWindowId) {
265 Browser* result = function->GetCurrentBrowser();
266 if (!result || !result->window()) {
267 if (error)
268 *error = keys::kNoCurrentWindowError;
269 return NULL;
270 }
271 return result;
272 } else {
273 return GetBrowserInProfileWithId(function->GetProfile(),
274 window_id,
275 function->include_incognito(),
276 error);
277 }
278}
279
[email protected]ac84431b2011-09-27 17:26:11280int ExtensionTabUtil::GetWindowId(const Browser* browser) {
281 return browser->session_id().id();
282}
283
[email protected]8c3495c2011-09-28 03:32:30284int ExtensionTabUtil::GetWindowIdOfTabStripModel(
285 const TabStripModel* tab_strip_model) {
[email protected]3539929f2013-02-01 05:59:14286 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
287 if (it->tab_strip_model() == tab_strip_model)
[email protected]8c3495c2011-09-28 03:32:30288 return GetWindowId(*it);
289 }
290 return -1;
291}
292
[email protected]d2bd5fde2014-05-29 02:24:31293int ExtensionTabUtil::GetTabId(const WebContents* web_contents) {
[email protected]e3f90c602014-08-18 12:41:59294 return SessionTabHelper::IdForTab(web_contents);
[email protected]ac84431b2011-09-27 17:26:11295}
296
297std::string ExtensionTabUtil::GetTabStatusText(bool is_loading) {
298 return is_loading ? keys::kStatusValueLoading : keys::kStatusValueComplete;
299}
300
[email protected]ea049a02011-12-25 21:37:09301int ExtensionTabUtil::GetWindowIdOfTab(const WebContents* web_contents) {
[email protected]e3f90c602014-08-18 12:41:59302 return SessionTabHelper::IdForWindowContainingTab(web_contents);
[email protected]ac84431b2011-09-27 17:26:11303}
304
[email protected]023b3d12013-12-23 18:46:49305base::DictionaryValue* ExtensionTabUtil::CreateTabValue(
[email protected]fc2b46b2014-05-03 16:33:45306 WebContents* contents,
[email protected]0c9f3262012-09-17 05:59:06307 TabStripModel* tab_strip,
308 int tab_index,
[email protected]f34706be2012-09-04 07:32:09309 const Extension* extension) {
[email protected]dbb03fb2014-02-15 05:36:33310 // If we have a matching AppWindow with a controller, get the tab value
[email protected]f1c102b2013-02-15 07:44:12311 // from its controller instead.
[email protected]dbb03fb2014-02-15 05:36:33312 WindowController* controller = GetAppWindowController(contents);
[email protected]f1c102b2013-02-15 07:44:12313 if (controller &&
314 (!extension || controller->IsVisibleToExtension(extension))) {
315 return controller->CreateTabValue(extension, tab_index);
316 }
[email protected]44424542014-01-29 12:10:31317 base::DictionaryValue* result =
[email protected]023b3d12013-12-23 18:46:49318 CreateTabValue(contents, tab_strip, tab_index);
[email protected]304fd152013-01-12 16:54:44319 ScrubTabValueForExtension(contents, extension, result);
320 return result;
[email protected]ac84431b2011-09-27 17:26:11321}
322
[email protected]aeca23f2013-06-21 22:34:41323base::ListValue* ExtensionTabUtil::CreateTabList(
[email protected]f34706be2012-09-04 07:32:09324 const Browser* browser,
325 const Extension* extension) {
[email protected]aeca23f2013-06-21 22:34:41326 base::ListValue* tab_list = new base::ListValue();
[email protected]c0849252012-05-12 13:51:27327 TabStripModel* tab_strip = browser->tab_strip_model();
[email protected]ac84431b2011-09-27 17:26:11328 for (int i = 0; i < tab_strip->count(); ++i) {
[email protected]72f67972012-10-30 18:53:28329 tab_list->Append(CreateTabValue(tab_strip->GetWebContentsAt(i),
330 tab_strip,
331 i,
332 extension));
[email protected]ac84431b2011-09-27 17:26:11333 }
334
335 return tab_list;
336}
337
[email protected]023b3d12013-12-23 18:46:49338base::DictionaryValue* ExtensionTabUtil::CreateTabValue(
[email protected]fc2b46b2014-05-03 16:33:45339 WebContents* contents,
[email protected]f34706be2012-09-04 07:32:09340 TabStripModel* tab_strip,
[email protected]304fd152013-01-12 16:54:44341 int tab_index) {
[email protected]dbb03fb2014-02-15 05:36:33342 // If we have a matching AppWindow with a controller, get the tab value
[email protected]f1c102b2013-02-15 07:44:12343 // from its controller instead.
[email protected]dbb03fb2014-02-15 05:36:33344 WindowController* controller = GetAppWindowController(contents);
[email protected]f1c102b2013-02-15 07:44:12345 if (controller)
346 return controller->CreateTabValue(NULL, tab_index);
347
[email protected]0c9f3262012-09-17 05:59:06348 if (!tab_strip)
349 ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index);
350
[email protected]023b3d12013-12-23 18:46:49351 base::DictionaryValue* result = new base::DictionaryValue();
[email protected]ac84431b2011-09-27 17:26:11352 bool is_loading = contents->IsLoading();
[email protected]f34706be2012-09-04 07:32:09353 result->SetInteger(keys::kIdKey, GetTabId(contents));
[email protected]ac84431b2011-09-27 17:26:11354 result->SetInteger(keys::kIndexKey, tab_index);
[email protected]f34706be2012-09-04 07:32:09355 result->SetInteger(keys::kWindowIdKey, GetWindowIdOfTab(contents));
[email protected]ac84431b2011-09-27 17:26:11356 result->SetString(keys::kStatusKey, GetTabStatusText(is_loading));
[email protected]8c3495c2011-09-28 03:32:30357 result->SetBoolean(keys::kActiveKey,
358 tab_strip && tab_index == tab_strip->active_index());
[email protected]ac84431b2011-09-27 17:26:11359 result->SetBoolean(keys::kSelectedKey,
360 tab_strip && tab_index == tab_strip->active_index());
[email protected]8c3495c2011-09-28 03:32:30361 result->SetBoolean(keys::kHighlightedKey,
362 tab_strip && tab_strip->IsTabSelected(tab_index));
[email protected]ac84431b2011-09-27 17:26:11363 result->SetBoolean(keys::kPinnedKey,
364 tab_strip && tab_strip->IsTabPinned(tab_index));
[email protected]ac84431b2011-09-27 17:26:11365 result->SetBoolean(keys::kIncognitoKey,
[email protected]627e0512011-12-21 22:55:30366 contents->GetBrowserContext()->IsOffTheRecord());
[email protected]a16a5a52013-08-16 17:23:35367 result->SetInteger(keys::kWidthKey,
[email protected]fc2b46b2014-05-03 16:33:45368 contents->GetContainerBounds().size().width());
[email protected]a16a5a52013-08-16 17:23:35369 result->SetInteger(keys::kHeightKey,
[email protected]fc2b46b2014-05-03 16:33:45370 contents->GetContainerBounds().size().height());
[email protected]ac84431b2011-09-27 17:26:11371
[email protected]304fd152013-01-12 16:54:44372 // Privacy-sensitive fields: these should be stripped off by
373 // ScrubTabValueForExtension if the extension should not see them.
374 result->SetString(keys::kUrlKey, contents->GetURL().spec());
375 result->SetString(keys::kTitleKey, contents->GetTitle());
376 if (!is_loading) {
[email protected]afe9aba2013-08-16 20:31:34377 NavigationEntry* entry = contents->GetController().GetVisibleEntry();
[email protected]304fd152013-01-12 16:54:44378 if (entry && entry->GetFavicon().valid)
379 result->SetString(keys::kFaviconUrlKey, entry->GetFavicon().url.spec());
[email protected]f34706be2012-09-04 07:32:09380 }
381
[email protected]327640a2012-01-24 21:57:59382 if (tab_strip) {
[email protected]67075402012-10-26 08:26:25383 WebContents* opener = tab_strip->GetOpenerOfWebContentsAt(tab_index);
384 if (opener)
385 result->SetInteger(keys::kOpenerTabIdKey, GetTabId(opener));
[email protected]ac84431b2011-09-27 17:26:11386 }
387
388 return result;
389}
390
[email protected]023b3d12013-12-23 18:46:49391void ExtensionTabUtil::ScrubTabValueForExtension(
[email protected]fc2b46b2014-05-03 16:33:45392 WebContents* contents,
[email protected]023b3d12013-12-23 18:46:49393 const Extension* extension,
394 base::DictionaryValue* tab_info) {
[email protected]a6910e72014-06-06 05:04:36395 bool has_permission = extension &&
396 extension->permissions_data()->HasAPIPermissionForTab(
397 GetTabId(contents), APIPermission::kTab);
[email protected]304fd152013-01-12 16:54:44398
399 if (!has_permission) {
400 tab_info->Remove(keys::kUrlKey, NULL);
401 tab_info->Remove(keys::kTitleKey, NULL);
402 tab_info->Remove(keys::kFaviconUrlKey, NULL);
403 }
404}
405
[email protected]ab3f61412013-01-29 21:55:07406void ExtensionTabUtil::ScrubTabForExtension(const Extension* extension,
[email protected]1c4fbc02013-11-13 02:52:42407 api::tabs::Tab* tab) {
[email protected]076ebeda2014-06-06 21:47:26408 bool has_permission =
409 extension &&
410 extension->permissions_data()->HasAPIPermission(APIPermission::kTab);
[email protected]ab3f61412013-01-29 21:55:07411
412 if (!has_permission) {
413 tab->url.reset();
414 tab->title.reset();
415 tab->fav_icon_url.reset();
416 }
417}
418
[email protected]ea049a02011-12-25 21:37:09419bool ExtensionTabUtil::GetTabStripModel(const WebContents* web_contents,
[email protected]ac84431b2011-09-27 17:26:11420 TabStripModel** tab_strip_model,
421 int* tab_index) {
[email protected]ea049a02011-12-25 21:37:09422 DCHECK(web_contents);
[email protected]ac84431b2011-09-27 17:26:11423 DCHECK(tab_strip_model);
424 DCHECK(tab_index);
425
[email protected]3539929f2013-02-01 05:59:14426 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
427 TabStripModel* tab_strip = it->tab_strip_model();
[email protected]e52d0a42012-06-08 22:44:16428 int index = tab_strip->GetIndexOfWebContents(web_contents);
[email protected]ac84431b2011-09-27 17:26:11429 if (index != -1) {
430 *tab_strip_model = tab_strip;
431 *tab_index = index;
432 return true;
433 }
434 }
435
436 return false;
437}
438
439bool ExtensionTabUtil::GetDefaultTab(Browser* browser,
[email protected]72f67972012-10-30 18:53:28440 WebContents** contents,
[email protected]ac84431b2011-09-27 17:26:11441 int* tab_id) {
442 DCHECK(browser);
443 DCHECK(contents);
444
[email protected]617ee962013-01-29 20:49:12445 *contents = browser->tab_strip_model()->GetActiveWebContents();
[email protected]ac84431b2011-09-27 17:26:11446 if (*contents) {
447 if (tab_id)
[email protected]72f67972012-10-30 18:53:28448 *tab_id = GetTabId(*contents);
[email protected]ac84431b2011-09-27 17:26:11449 return true;
450 }
451
452 return false;
453}
454
455bool ExtensionTabUtil::GetTabById(int tab_id,
wjmaclean5b11eee2014-09-05 00:55:14456 content::BrowserContext* browser_context,
[email protected]ac84431b2011-09-27 17:26:11457 bool include_incognito,
458 Browser** browser,
459 TabStripModel** tab_strip,
[email protected]72f67972012-10-30 18:53:28460 WebContents** contents,
[email protected]ac84431b2011-09-27 17:26:11461 int* tab_index) {
wjmaclean5b11eee2014-09-05 00:55:14462 Profile* profile = Profile::FromBrowserContext(browser_context);
[email protected]ac84431b2011-09-27 17:26:11463 Profile* incognito_profile =
464 include_incognito && profile->HasOffTheRecordProfile() ?
465 profile->GetOffTheRecordProfile() : NULL;
[email protected]3539929f2013-02-01 05:59:14466 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
467 Browser* target_browser = *it;
[email protected]ac84431b2011-09-27 17:26:11468 if (target_browser->profile() == profile ||
469 target_browser->profile() == incognito_profile) {
[email protected]c0849252012-05-12 13:51:27470 TabStripModel* target_tab_strip = target_browser->tab_strip_model();
[email protected]ac84431b2011-09-27 17:26:11471 for (int i = 0; i < target_tab_strip->count(); ++i) {
[email protected]72f67972012-10-30 18:53:28472 WebContents* target_contents = target_tab_strip->GetWebContentsAt(i);
[email protected]e3f90c602014-08-18 12:41:59473 if (SessionTabHelper::IdForTab(target_contents) == tab_id) {
[email protected]ac84431b2011-09-27 17:26:11474 if (browser)
475 *browser = target_browser;
476 if (tab_strip)
477 *tab_strip = target_tab_strip;
478 if (contents)
479 *contents = target_contents;
480 if (tab_index)
481 *tab_index = i;
482 return true;
483 }
484 }
485 }
486 }
487 return false;
488}
[email protected]45c75e62012-03-21 19:56:35489
490GURL ExtensionTabUtil::ResolvePossiblyRelativeURL(const std::string& url_string,
[email protected]1c4fbc02013-11-13 02:52:42491 const Extension* extension) {
[email protected]45c75e62012-03-21 19:56:35492 GURL url = GURL(url_string);
493 if (!url.is_valid())
494 url = extension->GetResourceURL(url_string);
495
496 return url;
497}
498
499bool ExtensionTabUtil::IsCrashURL(const GURL& url) {
500 // Check a fixed-up URL, to normalize the scheme and parse hosts correctly.
501 GURL fixed_url =
[email protected]9b5b1d602014-06-12 14:29:02502 url_fixer::FixupURL(url.possibly_invalid_spec(), std::string());
[email protected]2d9748b22014-02-11 00:17:29503 return (fixed_url.SchemeIs(content::kChromeUIScheme) &&
[email protected]46ed0862013-04-14 02:47:56504 (fixed_url.host() == content::kChromeUIBrowserCrashHost ||
[email protected]45c75e62012-03-21 19:56:35505 fixed_url.host() == chrome::kChromeUICrashHost));
506}
[email protected]73c1a6842012-07-13 17:39:04507
508void ExtensionTabUtil::CreateTab(WebContents* web_contents,
509 const std::string& extension_id,
510 WindowOpenDisposition disposition,
511 const gfx::Rect& initial_pos,
512 bool user_gesture) {
[email protected]73c1a6842012-07-13 17:39:04513 Profile* profile =
514 Profile::FromBrowserContext(web_contents->GetBrowserContext());
[email protected]435d43e02012-12-09 09:13:55515 chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop();
[email protected]75072732013-01-09 13:39:25516 Browser* browser = chrome::FindTabbedBrowser(profile, false, active_desktop);
[email protected]2764cab72012-07-19 17:02:10517 const bool browser_created = !browser;
518 if (!browser)
[email protected]435d43e02012-12-09 09:13:55519 browser = new Browser(Browser::CreateParams(profile, active_desktop));
[email protected]e232c992012-12-06 12:43:20520 chrome::NavigateParams params(browser, web_contents);
[email protected]73c1a6842012-07-13 17:39:04521
522 // The extension_app_id parameter ends up as app_name in the Browser
523 // which causes the Browser to return true for is_app(). This affects
524 // among other things, whether the location bar gets displayed.
525 // TODO(mpcomplete): This seems wrong. What if the extension content is hosted
526 // in a tab?
527 if (disposition == NEW_POPUP)
528 params.extension_app_id = extension_id;
529
[email protected]73c1a6842012-07-13 17:39:04530 params.disposition = disposition;
531 params.window_bounds = initial_pos;
532 params.window_action = chrome::NavigateParams::SHOW_WINDOW;
533 params.user_gesture = user_gesture;
534 chrome::Navigate(&params);
[email protected]2764cab72012-07-19 17:02:10535
536 // Close the browser if chrome::Navigate created a new one.
537 if (browser_created && (browser != params.browser))
538 browser->window()->Close();
[email protected]73c1a6842012-07-13 17:39:04539}
[email protected]44e329a2012-07-14 01:13:06540
541// static
542void ExtensionTabUtil::ForEachTab(
543 const base::Callback<void(WebContents*)>& callback) {
[email protected]b031ff82013-01-29 22:53:16544 for (TabContentsIterator iterator; !iterator.done(); iterator.Next())
[email protected]f8073562012-12-06 12:43:53545 callback.Run(*iterator);
[email protected]44e329a2012-07-14 01:13:06546}
[email protected]e9570fdf2012-07-18 20:01:21547
548// static
[email protected]1c4fbc02013-11-13 02:52:42549WindowController* ExtensionTabUtil::GetWindowControllerOfTab(
[email protected]e9570fdf2012-07-18 20:01:21550 const WebContents* web_contents) {
[email protected]f7b4b9e2012-12-02 07:43:17551 Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
[email protected]e9570fdf2012-07-18 20:01:21552 if (browser != NULL)
553 return browser->extension_window_controller();
554
555 return NULL;
556}
[email protected]695089782013-04-09 16:03:17557
558void ExtensionTabUtil::OpenOptionsPage(const Extension* extension,
559 Browser* browser) {
[email protected]1c4fbc02013-11-13 02:52:42560 DCHECK(!ManifestURL::GetOptionsPage(extension).is_empty());
[email protected]695089782013-04-09 16:03:17561
562 // Force the options page to open in non-OTR window, because it won't be
563 // able to save settings from OTR.
[email protected]0edcdec2013-10-31 06:43:08564 scoped_ptr<chrome::ScopedTabbedBrowserDisplayer> displayer;
[email protected]695089782013-04-09 16:03:17565 if (browser->profile()->IsOffTheRecord()) {
[email protected]0edcdec2013-10-31 06:43:08566 displayer.reset(new chrome::ScopedTabbedBrowserDisplayer(
567 browser->profile()->GetOriginalProfile(),
568 browser->host_desktop_type()));
569 browser = displayer->browser();
[email protected]695089782013-04-09 16:03:17570 }
571
ericzengf97b7c22014-08-26 03:07:30572 if (FeatureSwitch::embedded_extension_options()->IsEnabled()) {
573 // If embedded extension options are enabled, open chrome://extensions
574 // in a new tab and show the extension options in an embedded popup.
575 chrome::NavigateParams params(chrome::GetSingletonTabNavigateParams(
576 browser, GURL(chrome::kChromeUIExtensionsURL)));
577 params.path_behavior = chrome::NavigateParams::IGNORE_AND_NAVIGATE;
578
579 GURL::Replacements replacements;
580 std::string query =
581 base::StringPrintf("options=%s", extension->id().c_str());
582 replacements.SetQueryStr(query);
583 params.url = params.url.ReplaceComponents(replacements);
584
585 chrome::ShowSingletonTabOverwritingNTP(browser, params);
586 } else {
587 // Otherwise open a new tab with the extension's options page
588 content::OpenURLParams params(ManifestURL::GetOptionsPage(extension),
589 content::Referrer(),
590 SINGLETON_TAB,
591 content::PAGE_TRANSITION_LINK,
592 false);
593 browser->OpenURL(params);
594 browser->window()->Show();
595 WebContents* web_contents =
596 browser->tab_strip_model()->GetActiveWebContents();
597 web_contents->GetDelegate()->ActivateContents(web_contents);
598 }
[email protected]695089782013-04-09 16:03:17599}
[email protected]1c4fbc02013-11-13 02:52:42600
601} // namespace extensions