| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/background/background_contents_service.h" | 5 #include "chrome/browser/background/background_contents_service.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| 11 #include "base/values.h" | 11 #include "base/values.h" |
| 12 #include "chrome/browser/background/background_contents_service_factory.h" | 12 #include "chrome/browser/background/background_contents_service_factory.h" |
| 13 #include "chrome/browser/browser_process.h" | 13 #include "chrome/browser/browser_process.h" |
| 14 #include "chrome/browser/extensions/extension_host.h" | 14 #include "chrome/browser/extensions/extension_host.h" |
| 15 #include "chrome/browser/extensions/extension_service.h" | 15 #include "chrome/browser/extensions/extension_service.h" |
| 16 #include "chrome/browser/notifications/desktop_notification_service.h" | 16 #include "chrome/browser/notifications/desktop_notification_service.h" |
| 17 #include "chrome/browser/notifications/notification.h" | 17 #include "chrome/browser/notifications/notification.h" |
| 18 #include "chrome/browser/notifications/notification_ui_manager.h" | 18 #include "chrome/browser/notifications/notification_ui_manager.h" |
| 19 #include "chrome/browser/prefs/pref_service.h" | 19 #include "chrome/browser/prefs/pref_service.h" |
| 20 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 20 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| 21 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
| 22 #include "chrome/browser/ui/browser.h" | 22 #include "chrome/browser/ui/browser.h" |
| 23 #include "chrome/browser/ui/browser_list.h" | 23 #include "chrome/browser/ui/browser_list.h" |
| 24 #include "chrome/common/chrome_notification_types.h" |
| 24 #include "chrome/common/chrome_switches.h" | 25 #include "chrome/common/chrome_switches.h" |
| 25 #include "chrome/common/extensions/extension.h" | 26 #include "chrome/common/extensions/extension.h" |
| 26 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
| 27 #include "content/browser/renderer_host/render_view_host.h" | 28 #include "content/browser/renderer_host/render_view_host.h" |
| 28 #include "content/browser/site_instance.h" | 29 #include "content/browser/site_instance.h" |
| 29 #include "content/browser/tab_contents/tab_contents.h" | 30 #include "content/browser/tab_contents/tab_contents.h" |
| 30 #include "content/common/notification_service.h" | 31 #include "content/common/notification_service.h" |
| 31 #include "content/common/notification_type.h" | |
| 32 #include "grit/generated_resources.h" | 32 #include "grit/generated_resources.h" |
| 33 #include "ui/base/l10n/l10n_util.h" | 33 #include "ui/base/l10n/l10n_util.h" |
| 34 | 34 |
| 35 namespace { | 35 namespace { |
| 36 | 36 |
| 37 const char kNotificationPrefix[] = "app.background.crashed."; | 37 const char kNotificationPrefix[] = "app.background.crashed."; |
| 38 | 38 |
| 39 void CloseBalloon(const std::string id) { | 39 void CloseBalloon(const std::string id) { |
| 40 g_browser_process->notification_ui_manager()->CancelById(id); | 40 g_browser_process->notification_ui_manager()->CancelById(id); |
| 41 } | 41 } |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 { | 152 { |
| 153 std::vector<BackgroundContents*> contents; | 153 std::vector<BackgroundContents*> contents; |
| 154 for (BackgroundContentsMap::const_iterator it = contents_map_.begin(); | 154 for (BackgroundContentsMap::const_iterator it = contents_map_.begin(); |
| 155 it != contents_map_.end(); ++it) | 155 it != contents_map_.end(); ++it) |
| 156 contents.push_back(it->second.contents); | 156 contents.push_back(it->second.contents); |
| 157 return contents; | 157 return contents; |
| 158 } | 158 } |
| 159 | 159 |
| 160 void BackgroundContentsService::StartObserving(Profile* profile) { | 160 void BackgroundContentsService::StartObserving(Profile* profile) { |
| 161 // On startup, load our background pages after extension-apps have loaded. | 161 // On startup, load our background pages after extension-apps have loaded. |
| 162 registrar_.Add(this, NotificationType::EXTENSIONS_READY, | 162 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, |
| 163 Source<Profile>(profile)); | 163 Source<Profile>(profile)); |
| 164 | 164 |
| 165 // Track the lifecycle of all BackgroundContents in the system to allow us | 165 // Track the lifecycle of all BackgroundContents in the system to allow us |
| 166 // to store an up-to-date list of the urls. Start tracking contents when they | 166 // to store an up-to-date list of the urls. Start tracking contents when they |
| 167 // have been opened via CreateBackgroundContents(), and stop tracking them | 167 // have been opened via CreateBackgroundContents(), and stop tracking them |
| 168 // when they are closed by script. | 168 // when they are closed by script. |
| 169 registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_CLOSED, | 169 registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED, |
| 170 Source<Profile>(profile)); | 170 Source<Profile>(profile)); |
| 171 | 171 |
| 172 // Stop tracking BackgroundContents when they have been deleted (happens | 172 // Stop tracking BackgroundContents when they have been deleted (happens |
| 173 // during shutdown or if the render process dies). | 173 // during shutdown or if the render process dies). |
| 174 registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_DELETED, | 174 registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED, |
| 175 Source<Profile>(profile)); | 175 Source<Profile>(profile)); |
| 176 | 176 |
| 177 // Track when the BackgroundContents navigates to a new URL so we can update | 177 // Track when the BackgroundContents navigates to a new URL so we can update |
| 178 // our persisted information as appropriate. | 178 // our persisted information as appropriate. |
| 179 registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_NAVIGATED, | 179 registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED, |
| 180 Source<Profile>(profile)); | 180 Source<Profile>(profile)); |
| 181 | 181 |
| 182 // Listen for new extension installs so that we can load any associated | 182 // Listen for new extension installs so that we can load any associated |
| 183 // background page. | 183 // background page. |
| 184 registrar_.Add(this, NotificationType::EXTENSION_LOADED, | 184 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
| 185 Source<Profile>(profile)); | 185 Source<Profile>(profile)); |
| 186 | 186 |
| 187 // Track when the extensions crash so that the user can be notified | 187 // Track when the extensions crash so that the user can be notified |
| 188 // about it, and the crashed contents can be restarted. | 188 // about it, and the crashed contents can be restarted. |
| 189 registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED, | 189 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, |
| 190 Source<Profile>(profile)); | 190 Source<Profile>(profile)); |
| 191 registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_TERMINATED, | 191 registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED, |
| 192 Source<Profile>(profile)); | 192 Source<Profile>(profile)); |
| 193 | 193 |
| 194 // Listen for extensions to be unloaded so we can shutdown associated | 194 // Listen for extensions to be unloaded so we can shutdown associated |
| 195 // BackgroundContents. | 195 // BackgroundContents. |
| 196 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, | 196 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 197 Source<Profile>(profile)); | 197 Source<Profile>(profile)); |
| 198 | 198 |
| 199 // Make sure the extension-crash balloons are removed when the extension is | 199 // Make sure the extension-crash balloons are removed when the extension is |
| 200 // uninstalled/reloaded. We cannot do this from UNLOADED since a crashed | 200 // uninstalled/reloaded. We cannot do this from UNLOADED since a crashed |
| 201 // extension is unloaded immediately after the crash, not when user reloads or | 201 // extension is unloaded immediately after the crash, not when user reloads or |
| 202 // uninstalls the extension. | 202 // uninstalls the extension. |
| 203 registrar_.Add(this, NotificationType::EXTENSION_UNINSTALLED, | 203 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, |
| 204 Source<Profile>(profile)); | 204 Source<Profile>(profile)); |
| 205 } | 205 } |
| 206 | 206 |
| 207 void BackgroundContentsService::Observe(NotificationType type, | 207 void BackgroundContentsService::Observe(int type, |
| 208 const NotificationSource& source, | 208 const NotificationSource& source, |
| 209 const NotificationDetails& details) { | 209 const NotificationDetails& details) { |
| 210 switch (type.value) { | 210 switch (type) { |
| 211 case NotificationType::EXTENSIONS_READY: | 211 case chrome::NOTIFICATION_EXTENSIONS_READY: |
| 212 LoadBackgroundContentsFromManifests(Source<Profile>(source).ptr()); | 212 LoadBackgroundContentsFromManifests(Source<Profile>(source).ptr()); |
| 213 LoadBackgroundContentsFromPrefs(Source<Profile>(source).ptr()); | 213 LoadBackgroundContentsFromPrefs(Source<Profile>(source).ptr()); |
| 214 break; | 214 break; |
| 215 case NotificationType::BACKGROUND_CONTENTS_DELETED: | 215 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED: |
| 216 BackgroundContentsShutdown(Details<BackgroundContents>(details).ptr()); | 216 BackgroundContentsShutdown(Details<BackgroundContents>(details).ptr()); |
| 217 break; | 217 break; |
| 218 case NotificationType::BACKGROUND_CONTENTS_CLOSED: | 218 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED: |
| 219 DCHECK(IsTracked(Details<BackgroundContents>(details).ptr())); | 219 DCHECK(IsTracked(Details<BackgroundContents>(details).ptr())); |
| 220 UnregisterBackgroundContents(Details<BackgroundContents>(details).ptr()); | 220 UnregisterBackgroundContents(Details<BackgroundContents>(details).ptr()); |
| 221 break; | 221 break; |
| 222 case NotificationType::BACKGROUND_CONTENTS_NAVIGATED: { | 222 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED: { |
| 223 DCHECK(IsTracked(Details<BackgroundContents>(details).ptr())); | 223 DCHECK(IsTracked(Details<BackgroundContents>(details).ptr())); |
| 224 | 224 |
| 225 // Do not register in the pref if the extension has a manifest-specified | 225 // Do not register in the pref if the extension has a manifest-specified |
| 226 // background page. | 226 // background page. |
| 227 BackgroundContents* bgcontents = | 227 BackgroundContents* bgcontents = |
| 228 Details<BackgroundContents>(details).ptr(); | 228 Details<BackgroundContents>(details).ptr(); |
| 229 Profile* profile = Source<Profile>(source).ptr(); | 229 Profile* profile = Source<Profile>(source).ptr(); |
| 230 const string16& appid = GetParentApplicationId(bgcontents); | 230 const string16& appid = GetParentApplicationId(bgcontents); |
| 231 ExtensionService* extension_service = profile->GetExtensionService(); | 231 ExtensionService* extension_service = profile->GetExtensionService(); |
| 232 // extension_service can be NULL when running tests. | 232 // extension_service can be NULL when running tests. |
| 233 if (extension_service) { | 233 if (extension_service) { |
| 234 const Extension* extension = | 234 const Extension* extension = |
| 235 extension_service->GetExtensionById(UTF16ToUTF8(appid), false); | 235 extension_service->GetExtensionById(UTF16ToUTF8(appid), false); |
| 236 if (extension && extension->background_url().is_valid()) | 236 if (extension && extension->background_url().is_valid()) |
| 237 break; | 237 break; |
| 238 } | 238 } |
| 239 RegisterBackgroundContents(bgcontents); | 239 RegisterBackgroundContents(bgcontents); |
| 240 break; | 240 break; |
| 241 } | 241 } |
| 242 case NotificationType::EXTENSION_LOADED: { | 242 case chrome::NOTIFICATION_EXTENSION_LOADED: { |
| 243 const Extension* extension = Details<const Extension>(details).ptr(); | 243 const Extension* extension = Details<const Extension>(details).ptr(); |
| 244 Profile* profile = Source<Profile>(source).ptr(); | 244 Profile* profile = Source<Profile>(source).ptr(); |
| 245 if (extension->is_hosted_app() && | 245 if (extension->is_hosted_app() && |
| 246 extension->background_url().is_valid()) { | 246 extension->background_url().is_valid()) { |
| 247 // If there is a background page specified in the manifest for a hosted | 247 // If there is a background page specified in the manifest for a hosted |
| 248 // app, then blow away registered urls in the pref. | 248 // app, then blow away registered urls in the pref. |
| 249 ShutdownAssociatedBackgroundContents(ASCIIToUTF16(extension->id())); | 249 ShutdownAssociatedBackgroundContents(ASCIIToUTF16(extension->id())); |
| 250 | 250 |
| 251 ExtensionService* service = profile->GetExtensionService(); | 251 ExtensionService* service = profile->GetExtensionService(); |
| 252 if (service && service->is_ready()) { | 252 if (service && service->is_ready()) { |
| 253 // Now load the manifest-specified background page. If service isn't | 253 // Now load the manifest-specified background page. If service isn't |
| 254 // ready, then the background page will be loaded from the | 254 // ready, then the background page will be loaded from the |
| 255 // EXTENSIONS_READY callback. | 255 // EXTENSIONS_READY callback. |
| 256 LoadBackgroundContents(profile, extension->background_url(), | 256 LoadBackgroundContents(profile, extension->background_url(), |
| 257 ASCIIToUTF16("background"), UTF8ToUTF16(extension->id())); | 257 ASCIIToUTF16("background"), UTF8ToUTF16(extension->id())); |
| 258 } | 258 } |
| 259 } | 259 } |
| 260 | 260 |
| 261 // Remove any "This extension has crashed" balloons. | 261 // Remove any "This extension has crashed" balloons. |
| 262 ScheduleCloseBalloon(extension->id()); | 262 ScheduleCloseBalloon(extension->id()); |
| 263 break; | 263 break; |
| 264 } | 264 } |
| 265 case NotificationType::EXTENSION_PROCESS_TERMINATED: | 265 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: |
| 266 case NotificationType::BACKGROUND_CONTENTS_TERMINATED: { | 266 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED: { |
| 267 Profile* profile = Source<Profile>(source).ptr(); | 267 Profile* profile = Source<Profile>(source).ptr(); |
| 268 const Extension* extension = NULL; | 268 const Extension* extension = NULL; |
| 269 if (type.value == NotificationType::BACKGROUND_CONTENTS_TERMINATED) { | 269 if (type == chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED) { |
| 270 BackgroundContents* bg = | 270 BackgroundContents* bg = |
| 271 Details<BackgroundContents>(details).ptr(); | 271 Details<BackgroundContents>(details).ptr(); |
| 272 std::string extension_id = UTF16ToASCII( | 272 std::string extension_id = UTF16ToASCII( |
| 273 BackgroundContentsServiceFactory::GetForProfile(profile)-> | 273 BackgroundContentsServiceFactory::GetForProfile(profile)-> |
| 274 GetParentApplicationId(bg)); | 274 GetParentApplicationId(bg)); |
| 275 extension = | 275 extension = |
| 276 profile->GetExtensionService()->GetExtensionById(extension_id, false); | 276 profile->GetExtensionService()->GetExtensionById(extension_id, false); |
| 277 } else { | 277 } else { |
| 278 ExtensionHost* extension_host = Details<ExtensionHost>(details).ptr(); | 278 ExtensionHost* extension_host = Details<ExtensionHost>(details).ptr(); |
| 279 extension = extension_host->extension(); | 279 extension = extension_host->extension(); |
| 280 } | 280 } |
| 281 if (!extension) | 281 if (!extension) |
| 282 break; | 282 break; |
| 283 | 283 |
| 284 // When an extension crashes, EXTENSION_PROCESS_TERMINATED is followed by | 284 // When an extension crashes, EXTENSION_PROCESS_TERMINATED is followed by |
| 285 // an EXTENSION_UNLOADED notification. This UNLOADED signal causes all the | 285 // an EXTENSION_UNLOADED notification. This UNLOADED signal causes all the |
| 286 // notifications for this extension to be cancelled by | 286 // notifications for this extension to be cancelled by |
| 287 // DesktopNotificationService. For this reason, instead of showing the | 287 // DesktopNotificationService. For this reason, instead of showing the |
| 288 // balloon right now, we schedule it to show a little later. | 288 // balloon right now, we schedule it to show a little later. |
| 289 MessageLoop::current()->PostTask(FROM_HERE, | 289 MessageLoop::current()->PostTask(FROM_HERE, |
| 290 NewRunnableFunction(&ShowBalloon, extension, profile)); | 290 NewRunnableFunction(&ShowBalloon, extension, profile)); |
| 291 break; | 291 break; |
| 292 } | 292 } |
| 293 case NotificationType::EXTENSION_UNLOADED: | 293 case chrome::NOTIFICATION_EXTENSION_UNLOADED: |
| 294 switch (Details<UnloadedExtensionInfo>(details)->reason) { | 294 switch (Details<UnloadedExtensionInfo>(details)->reason) { |
| 295 case UnloadedExtensionInfo::DISABLE: // Intentionally fall through. | 295 case UnloadedExtensionInfo::DISABLE: // Intentionally fall through. |
| 296 case UnloadedExtensionInfo::UNINSTALL: | 296 case UnloadedExtensionInfo::UNINSTALL: |
| 297 ShutdownAssociatedBackgroundContents( | 297 ShutdownAssociatedBackgroundContents( |
| 298 ASCIIToUTF16( | 298 ASCIIToUTF16( |
| 299 Details<UnloadedExtensionInfo>(details)->extension->id())); | 299 Details<UnloadedExtensionInfo>(details)->extension->id())); |
| 300 break; | 300 break; |
| 301 case UnloadedExtensionInfo::UPDATE: { | 301 case UnloadedExtensionInfo::UPDATE: { |
| 302 // If there is a manifest specified background page, then shut it down | 302 // If there is a manifest specified background page, then shut it down |
| 303 // here, since if the updated extension still has the background page, | 303 // here, since if the updated extension still has the background page, |
| 304 // then it will be loaded from LOADED callback. Otherwise, leave | 304 // then it will be loaded from LOADED callback. Otherwise, leave |
| 305 // BackgroundContents in place. | 305 // BackgroundContents in place. |
| 306 const Extension* extension = | 306 const Extension* extension = |
| 307 Details<UnloadedExtensionInfo>(details)->extension; | 307 Details<UnloadedExtensionInfo>(details)->extension; |
| 308 if (extension->background_url().is_valid()) | 308 if (extension->background_url().is_valid()) |
| 309 ShutdownAssociatedBackgroundContents(ASCIIToUTF16(extension->id())); | 309 ShutdownAssociatedBackgroundContents(ASCIIToUTF16(extension->id())); |
| 310 break; | 310 break; |
| 311 } | 311 } |
| 312 default: | 312 default: |
| 313 NOTREACHED(); | 313 NOTREACHED(); |
| 314 ShutdownAssociatedBackgroundContents( | 314 ShutdownAssociatedBackgroundContents( |
| 315 ASCIIToUTF16( | 315 ASCIIToUTF16( |
| 316 Details<UnloadedExtensionInfo>(details)->extension->id())); | 316 Details<UnloadedExtensionInfo>(details)->extension->id())); |
| 317 break; | 317 break; |
| 318 } | 318 } |
| 319 break; | 319 break; |
| 320 | 320 |
| 321 case NotificationType::EXTENSION_UNINSTALLED: { | 321 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: { |
| 322 // Remove any "This extension has crashed" balloons. | 322 // Remove any "This extension has crashed" balloons. |
| 323 const UninstalledExtensionInfo* uninstalled_extension = | 323 const UninstalledExtensionInfo* uninstalled_extension = |
| 324 Details<const UninstalledExtensionInfo>(details).ptr(); | 324 Details<const UninstalledExtensionInfo>(details).ptr(); |
| 325 ScheduleCloseBalloon(uninstalled_extension->extension_id); | 325 ScheduleCloseBalloon(uninstalled_extension->extension_id); |
| 326 break; | 326 break; |
| 327 } | 327 } |
| 328 | 328 |
| 329 default: | 329 default: |
| 330 NOTREACHED(); | 330 NOTREACHED(); |
| 331 break; | 331 break; |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 const string16& application_id) { | 460 const string16& application_id) { |
| 461 BackgroundContents* contents = new BackgroundContents(site, routing_id, this); | 461 BackgroundContents* contents = new BackgroundContents(site, routing_id, this); |
| 462 | 462 |
| 463 // Register the BackgroundContents internally, then send out a notification | 463 // Register the BackgroundContents internally, then send out a notification |
| 464 // to external listeners. | 464 // to external listeners. |
| 465 BackgroundContentsOpenedDetails details = {contents, | 465 BackgroundContentsOpenedDetails details = {contents, |
| 466 frame_name, | 466 frame_name, |
| 467 application_id}; | 467 application_id}; |
| 468 BackgroundContentsOpened(&details); | 468 BackgroundContentsOpened(&details); |
| 469 NotificationService::current()->Notify( | 469 NotificationService::current()->Notify( |
| 470 NotificationType::BACKGROUND_CONTENTS_OPENED, | 470 chrome::NOTIFICATION_BACKGROUND_CONTENTS_OPENED, |
| 471 Source<Profile>(profile), | 471 Source<Profile>(profile), |
| 472 Details<BackgroundContentsOpenedDetails>(&details)); | 472 Details<BackgroundContentsOpenedDetails>(&details)); |
| 473 return contents; | 473 return contents; |
| 474 } | 474 } |
| 475 | 475 |
| 476 void BackgroundContentsService::RegisterBackgroundContents( | 476 void BackgroundContentsService::RegisterBackgroundContents( |
| 477 BackgroundContents* background_contents) { | 477 BackgroundContents* background_contents) { |
| 478 DCHECK(IsTracked(background_contents)); | 478 DCHECK(IsTracked(background_contents)); |
| 479 if (!prefs_) | 479 if (!prefs_) |
| 480 return; | 480 return; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 TabContents* new_contents, | 571 TabContents* new_contents, |
| 572 WindowOpenDisposition disposition, | 572 WindowOpenDisposition disposition, |
| 573 const gfx::Rect& initial_pos, | 573 const gfx::Rect& initial_pos, |
| 574 bool user_gesture) { | 574 bool user_gesture) { |
| 575 Browser* browser = BrowserList::GetLastActiveWithProfile( | 575 Browser* browser = BrowserList::GetLastActiveWithProfile( |
| 576 new_contents->profile()); | 576 new_contents->profile()); |
| 577 if (!browser) | 577 if (!browser) |
| 578 return; | 578 return; |
| 579 browser->AddTabContents(new_contents, disposition, initial_pos, user_gesture); | 579 browser->AddTabContents(new_contents, disposition, initial_pos, user_gesture); |
| 580 } | 580 } |
| OLD | NEW |