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 and will be set with an |
| 64 // appropriate 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); |
| 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 |