[email protected] | 327640a | 2012-01-24 21:57:59 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 5 | #include "chrome/browser/extensions/extension_tab_util.h" |
[email protected] | 41d9faf | 2012-02-28 23:46:02 | [diff] [blame] | 6 | |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 7 | #include "base/strings/string_number_conversions.h" |
ericzeng | f97b7c2 | 2014-08-26 03:07:30 | [diff] [blame] | 8 | #include "base/strings/stringprintf.h" |
[email protected] | b19451b | 2012-06-08 17:36:19 | [diff] [blame] | 9 | #include "chrome/browser/extensions/api/tabs/tabs_constants.h" |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 10 | #include "chrome/browser/extensions/chrome_extension_function.h" |
lfg | 18533307 | 2014-09-09 20:16:11 | [diff] [blame] | 11 | #include "chrome/browser/extensions/chrome_extension_function_details.h" |
[email protected] | e9570fdf | 2012-07-18 20:01:21 | [diff] [blame] | 12 | #include "chrome/browser/extensions/tab_helper.h" |
| 13 | #include "chrome/browser/extensions/window_controller.h" |
[email protected] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 14 | #include "chrome/browser/extensions/window_controller_list.h" |
[email protected] | b56e2e3 | 2012-05-11 21:18:04 | [diff] [blame] | 15 | #include "chrome/browser/profiles/profile.h" |
[email protected] | e3f90c60 | 2014-08-18 12:41:59 | [diff] [blame] | 16 | #include "chrome/browser/sessions/session_tab_helper.h" |
[email protected] | b56e2e3 | 2012-05-11 21:18:04 | [diff] [blame] | 17 | #include "chrome/browser/ui/browser.h" |
[email protected] | 73c1a684 | 2012-07-13 17:39:04 | [diff] [blame] | 18 | #include "chrome/browser/ui/browser_finder.h" |
[email protected] | 3539929f | 2013-02-01 05:59:14 | [diff] [blame] | 19 | #include "chrome/browser/ui/browser_iterator.h" |
[email protected] | b56e2e3 | 2012-05-11 21:18:04 | [diff] [blame] | 20 | #include "chrome/browser/ui/browser_window.h" |
[email protected] | 0edcdec | 2013-10-31 06:43:08 | [diff] [blame] | 21 | #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" |
ericzeng | f97b7c2 | 2014-08-26 03:07:30 | [diff] [blame] | 22 | #include "chrome/browser/ui/singleton_tabs.h" |
[email protected] | 44e329a | 2012-07-14 01:13:06 | [diff] [blame] | 23 | #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" |
[email protected] | b56e2e3 | 2012-05-11 21:18:04 | [diff] [blame] | 24 | #include "chrome/browser/ui/tabs/tab_strip_model.h" |
jared.sohn | 09a3ccc | 2015-07-09 03:47:30 | [diff] [blame] | 25 | #include "chrome/browser/ui/tabs/tab_utils.h" |
[email protected] | 760f603 | 2014-06-30 23:18:19 | [diff] [blame] | 26 | #include "chrome/common/extensions/api/tabs.h" |
[email protected] | 45c75e6 | 2012-03-21 19:56:35 | [diff] [blame] | 27 | #include "chrome/common/url_constants.h" |
[email protected] | 9b5b1d60 | 2014-06-12 14:29:02 | [diff] [blame] | 28 | #include "components/url_fixer/url_fixer.h" |
[email protected] | ad23a09 | 2011-12-28 07:02:04 | [diff] [blame] | 29 | #include "content/public/browser/favicon_status.h" |
| 30 | #include "content/public/browser/navigation_entry.h" |
[email protected] | 6acde635 | 2012-01-04 16:52:20 | [diff] [blame] | 31 | #include "content/public/browser/web_contents.h" |
hashimoto | ad3c687 | 2014-08-29 09:46:57 | [diff] [blame] | 32 | #include "extensions/browser/app_window/app_window.h" |
| 33 | #include "extensions/browser/app_window/app_window_registry.h" |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 34 | #include "extensions/common/constants.h" |
| 35 | #include "extensions/common/error_utils.h" |
[email protected] | e4452d3 | 2013-11-15 23:07:41 | [diff] [blame] | 36 | #include "extensions/common/extension.h" |
ericzeng | f97b7c2 | 2014-08-26 03:07:30 | [diff] [blame] | 37 | #include "extensions/common/feature_switch.h" |
[email protected] | 0c3c973 | 2013-09-16 08:53:41 | [diff] [blame] | 38 | #include "extensions/common/manifest_constants.h" |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 39 | #include "extensions/common/manifest_handlers/incognito_info.h" |
ericzeng | 09a7e00 | 2014-09-09 21:43:47 | [diff] [blame] | 40 | #include "extensions/common/manifest_handlers/options_page_info.h" |
[email protected] | 793964a | 2013-10-08 00:47:19 | [diff] [blame] | 41 | #include "extensions/common/permissions/api_permission.h" |
[email protected] | e4452d3 | 2013-11-15 23:07:41 | [diff] [blame] | 42 | #include "extensions/common/permissions/permissions_data.h" |
[email protected] | a6483d2 | 2013-07-03 22:11:00 | [diff] [blame] | 43 | #include "url/gurl.h" |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 44 | |
[email protected] | 10f417c5 | 2011-12-28 21:04:23 | [diff] [blame] | 45 | using content::NavigationEntry; |
[email protected] | 26b5e32 | 2011-12-23 01:36:47 | [diff] [blame] | 46 | using content::WebContents; |
[email protected] | 1c4fbc0 | 2013-11-13 02:52:42 | [diff] [blame] | 47 | |
| 48 | namespace extensions { |
[email protected] | 26b5e32 | 2011-12-23 01:36:47 | [diff] [blame] | 49 | |
[email protected] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 50 | namespace { |
| 51 | |
[email protected] | 1c4fbc0 | 2013-11-13 02:52:42 | [diff] [blame] | 52 | namespace keys = tabs_constants; |
| 53 | |
[email protected] | dbb03fb | 2014-02-15 05:36:33 | [diff] [blame] | 54 | WindowController* GetAppWindowController(const WebContents* contents) { |
[email protected] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 55 | Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); |
hashimoto | ad3c687 | 2014-08-29 09:46:57 | [diff] [blame] | 56 | AppWindowRegistry* registry = AppWindowRegistry::Get(profile); |
[email protected] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 57 | if (!registry) |
| 58 | return NULL; |
rdevlin.cronin | c3d6ba1b1 | 2015-07-09 17:36:59 | [diff] [blame] | 59 | AppWindow* app_window = registry->GetAppWindowForWebContents(contents); |
[email protected] | dbb03fb | 2014-02-15 05:36:33 | [diff] [blame] | 60 | if (!app_window) |
[email protected] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 61 | return NULL; |
[email protected] | 4442454 | 2014-01-29 12:10:31 | [diff] [blame] | 62 | return WindowControllerList::GetInstance()->FindWindowById( |
[email protected] | dbb03fb | 2014-02-15 05:36:33 | [diff] [blame] | 63 | app_window->session_id().id()); |
[email protected] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 64 | } |
| 65 | |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 66 | // |error_message| can optionally be passed in and will be set with an |
| 67 | // appropriate message if the window cannot be found by id. |
| 68 | Browser* GetBrowserInProfileWithId(Profile* profile, |
| 69 | const int window_id, |
| 70 | bool include_incognito, |
| 71 | std::string* error_message) { |
| 72 | Profile* incognito_profile = |
| 73 | include_incognito && profile->HasOffTheRecordProfile() |
| 74 | ? profile->GetOffTheRecordProfile() |
| 75 | : NULL; |
| 76 | for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
| 77 | Browser* browser = *it; |
| 78 | if ((browser->profile() == profile || |
| 79 | browser->profile() == incognito_profile) && |
| 80 | ExtensionTabUtil::GetWindowId(browser) == window_id && |
| 81 | browser->window()) { |
| 82 | return browser; |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | if (error_message) |
| 87 | *error_message = ErrorUtils::FormatErrorMessage( |
| 88 | keys::kWindowNotFoundError, base::IntToString(window_id)); |
| 89 | |
| 90 | return NULL; |
| 91 | } |
| 92 | |
[email protected] | a0c91a9f | 2014-05-03 03:41:43 | [diff] [blame] | 93 | Browser* CreateBrowser(ChromeUIThreadExtensionFunction* function, |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 94 | int window_id, |
| 95 | std::string* error) { |
| 96 | content::WebContents* web_contents = function->GetAssociatedWebContents(); |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 97 | chrome::HostDesktopType desktop_type = |
rpaquay | f2ed43c | 2014-11-05 18:50:51 | [diff] [blame] | 98 | web_contents && web_contents->GetNativeView() |
| 99 | ? chrome::GetHostDesktopTypeForNativeView( |
| 100 | web_contents->GetNativeView()) |
| 101 | : chrome::GetHostDesktopTypeForNativeView(NULL); |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 102 | 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] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 109 | } // namespace |
| 110 | |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 111 | ExtensionTabUtil::OpenTabParams::OpenTabParams() |
| 112 | : create_browser_if_needed(false) { |
| 113 | } |
| 114 | |
| 115 | ExtensionTabUtil::OpenTabParams::~OpenTabParams() { |
| 116 | } |
| 117 | |
| 118 | // Opens a new tab for a given extension. Returns NULL and sets |error| if an |
| 119 | // error occurs. |
| 120 | base::DictionaryValue* ExtensionTabUtil::OpenTab( |
[email protected] | a0c91a9f | 2014-05-03 03:41:43 | [diff] [blame] | 121 | ChromeUIThreadExtensionFunction* function, |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 122 | 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()) { |
deepak.m1 | 21895c01 | 2015-05-11 08:11:19 | [diff] [blame] | 146 | if (error) |
| 147 | *error = keys::kNoCurrentWindowError; |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 148 | return NULL; |
| 149 | } |
| 150 | |
| 151 | // TODO(jstritar): Add a constant, chrome.tabs.TAB_ID_ACTIVE, that |
| 152 | // represents the active tab. |
| 153 | WebContents* opener = NULL; |
| 154 | if (params.opener_tab_id.get()) { |
| 155 | int opener_id = *params.opener_tab_id; |
| 156 | |
| 157 | if (!ExtensionTabUtil::GetTabById(opener_id, |
| 158 | function->GetProfile(), |
| 159 | function->include_incognito(), |
| 160 | NULL, |
| 161 | NULL, |
| 162 | &opener, |
| 163 | NULL)) { |
deepak.m1 | 21895c01 | 2015-05-11 08:11:19 | [diff] [blame] | 164 | if (error) { |
| 165 | *error = ErrorUtils::FormatErrorMessage(keys::kTabNotFoundError, |
| 166 | base::IntToString(opener_id)); |
| 167 | } |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 168 | return NULL; |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | // TODO(rafaelw): handle setting remaining tab properties: |
| 173 | // -title |
| 174 | // -favIconUrl |
| 175 | |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 176 | GURL url; |
| 177 | if (params.url.get()) { |
bokan | 107a47f | 2015-02-03 23:23:39 | [diff] [blame] | 178 | std::string url_string = *params.url; |
[email protected] | eba8f7d | 2014-07-28 22:09:23 | [diff] [blame] | 179 | url = ExtensionTabUtil::ResolvePossiblyRelativeURL(url_string, |
| 180 | function->extension()); |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 181 | if (!url.is_valid()) { |
| 182 | *error = |
| 183 | ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, url_string); |
| 184 | return NULL; |
| 185 | } |
[email protected] | f5ec3c92 | 2014-05-22 15:04:03 | [diff] [blame] | 186 | } else { |
| 187 | url = GURL(chrome::kChromeUINewTabURL); |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | // Don't let extensions crash the browser or renderers. |
kalman | dfefe1a | 2015-07-13 22:27:54 | [diff] [blame^] | 191 | if (ExtensionTabUtil::IsKillURL(url)) { |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 192 | *error = keys::kNoCrashBrowserError; |
| 193 | return NULL; |
| 194 | } |
| 195 | |
| 196 | // Default to foreground for the new tab. The presence of 'active' property |
| 197 | // will override this default. |
| 198 | bool active = true; |
| 199 | if (params.active.get()) |
| 200 | active = *params.active; |
| 201 | |
| 202 | // Default to not pinning the tab. Setting the 'pinned' property to true |
| 203 | // will override this default. |
| 204 | bool pinned = false; |
| 205 | if (params.pinned.get()) |
| 206 | pinned = *params.pinned; |
| 207 | |
| 208 | // We can't load extension URLs into incognito windows unless the extension |
| 209 | // uses split mode. Special case to fall back to a tabbed window. |
| 210 | if (url.SchemeIs(kExtensionScheme) && |
[email protected] | eba8f7d | 2014-07-28 22:09:23 | [diff] [blame] | 211 | !IncognitoInfo::IsSplitMode(function->extension()) && |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 212 | browser->profile()->IsOffTheRecord()) { |
| 213 | Profile* profile = browser->profile()->GetOriginalProfile(); |
| 214 | chrome::HostDesktopType desktop_type = browser->host_desktop_type(); |
| 215 | |
| 216 | browser = chrome::FindTabbedBrowser(profile, false, desktop_type); |
| 217 | if (!browser) { |
| 218 | browser = new Browser( |
| 219 | Browser::CreateParams(Browser::TYPE_TABBED, profile, desktop_type)); |
| 220 | browser->window()->Show(); |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | // If index is specified, honor the value, but keep it bound to |
| 225 | // -1 <= index <= tab_strip->count() where -1 invokes the default behavior. |
| 226 | int index = -1; |
| 227 | if (params.index.get()) |
| 228 | index = *params.index; |
| 229 | |
| 230 | TabStripModel* tab_strip = browser->tab_strip_model(); |
| 231 | |
| 232 | index = std::min(std::max(index, -1), tab_strip->count()); |
| 233 | |
| 234 | int add_types = active ? TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE; |
| 235 | add_types |= TabStripModel::ADD_FORCE_INDEX; |
| 236 | if (pinned) |
| 237 | add_types |= TabStripModel::ADD_PINNED; |
| 238 | chrome::NavigateParams navigate_params( |
Sylvain Defresne | c6ccc77d | 2014-09-19 10:19:35 | [diff] [blame] | 239 | browser, url, ui::PAGE_TRANSITION_LINK); |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 240 | navigate_params.disposition = |
| 241 | active ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB; |
| 242 | navigate_params.tabstrip_index = index; |
| 243 | navigate_params.tabstrip_add_types = add_types; |
| 244 | chrome::Navigate(&navigate_params); |
| 245 | |
| 246 | // The tab may have been created in a different window, so make sure we look |
| 247 | // at the right tab strip. |
| 248 | tab_strip = navigate_params.browser->tab_strip_model(); |
| 249 | int new_index = |
| 250 | tab_strip->GetIndexOfWebContents(navigate_params.target_contents); |
| 251 | if (opener) |
| 252 | tab_strip->SetOpenerOfWebContentsAt(new_index, opener); |
| 253 | |
| 254 | if (active) |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 255 | navigate_params.target_contents->SetInitialFocus(); |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 256 | |
| 257 | // Return data about the newly created tab. |
| 258 | return ExtensionTabUtil::CreateTabValue(navigate_params.target_contents, |
| 259 | tab_strip, |
| 260 | new_index, |
[email protected] | eba8f7d | 2014-07-28 22:09:23 | [diff] [blame] | 261 | function->extension()); |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 262 | } |
| 263 | |
| 264 | Browser* ExtensionTabUtil::GetBrowserFromWindowID( |
[email protected] | a0c91a9f | 2014-05-03 03:41:43 | [diff] [blame] | 265 | ChromeUIThreadExtensionFunction* function, |
[email protected] | 9852830 | 2014-05-02 00:34:08 | [diff] [blame] | 266 | int window_id, |
| 267 | std::string* error) { |
| 268 | if (window_id == extension_misc::kCurrentWindowId) { |
| 269 | Browser* result = function->GetCurrentBrowser(); |
| 270 | if (!result || !result->window()) { |
| 271 | if (error) |
| 272 | *error = keys::kNoCurrentWindowError; |
| 273 | return NULL; |
| 274 | } |
| 275 | return result; |
| 276 | } else { |
| 277 | return GetBrowserInProfileWithId(function->GetProfile(), |
| 278 | window_id, |
| 279 | function->include_incognito(), |
| 280 | error); |
| 281 | } |
| 282 | } |
| 283 | |
lfg | 18533307 | 2014-09-09 20:16:11 | [diff] [blame] | 284 | Browser* ExtensionTabUtil::GetBrowserFromWindowID( |
| 285 | const ChromeExtensionFunctionDetails& details, |
| 286 | int window_id, |
| 287 | std::string* error) { |
| 288 | if (window_id == extension_misc::kCurrentWindowId) { |
| 289 | Browser* result = details.GetCurrentBrowser(); |
| 290 | if (!result || !result->window()) { |
| 291 | if (error) |
| 292 | *error = keys::kNoCurrentWindowError; |
| 293 | return NULL; |
| 294 | } |
| 295 | return result; |
| 296 | } else { |
| 297 | return GetBrowserInProfileWithId(details.GetProfile(), |
| 298 | window_id, |
| 299 | details.function()->include_incognito(), |
| 300 | error); |
| 301 | } |
| 302 | } |
| 303 | |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 304 | int ExtensionTabUtil::GetWindowId(const Browser* browser) { |
| 305 | return browser->session_id().id(); |
| 306 | } |
| 307 | |
[email protected] | 8c3495c | 2011-09-28 03:32:30 | [diff] [blame] | 308 | int ExtensionTabUtil::GetWindowIdOfTabStripModel( |
| 309 | const TabStripModel* tab_strip_model) { |
[email protected] | 3539929f | 2013-02-01 05:59:14 | [diff] [blame] | 310 | for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
| 311 | if (it->tab_strip_model() == tab_strip_model) |
[email protected] | 8c3495c | 2011-09-28 03:32:30 | [diff] [blame] | 312 | return GetWindowId(*it); |
| 313 | } |
| 314 | return -1; |
| 315 | } |
| 316 | |
[email protected] | d2bd5fde | 2014-05-29 02:24:31 | [diff] [blame] | 317 | int ExtensionTabUtil::GetTabId(const WebContents* web_contents) { |
[email protected] | e3f90c60 | 2014-08-18 12:41:59 | [diff] [blame] | 318 | return SessionTabHelper::IdForTab(web_contents); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 319 | } |
| 320 | |
| 321 | std::string ExtensionTabUtil::GetTabStatusText(bool is_loading) { |
| 322 | return is_loading ? keys::kStatusValueLoading : keys::kStatusValueComplete; |
| 323 | } |
| 324 | |
[email protected] | ea049a0 | 2011-12-25 21:37:09 | [diff] [blame] | 325 | int ExtensionTabUtil::GetWindowIdOfTab(const WebContents* web_contents) { |
[email protected] | e3f90c60 | 2014-08-18 12:41:59 | [diff] [blame] | 326 | return SessionTabHelper::IdForWindowContainingTab(web_contents); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 327 | } |
| 328 | |
[email protected] | 023b3d1 | 2013-12-23 18:46:49 | [diff] [blame] | 329 | base::DictionaryValue* ExtensionTabUtil::CreateTabValue( |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 330 | WebContents* contents, |
[email protected] | 0c9f326 | 2012-09-17 05:59:06 | [diff] [blame] | 331 | TabStripModel* tab_strip, |
| 332 | int tab_index, |
[email protected] | f34706be | 2012-09-04 07:32:09 | [diff] [blame] | 333 | const Extension* extension) { |
[email protected] | dbb03fb | 2014-02-15 05:36:33 | [diff] [blame] | 334 | // If we have a matching AppWindow with a controller, get the tab value |
[email protected] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 335 | // from its controller instead. |
[email protected] | dbb03fb | 2014-02-15 05:36:33 | [diff] [blame] | 336 | WindowController* controller = GetAppWindowController(contents); |
[email protected] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 337 | if (controller && |
| 338 | (!extension || controller->IsVisibleToExtension(extension))) { |
| 339 | return controller->CreateTabValue(extension, tab_index); |
| 340 | } |
[email protected] | 4442454 | 2014-01-29 12:10:31 | [diff] [blame] | 341 | base::DictionaryValue* result = |
[email protected] | 023b3d1 | 2013-12-23 18:46:49 | [diff] [blame] | 342 | CreateTabValue(contents, tab_strip, tab_index); |
[email protected] | 304fd15 | 2013-01-12 16:54:44 | [diff] [blame] | 343 | ScrubTabValueForExtension(contents, extension, result); |
| 344 | return result; |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 345 | } |
| 346 | |
[email protected] | aeca23f | 2013-06-21 22:34:41 | [diff] [blame] | 347 | base::ListValue* ExtensionTabUtil::CreateTabList( |
[email protected] | f34706be | 2012-09-04 07:32:09 | [diff] [blame] | 348 | const Browser* browser, |
| 349 | const Extension* extension) { |
[email protected] | aeca23f | 2013-06-21 22:34:41 | [diff] [blame] | 350 | base::ListValue* tab_list = new base::ListValue(); |
[email protected] | c084925 | 2012-05-12 13:51:27 | [diff] [blame] | 351 | TabStripModel* tab_strip = browser->tab_strip_model(); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 352 | for (int i = 0; i < tab_strip->count(); ++i) { |
[email protected] | 72f6797 | 2012-10-30 18:53:28 | [diff] [blame] | 353 | tab_list->Append(CreateTabValue(tab_strip->GetWebContentsAt(i), |
| 354 | tab_strip, |
| 355 | i, |
| 356 | extension)); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 357 | } |
| 358 | |
| 359 | return tab_list; |
| 360 | } |
| 361 | |
[email protected] | 023b3d1 | 2013-12-23 18:46:49 | [diff] [blame] | 362 | base::DictionaryValue* ExtensionTabUtil::CreateTabValue( |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 363 | WebContents* contents, |
[email protected] | f34706be | 2012-09-04 07:32:09 | [diff] [blame] | 364 | TabStripModel* tab_strip, |
[email protected] | 304fd15 | 2013-01-12 16:54:44 | [diff] [blame] | 365 | int tab_index) { |
[email protected] | dbb03fb | 2014-02-15 05:36:33 | [diff] [blame] | 366 | // If we have a matching AppWindow with a controller, get the tab value |
[email protected] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 367 | // from its controller instead. |
[email protected] | dbb03fb | 2014-02-15 05:36:33 | [diff] [blame] | 368 | WindowController* controller = GetAppWindowController(contents); |
[email protected] | f1c102b | 2013-02-15 07:44:12 | [diff] [blame] | 369 | if (controller) |
| 370 | return controller->CreateTabValue(NULL, tab_index); |
| 371 | |
[email protected] | 0c9f326 | 2012-09-17 05:59:06 | [diff] [blame] | 372 | if (!tab_strip) |
| 373 | ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index); |
| 374 | |
[email protected] | 023b3d1 | 2013-12-23 18:46:49 | [diff] [blame] | 375 | base::DictionaryValue* result = new base::DictionaryValue(); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 376 | bool is_loading = contents->IsLoading(); |
[email protected] | f34706be | 2012-09-04 07:32:09 | [diff] [blame] | 377 | result->SetInteger(keys::kIdKey, GetTabId(contents)); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 378 | result->SetInteger(keys::kIndexKey, tab_index); |
[email protected] | f34706be | 2012-09-04 07:32:09 | [diff] [blame] | 379 | result->SetInteger(keys::kWindowIdKey, GetWindowIdOfTab(contents)); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 380 | result->SetString(keys::kStatusKey, GetTabStatusText(is_loading)); |
[email protected] | 8c3495c | 2011-09-28 03:32:30 | [diff] [blame] | 381 | result->SetBoolean(keys::kActiveKey, |
| 382 | tab_strip && tab_index == tab_strip->active_index()); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 383 | result->SetBoolean(keys::kSelectedKey, |
| 384 | tab_strip && tab_index == tab_strip->active_index()); |
[email protected] | 8c3495c | 2011-09-28 03:32:30 | [diff] [blame] | 385 | result->SetBoolean(keys::kHighlightedKey, |
| 386 | tab_strip && tab_strip->IsTabSelected(tab_index)); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 387 | result->SetBoolean(keys::kPinnedKey, |
| 388 | tab_strip && tab_strip->IsTabPinned(tab_index)); |
jared.sohn | 09a3ccc | 2015-07-09 03:47:30 | [diff] [blame] | 389 | result->SetBoolean(keys::kAudibleKey, |
| 390 | tab_strip && chrome::IsPlayingAudio(contents)); |
| 391 | result->SetBoolean(keys::kMutedKey, |
| 392 | tab_strip && chrome::IsTabAudioMuted(contents)); |
| 393 | result->SetString(keys::kMutedCauseKey, |
| 394 | chrome::GetTabAudioMutedCause(contents)); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 395 | result->SetBoolean(keys::kIncognitoKey, |
[email protected] | 627e051 | 2011-12-21 22:55:30 | [diff] [blame] | 396 | contents->GetBrowserContext()->IsOffTheRecord()); |
[email protected] | a16a5a5 | 2013-08-16 17:23:35 | [diff] [blame] | 397 | result->SetInteger(keys::kWidthKey, |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 398 | contents->GetContainerBounds().size().width()); |
[email protected] | a16a5a5 | 2013-08-16 17:23:35 | [diff] [blame] | 399 | result->SetInteger(keys::kHeightKey, |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 400 | contents->GetContainerBounds().size().height()); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 401 | |
[email protected] | 304fd15 | 2013-01-12 16:54:44 | [diff] [blame] | 402 | // Privacy-sensitive fields: these should be stripped off by |
| 403 | // ScrubTabValueForExtension if the extension should not see them. |
| 404 | result->SetString(keys::kUrlKey, contents->GetURL().spec()); |
| 405 | result->SetString(keys::kTitleKey, contents->GetTitle()); |
| 406 | if (!is_loading) { |
[email protected] | afe9aba | 2013-08-16 20:31:34 | [diff] [blame] | 407 | NavigationEntry* entry = contents->GetController().GetVisibleEntry(); |
[email protected] | 304fd15 | 2013-01-12 16:54:44 | [diff] [blame] | 408 | if (entry && entry->GetFavicon().valid) |
| 409 | result->SetString(keys::kFaviconUrlKey, entry->GetFavicon().url.spec()); |
[email protected] | f34706be | 2012-09-04 07:32:09 | [diff] [blame] | 410 | } |
| 411 | |
[email protected] | 327640a | 2012-01-24 21:57:59 | [diff] [blame] | 412 | if (tab_strip) { |
[email protected] | 6707540 | 2012-10-26 08:26:25 | [diff] [blame] | 413 | WebContents* opener = tab_strip->GetOpenerOfWebContentsAt(tab_index); |
| 414 | if (opener) |
| 415 | result->SetInteger(keys::kOpenerTabIdKey, GetTabId(opener)); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 416 | } |
| 417 | |
| 418 | return result; |
| 419 | } |
| 420 | |
[email protected] | 023b3d1 | 2013-12-23 18:46:49 | [diff] [blame] | 421 | void ExtensionTabUtil::ScrubTabValueForExtension( |
[email protected] | fc2b46b | 2014-05-03 16:33:45 | [diff] [blame] | 422 | WebContents* contents, |
[email protected] | 023b3d1 | 2013-12-23 18:46:49 | [diff] [blame] | 423 | const Extension* extension, |
| 424 | base::DictionaryValue* tab_info) { |
[email protected] | a6910e7 | 2014-06-06 05:04:36 | [diff] [blame] | 425 | bool has_permission = extension && |
| 426 | extension->permissions_data()->HasAPIPermissionForTab( |
| 427 | GetTabId(contents), APIPermission::kTab); |
[email protected] | 304fd15 | 2013-01-12 16:54:44 | [diff] [blame] | 428 | |
| 429 | if (!has_permission) { |
| 430 | tab_info->Remove(keys::kUrlKey, NULL); |
| 431 | tab_info->Remove(keys::kTitleKey, NULL); |
| 432 | tab_info->Remove(keys::kFaviconUrlKey, NULL); |
| 433 | } |
| 434 | } |
| 435 | |
[email protected] | ab3f6141 | 2013-01-29 21:55:07 | [diff] [blame] | 436 | void ExtensionTabUtil::ScrubTabForExtension(const Extension* extension, |
[email protected] | 1c4fbc0 | 2013-11-13 02:52:42 | [diff] [blame] | 437 | api::tabs::Tab* tab) { |
[email protected] | 076ebeda | 2014-06-06 21:47:26 | [diff] [blame] | 438 | bool has_permission = |
| 439 | extension && |
| 440 | extension->permissions_data()->HasAPIPermission(APIPermission::kTab); |
[email protected] | ab3f6141 | 2013-01-29 21:55:07 | [diff] [blame] | 441 | |
| 442 | if (!has_permission) { |
| 443 | tab->url.reset(); |
| 444 | tab->title.reset(); |
| 445 | tab->fav_icon_url.reset(); |
| 446 | } |
| 447 | } |
| 448 | |
[email protected] | ea049a0 | 2011-12-25 21:37:09 | [diff] [blame] | 449 | bool ExtensionTabUtil::GetTabStripModel(const WebContents* web_contents, |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 450 | TabStripModel** tab_strip_model, |
| 451 | int* tab_index) { |
[email protected] | ea049a0 | 2011-12-25 21:37:09 | [diff] [blame] | 452 | DCHECK(web_contents); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 453 | DCHECK(tab_strip_model); |
| 454 | DCHECK(tab_index); |
| 455 | |
[email protected] | 3539929f | 2013-02-01 05:59:14 | [diff] [blame] | 456 | for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
| 457 | TabStripModel* tab_strip = it->tab_strip_model(); |
[email protected] | e52d0a4 | 2012-06-08 22:44:16 | [diff] [blame] | 458 | int index = tab_strip->GetIndexOfWebContents(web_contents); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 459 | if (index != -1) { |
| 460 | *tab_strip_model = tab_strip; |
| 461 | *tab_index = index; |
| 462 | return true; |
| 463 | } |
| 464 | } |
| 465 | |
| 466 | return false; |
| 467 | } |
| 468 | |
| 469 | bool ExtensionTabUtil::GetDefaultTab(Browser* browser, |
[email protected] | 72f6797 | 2012-10-30 18:53:28 | [diff] [blame] | 470 | WebContents** contents, |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 471 | int* tab_id) { |
| 472 | DCHECK(browser); |
| 473 | DCHECK(contents); |
| 474 | |
[email protected] | 617ee96 | 2013-01-29 20:49:12 | [diff] [blame] | 475 | *contents = browser->tab_strip_model()->GetActiveWebContents(); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 476 | if (*contents) { |
| 477 | if (tab_id) |
[email protected] | 72f6797 | 2012-10-30 18:53:28 | [diff] [blame] | 478 | *tab_id = GetTabId(*contents); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 479 | return true; |
| 480 | } |
| 481 | |
| 482 | return false; |
| 483 | } |
| 484 | |
| 485 | bool ExtensionTabUtil::GetTabById(int tab_id, |
wjmaclean | 5b11eee | 2014-09-05 00:55:14 | [diff] [blame] | 486 | content::BrowserContext* browser_context, |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 487 | bool include_incognito, |
| 488 | Browser** browser, |
| 489 | TabStripModel** tab_strip, |
[email protected] | 72f6797 | 2012-10-30 18:53:28 | [diff] [blame] | 490 | WebContents** contents, |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 491 | int* tab_index) { |
wjmaclean | 5b11eee | 2014-09-05 00:55:14 | [diff] [blame] | 492 | Profile* profile = Profile::FromBrowserContext(browser_context); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 493 | Profile* incognito_profile = |
| 494 | include_incognito && profile->HasOffTheRecordProfile() ? |
| 495 | profile->GetOffTheRecordProfile() : NULL; |
[email protected] | 3539929f | 2013-02-01 05:59:14 | [diff] [blame] | 496 | for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
| 497 | Browser* target_browser = *it; |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 498 | if (target_browser->profile() == profile || |
| 499 | target_browser->profile() == incognito_profile) { |
[email protected] | c084925 | 2012-05-12 13:51:27 | [diff] [blame] | 500 | TabStripModel* target_tab_strip = target_browser->tab_strip_model(); |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 501 | for (int i = 0; i < target_tab_strip->count(); ++i) { |
[email protected] | 72f6797 | 2012-10-30 18:53:28 | [diff] [blame] | 502 | WebContents* target_contents = target_tab_strip->GetWebContentsAt(i); |
[email protected] | e3f90c60 | 2014-08-18 12:41:59 | [diff] [blame] | 503 | if (SessionTabHelper::IdForTab(target_contents) == tab_id) { |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 504 | if (browser) |
| 505 | *browser = target_browser; |
| 506 | if (tab_strip) |
| 507 | *tab_strip = target_tab_strip; |
| 508 | if (contents) |
| 509 | *contents = target_contents; |
| 510 | if (tab_index) |
| 511 | *tab_index = i; |
| 512 | return true; |
| 513 | } |
| 514 | } |
| 515 | } |
| 516 | } |
| 517 | return false; |
| 518 | } |
[email protected] | 45c75e6 | 2012-03-21 19:56:35 | [diff] [blame] | 519 | |
| 520 | GURL ExtensionTabUtil::ResolvePossiblyRelativeURL(const std::string& url_string, |
[email protected] | 1c4fbc0 | 2013-11-13 02:52:42 | [diff] [blame] | 521 | const Extension* extension) { |
[email protected] | 45c75e6 | 2012-03-21 19:56:35 | [diff] [blame] | 522 | GURL url = GURL(url_string); |
| 523 | if (!url.is_valid()) |
| 524 | url = extension->GetResourceURL(url_string); |
| 525 | |
| 526 | return url; |
| 527 | } |
| 528 | |
kalman | dfefe1a | 2015-07-13 22:27:54 | [diff] [blame^] | 529 | bool ExtensionTabUtil::IsKillURL(const GURL& url) { |
| 530 | static const char* kill_hosts[] = { |
| 531 | chrome::kChromeUICrashHost, |
| 532 | chrome::kChromeUIHangUIHost, |
| 533 | chrome::kChromeUIKillHost, |
| 534 | chrome::kChromeUIQuitHost, |
| 535 | chrome::kChromeUIRestartHost, |
| 536 | content::kChromeUIBrowserCrashHost, |
| 537 | }; |
| 538 | |
[email protected] | 45c75e6 | 2012-03-21 19:56:35 | [diff] [blame] | 539 | // Check a fixed-up URL, to normalize the scheme and parse hosts correctly. |
| 540 | GURL fixed_url = |
[email protected] | 9b5b1d60 | 2014-06-12 14:29:02 | [diff] [blame] | 541 | url_fixer::FixupURL(url.possibly_invalid_spec(), std::string()); |
kalman | dfefe1a | 2015-07-13 22:27:54 | [diff] [blame^] | 542 | if (!fixed_url.SchemeIs(content::kChromeUIScheme)) |
| 543 | return false; |
| 544 | |
| 545 | for (size_t i = 0; i < arraysize(kill_hosts); ++i) { |
| 546 | if (fixed_url.host() == kill_hosts[i]) |
| 547 | return true; |
| 548 | } |
| 549 | |
| 550 | return false; |
[email protected] | 45c75e6 | 2012-03-21 19:56:35 | [diff] [blame] | 551 | } |
[email protected] | 73c1a684 | 2012-07-13 17:39:04 | [diff] [blame] | 552 | |
| 553 | void ExtensionTabUtil::CreateTab(WebContents* web_contents, |
| 554 | const std::string& extension_id, |
| 555 | WindowOpenDisposition disposition, |
bokan | 107a47f | 2015-02-03 23:23:39 | [diff] [blame] | 556 | const gfx::Rect& initial_rect, |
[email protected] | 73c1a684 | 2012-07-13 17:39:04 | [diff] [blame] | 557 | bool user_gesture) { |
[email protected] | 73c1a684 | 2012-07-13 17:39:04 | [diff] [blame] | 558 | Profile* profile = |
| 559 | Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
[email protected] | 435d43e0 | 2012-12-09 09:13:55 | [diff] [blame] | 560 | chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop(); |
[email protected] | 7507273 | 2013-01-09 13:39:25 | [diff] [blame] | 561 | Browser* browser = chrome::FindTabbedBrowser(profile, false, active_desktop); |
[email protected] | 2764cab7 | 2012-07-19 17:02:10 | [diff] [blame] | 562 | const bool browser_created = !browser; |
| 563 | if (!browser) |
[email protected] | 435d43e0 | 2012-12-09 09:13:55 | [diff] [blame] | 564 | browser = new Browser(Browser::CreateParams(profile, active_desktop)); |
[email protected] | e232c99 | 2012-12-06 12:43:20 | [diff] [blame] | 565 | chrome::NavigateParams params(browser, web_contents); |
[email protected] | 73c1a684 | 2012-07-13 17:39:04 | [diff] [blame] | 566 | |
| 567 | // The extension_app_id parameter ends up as app_name in the Browser |
| 568 | // which causes the Browser to return true for is_app(). This affects |
| 569 | // among other things, whether the location bar gets displayed. |
| 570 | // TODO(mpcomplete): This seems wrong. What if the extension content is hosted |
| 571 | // in a tab? |
| 572 | if (disposition == NEW_POPUP) |
| 573 | params.extension_app_id = extension_id; |
| 574 | |
[email protected] | 73c1a684 | 2012-07-13 17:39:04 | [diff] [blame] | 575 | params.disposition = disposition; |
bokan | 107a47f | 2015-02-03 23:23:39 | [diff] [blame] | 576 | params.window_bounds = initial_rect; |
[email protected] | 73c1a684 | 2012-07-13 17:39:04 | [diff] [blame] | 577 | params.window_action = chrome::NavigateParams::SHOW_WINDOW; |
| 578 | params.user_gesture = user_gesture; |
| 579 | chrome::Navigate(¶ms); |
[email protected] | 2764cab7 | 2012-07-19 17:02:10 | [diff] [blame] | 580 | |
| 581 | // Close the browser if chrome::Navigate created a new one. |
| 582 | if (browser_created && (browser != params.browser)) |
| 583 | browser->window()->Close(); |
[email protected] | 73c1a684 | 2012-07-13 17:39:04 | [diff] [blame] | 584 | } |
[email protected] | 44e329a | 2012-07-14 01:13:06 | [diff] [blame] | 585 | |
| 586 | // static |
| 587 | void ExtensionTabUtil::ForEachTab( |
| 588 | const base::Callback<void(WebContents*)>& callback) { |
[email protected] | b031ff8 | 2013-01-29 22:53:16 | [diff] [blame] | 589 | for (TabContentsIterator iterator; !iterator.done(); iterator.Next()) |
[email protected] | f807356 | 2012-12-06 12:43:53 | [diff] [blame] | 590 | callback.Run(*iterator); |
[email protected] | 44e329a | 2012-07-14 01:13:06 | [diff] [blame] | 591 | } |
[email protected] | e9570fdf | 2012-07-18 20:01:21 | [diff] [blame] | 592 | |
| 593 | // static |
[email protected] | 1c4fbc0 | 2013-11-13 02:52:42 | [diff] [blame] | 594 | WindowController* ExtensionTabUtil::GetWindowControllerOfTab( |
[email protected] | e9570fdf | 2012-07-18 20:01:21 | [diff] [blame] | 595 | const WebContents* web_contents) { |
[email protected] | f7b4b9e | 2012-12-02 07:43:17 | [diff] [blame] | 596 | Browser* browser = chrome::FindBrowserWithWebContents(web_contents); |
[email protected] | e9570fdf | 2012-07-18 20:01:21 | [diff] [blame] | 597 | if (browser != NULL) |
| 598 | return browser->extension_window_controller(); |
| 599 | |
| 600 | return NULL; |
| 601 | } |
[email protected] | 69508978 | 2013-04-09 16:03:17 | [diff] [blame] | 602 | |
kalman | ce22c47 | 2015-02-19 02:31:43 | [diff] [blame] | 603 | bool ExtensionTabUtil::OpenOptionsPage(const Extension* extension, |
[email protected] | 69508978 | 2013-04-09 16:03:17 | [diff] [blame] | 604 | Browser* browser) { |
kalman | ce22c47 | 2015-02-19 02:31:43 | [diff] [blame] | 605 | if (!OptionsPageInfo::HasOptionsPage(extension)) |
| 606 | return false; |
[email protected] | 69508978 | 2013-04-09 16:03:17 | [diff] [blame] | 607 | |
| 608 | // Force the options page to open in non-OTR window, because it won't be |
| 609 | // able to save settings from OTR. |
[email protected] | 0edcdec | 2013-10-31 06:43:08 | [diff] [blame] | 610 | scoped_ptr<chrome::ScopedTabbedBrowserDisplayer> displayer; |
[email protected] | 69508978 | 2013-04-09 16:03:17 | [diff] [blame] | 611 | if (browser->profile()->IsOffTheRecord()) { |
[email protected] | 0edcdec | 2013-10-31 06:43:08 | [diff] [blame] | 612 | displayer.reset(new chrome::ScopedTabbedBrowserDisplayer( |
| 613 | browser->profile()->GetOriginalProfile(), |
| 614 | browser->host_desktop_type())); |
| 615 | browser = displayer->browser(); |
[email protected] | 69508978 | 2013-04-09 16:03:17 | [diff] [blame] | 616 | } |
| 617 | |
kalman | 4427c25 | 2015-03-13 01:55:48 | [diff] [blame] | 618 | GURL url_to_navigate; |
| 619 | if (OptionsPageInfo::ShouldOpenInTab(extension)) { |
| 620 | // Options page tab is simply e.g. chrome-extension://.../options.html. |
| 621 | url_to_navigate = OptionsPageInfo::GetOptionsPage(extension); |
| 622 | } else { |
| 623 | // Options page tab is Extension settings pointed at that Extension's ID, |
| 624 | // e.g. chrome://extensions?options=... |
| 625 | url_to_navigate = GURL(chrome::kChromeUIExtensionsURL); |
ericzeng | f97b7c2 | 2014-08-26 03:07:30 | [diff] [blame] | 626 | GURL::Replacements replacements; |
| 627 | std::string query = |
| 628 | base::StringPrintf("options=%s", extension->id().c_str()); |
| 629 | replacements.SetQueryStr(query); |
kalman | 4427c25 | 2015-03-13 01:55:48 | [diff] [blame] | 630 | url_to_navigate = url_to_navigate.ReplaceComponents(replacements); |
ericzeng | f97b7c2 | 2014-08-26 03:07:30 | [diff] [blame] | 631 | } |
kalman | ce22c47 | 2015-02-19 02:31:43 | [diff] [blame] | 632 | |
kalman | 4427c25 | 2015-03-13 01:55:48 | [diff] [blame] | 633 | chrome::NavigateParams params( |
| 634 | chrome::GetSingletonTabNavigateParams(browser, url_to_navigate)); |
| 635 | params.path_behavior = chrome::NavigateParams::IGNORE_AND_NAVIGATE; |
| 636 | params.url = url_to_navigate; |
| 637 | chrome::ShowSingletonTabOverwritingNTP(browser, params); |
kalman | ce22c47 | 2015-02-19 02:31:43 | [diff] [blame] | 638 | return true; |
[email protected] | 69508978 | 2013-04-09 16:03:17 | [diff] [blame] | 639 | } |
[email protected] | 1c4fbc0 | 2013-11-13 02:52:42 | [diff] [blame] | 640 | |
| 641 | } // namespace extensions |