Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_tab_util.h" | 5 #include "chrome/browser/extensions/extension_tab_util.h" |
| 6 | 6 |
| 7 #include "apps/app_window.h" | 7 #include "apps/app_window.h" |
| 8 #include "apps/app_window_registry.h" | 8 #include "apps/app_window_registry.h" |
| 9 #include "base/strings/string_number_conversions.h" | |
| 9 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" | 10 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" |
| 11 #include "chrome/browser/extensions/chrome_extension_function.h" | |
| 10 #include "chrome/browser/extensions/tab_helper.h" | 12 #include "chrome/browser/extensions/tab_helper.h" |
| 11 #include "chrome/browser/extensions/window_controller.h" | 13 #include "chrome/browser/extensions/window_controller.h" |
| 12 #include "chrome/browser/extensions/window_controller_list.h" | 14 #include "chrome/browser/extensions/window_controller_list.h" |
| 13 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 14 #include "chrome/browser/sessions/session_id.h" | 16 #include "chrome/browser/sessions/session_id.h" |
| 15 #include "chrome/browser/ui/browser.h" | 17 #include "chrome/browser/ui/browser.h" |
| 16 #include "chrome/browser/ui/browser_finder.h" | 18 #include "chrome/browser/ui/browser_finder.h" |
| 17 #include "chrome/browser/ui/browser_iterator.h" | 19 #include "chrome/browser/ui/browser_iterator.h" |
| 18 #include "chrome/browser/ui/browser_window.h" | 20 #include "chrome/browser/ui/browser_window.h" |
| 19 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" | 21 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" |
| 20 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" | 22 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" |
| 21 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 23 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 22 #include "chrome/common/extensions/manifest_url_handler.h" | 24 #include "chrome/common/extensions/manifest_url_handler.h" |
| 23 #include "chrome/common/net/url_fixer_upper.h" | 25 #include "chrome/common/net/url_fixer_upper.h" |
| 24 #include "chrome/common/url_constants.h" | 26 #include "chrome/common/url_constants.h" |
| 25 #include "content/public/browser/favicon_status.h" | 27 #include "content/public/browser/favicon_status.h" |
| 26 #include "content/public/browser/navigation_entry.h" | 28 #include "content/public/browser/navigation_entry.h" |
| 27 #include "content/public/browser/web_contents.h" | 29 #include "content/public/browser/web_contents.h" |
| 28 #include "content/public/browser/web_contents_view.h" | 30 #include "content/public/browser/web_contents_view.h" |
| 31 #include "extensions/common/constants.h" | |
| 32 #include "extensions/common/error_utils.h" | |
| 29 #include "extensions/common/extension.h" | 33 #include "extensions/common/extension.h" |
| 30 #include "extensions/common/manifest_constants.h" | 34 #include "extensions/common/manifest_constants.h" |
| 35 #include "extensions/common/manifest_handlers/incognito_info.h" | |
| 31 #include "extensions/common/permissions/api_permission.h" | 36 #include "extensions/common/permissions/api_permission.h" |
| 32 #include "extensions/common/permissions/permissions_data.h" | 37 #include "extensions/common/permissions/permissions_data.h" |
| 33 #include "url/gurl.h" | 38 #include "url/gurl.h" |
| 34 | 39 |
| 35 using apps::AppWindow; | 40 using apps::AppWindow; |
| 36 using content::NavigationEntry; | 41 using content::NavigationEntry; |
| 37 using content::WebContents; | 42 using content::WebContents; |
| 38 | 43 |
| 39 namespace extensions { | 44 namespace extensions { |
| 40 | 45 |
| 41 namespace { | 46 namespace { |
| 42 | 47 |
| 43 namespace keys = tabs_constants; | 48 namespace keys = tabs_constants; |
| 44 | 49 |
| 45 WindowController* GetAppWindowController(const WebContents* contents) { | 50 WindowController* GetAppWindowController(const WebContents* contents) { |
| 46 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); | 51 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); |
| 47 apps::AppWindowRegistry* registry = apps::AppWindowRegistry::Get(profile); | 52 apps::AppWindowRegistry* registry = apps::AppWindowRegistry::Get(profile); |
| 48 if (!registry) | 53 if (!registry) |
| 49 return NULL; | 54 return NULL; |
| 50 AppWindow* app_window = | 55 AppWindow* app_window = |
| 51 registry->GetAppWindowForRenderViewHost(contents->GetRenderViewHost()); | 56 registry->GetAppWindowForRenderViewHost(contents->GetRenderViewHost()); |
| 52 if (!app_window) | 57 if (!app_window) |
| 53 return NULL; | 58 return NULL; |
| 54 return WindowControllerList::GetInstance()->FindWindowById( | 59 return WindowControllerList::GetInstance()->FindWindowById( |
| 55 app_window->session_id().id()); | 60 app_window->session_id().id()); |
| 56 } | 61 } |
| 57 | 62 |
| 63 // |error_message| can optionally be passed in a will be set with an appropriate | |
|
miket_OOO
2014/04/28 18:24:35
a => and?
rpaquay
2014/04/28 19:44:12
Done.
| |
| 64 // message if the window cannot be found by id. | |
| 65 Browser* GetBrowserInProfileWithId(Profile* profile, | |
| 66 const int window_id, | |
| 67 bool include_incognito, | |
| 68 std::string* error_message) { | |
| 69 Profile* incognito_profile = | |
| 70 include_incognito && profile->HasOffTheRecordProfile() | |
| 71 ? profile->GetOffTheRecordProfile() | |
| 72 : NULL; | |
| 73 for (chrome::BrowserIterator it; !it.done(); it.Next()) { | |
| 74 Browser* browser = *it; | |
| 75 if ((browser->profile() == profile || | |
| 76 browser->profile() == incognito_profile) && | |
| 77 ExtensionTabUtil::GetWindowId(browser) == window_id && | |
| 78 browser->window()) { | |
| 79 return browser; | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 if (error_message) | |
| 84 *error_message = ErrorUtils::FormatErrorMessage( | |
| 85 keys::kWindowNotFoundError, base::IntToString(window_id)); | |
| 86 | |
| 87 return NULL; | |
| 88 } | |
| 89 | |
| 90 Browser* CreateBrowser(ChromeAsyncExtensionFunction* function, | |
| 91 int window_id, | |
| 92 std::string* error) { | |
| 93 content::WebContents* web_contents = function->GetAssociatedWebContents(); | |
| 94 DCHECK(web_contents); | |
|
miket_OOO
2014/04/28 18:24:35
I don't know whether these should be DCHECKs or CH
rpaquay
2014/04/28 19:44:12
AFAIK, looking the the implementations, the first
| |
| 95 DCHECK(web_contents->GetView()); | |
| 96 DCHECK(web_contents->GetView()->GetNativeView()); | |
| 97 DCHECK(!chrome::FindBrowserWithWebContents(web_contents)); | |
| 98 | |
| 99 chrome::HostDesktopType desktop_type = | |
| 100 chrome::GetHostDesktopTypeForNativeView( | |
| 101 web_contents->GetView()->GetNativeView()); | |
| 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 | |
| 58 } // namespace | 109 } // namespace |
| 59 | 110 |
| 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( | |
| 121 ChromeAsyncExtensionFunction* function, | |
| 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()) { | |
| 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 | |
| 172 std::string url_string; | |
| 173 GURL url; | |
| 174 if (params.url.get()) { | |
| 175 url_string = *params.url; | |
| 176 url = ExtensionTabUtil::ResolvePossiblyRelativeURL( | |
| 177 url_string, function->GetExtension()); | |
| 178 if (!url.is_valid()) { | |
| 179 *error = | |
| 180 ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, url_string); | |
| 181 return NULL; | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 // Don't let extensions crash the browser or renderers. | |
| 186 if (ExtensionTabUtil::IsCrashURL(url)) { | |
| 187 *error = keys::kNoCrashBrowserError; | |
| 188 return NULL; | |
| 189 } | |
| 190 | |
| 191 // Default to foreground for the new tab. The presence of 'active' property | |
| 192 // will override this default. | |
| 193 bool active = true; | |
| 194 if (params.active.get()) | |
| 195 active = *params.active; | |
| 196 | |
| 197 // Default to not pinning the tab. Setting the 'pinned' property to true | |
| 198 // will override this default. | |
| 199 bool pinned = false; | |
| 200 if (params.pinned.get()) | |
| 201 pinned = *params.pinned; | |
| 202 | |
| 203 // We can't load extension URLs into incognito windows unless the extension | |
| 204 // uses split mode. Special case to fall back to a tabbed window. | |
| 205 if (url.SchemeIs(kExtensionScheme) && | |
| 206 !IncognitoInfo::IsSplitMode(function->GetExtension()) && | |
| 207 browser->profile()->IsOffTheRecord()) { | |
| 208 Profile* profile = browser->profile()->GetOriginalProfile(); | |
| 209 chrome::HostDesktopType desktop_type = browser->host_desktop_type(); | |
| 210 | |
| 211 browser = chrome::FindTabbedBrowser(profile, false, desktop_type); | |
| 212 if (!browser) { | |
| 213 browser = new Browser( | |
| 214 Browser::CreateParams(Browser::TYPE_TABBED, profile, desktop_type)); | |
| 215 browser->window()->Show(); | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 // If index is specified, honor the value, but keep it bound to | |
| 220 // -1 <= index <= tab_strip->count() where -1 invokes the default behavior. | |
| 221 int index = -1; | |
| 222 if (params.index.get()) | |
| 223 index = *params.index; | |
| 224 | |
| 225 TabStripModel* tab_strip = browser->tab_strip_model(); | |
| 226 | |
| 227 index = std::min(std::max(index, -1), tab_strip->count()); | |
| 228 | |
| 229 int add_types = active ? TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE; | |
| 230 add_types |= TabStripModel::ADD_FORCE_INDEX; | |
| 231 if (pinned) | |
| 232 add_types |= TabStripModel::ADD_PINNED; | |
| 233 chrome::NavigateParams navigate_params( | |
| 234 browser, url, content::PAGE_TRANSITION_LINK); | |
| 235 navigate_params.disposition = | |
| 236 active ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB; | |
| 237 navigate_params.tabstrip_index = index; | |
| 238 navigate_params.tabstrip_add_types = add_types; | |
| 239 chrome::Navigate(&navigate_params); | |
| 240 | |
| 241 // The tab may have been created in a different window, so make sure we look | |
| 242 // at the right tab strip. | |
| 243 tab_strip = navigate_params.browser->tab_strip_model(); | |
| 244 int new_index = | |
| 245 tab_strip->GetIndexOfWebContents(navigate_params.target_contents); | |
| 246 if (opener) | |
| 247 tab_strip->SetOpenerOfWebContentsAt(new_index, opener); | |
| 248 | |
| 249 if (active) | |
| 250 navigate_params.target_contents->GetView()->SetInitialFocus(); | |
| 251 | |
| 252 // Return data about the newly created tab. | |
| 253 return ExtensionTabUtil::CreateTabValue(navigate_params.target_contents, | |
| 254 tab_strip, | |
| 255 new_index, | |
| 256 function->GetExtension()); | |
| 257 } | |
| 258 | |
| 259 Browser* ExtensionTabUtil::GetBrowserFromWindowID( | |
| 260 ChromeAsyncExtensionFunction* function, | |
| 261 int window_id, | |
| 262 std::string* error) { | |
| 263 if (window_id == extension_misc::kCurrentWindowId) { | |
| 264 Browser* result = function->GetCurrentBrowser(); | |
| 265 if (!result || !result->window()) { | |
| 266 if (error) | |
| 267 *error = keys::kNoCurrentWindowError; | |
| 268 return NULL; | |
| 269 } | |
| 270 return result; | |
| 271 } else { | |
| 272 return GetBrowserInProfileWithId(function->GetProfile(), | |
| 273 window_id, | |
| 274 function->include_incognito(), | |
| 275 error); | |
| 276 } | |
| 277 } | |
| 278 | |
| 60 int ExtensionTabUtil::GetWindowId(const Browser* browser) { | 279 int ExtensionTabUtil::GetWindowId(const Browser* browser) { |
| 61 return browser->session_id().id(); | 280 return browser->session_id().id(); |
| 62 } | 281 } |
| 63 | 282 |
| 64 int ExtensionTabUtil::GetWindowIdOfTabStripModel( | 283 int ExtensionTabUtil::GetWindowIdOfTabStripModel( |
| 65 const TabStripModel* tab_strip_model) { | 284 const TabStripModel* tab_strip_model) { |
| 66 for (chrome::BrowserIterator it; !it.done(); it.Next()) { | 285 for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
| 67 if (it->tab_strip_model() == tab_strip_model) | 286 if (it->tab_strip_model() == tab_strip_model) |
| 68 return GetWindowId(*it); | 287 return GetWindowId(*it); |
| 69 } | 288 } |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 content::PAGE_TRANSITION_LINK, | 573 content::PAGE_TRANSITION_LINK, |
| 355 false); | 574 false); |
| 356 browser->OpenURL(params); | 575 browser->OpenURL(params); |
| 357 browser->window()->Show(); | 576 browser->window()->Show(); |
| 358 WebContents* web_contents = | 577 WebContents* web_contents = |
| 359 browser->tab_strip_model()->GetActiveWebContents(); | 578 browser->tab_strip_model()->GetActiveWebContents(); |
| 360 web_contents->GetDelegate()->ActivateContents(web_contents); | 579 web_contents->GetDelegate()->ActivateContents(web_contents); |
| 361 } | 580 } |
| 362 | 581 |
| 363 } // namespace extensions | 582 } // namespace extensions |
| OLD | NEW |