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 |