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/background/background_contents_service.h" | 5 #include "chrome/browser/background/background_contents_service.h" |
6 | 6 |
7 #include "apps/app_load_service.h" | 7 #include "apps/app_load_service.h" |
8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 #include "ui/gfx/image/image.h" | 47 #include "ui/gfx/image/image.h" |
48 | 48 |
49 using content::SiteInstance; | 49 using content::SiteInstance; |
50 using content::WebContents; | 50 using content::WebContents; |
51 using extensions::BackgroundInfo; | 51 using extensions::BackgroundInfo; |
52 using extensions::Extension; | 52 using extensions::Extension; |
53 using extensions::UnloadedExtensionInfo; | 53 using extensions::UnloadedExtensionInfo; |
54 | 54 |
55 namespace { | 55 namespace { |
56 | 56 |
57 const char kNotificationPrefix[] = "app.background.crashed."; | 57 const char kCrashNotificationPrefix[] = "app.background.crashed."; |
58 const char kMisbehaveNotificationPrefix[] = "app.background.misbehaved."; | |
59 | |
60 /** No. of recent crashes required to trigger an extension-misbehave popup **/ | |
bartfab (slow)
2013/08/26 13:26:53
Nit 1: Do not use abbreviations: No. => Number
Nit
anitawoodruff
2013/08/26 21:45:23
Done.
| |
61 const unsigned int kNCrashesShouldNotify = 5; | |
bartfab (slow)
2013/08/26 13:26:53
Nit: This constant does not follow the usual Chrom
anitawoodruff
2013/08/26 21:45:23
Done.
| |
58 | 62 |
59 void CloseBalloon(const std::string& id) { | 63 void CloseBalloon(const std::string& id) { |
60 g_browser_process->notification_ui_manager()->CancelById(id); | 64 g_browser_process->notification_ui_manager()->CancelById(id); |
61 } | 65 } |
62 | 66 |
63 void ScheduleCloseBalloon(const std::string& extension_id) { | 67 void ScheduleCloseBalloon(const std::string& id) { |
bartfab (slow)
2013/08/26 13:26:53
Nit 1: "extension_id" identifies an extension; eas
anitawoodruff
2013/08/26 21:45:23
Done - is prefixed_extension_id ok? Or should I ma
bartfab (slow)
2013/08/27 09:21:29
|prefixed_extension_id| is an accurate description
anitawoodruff
2013/08/27 10:00:51
Done.
| |
64 if (!base::MessageLoop::current()) // For unit_tests | 68 if (!base::MessageLoop::current()) // For unit_tests |
65 return; | 69 return; |
66 base::MessageLoop::current()->PostTask( | 70 base::MessageLoop::current()->PostTask( |
67 FROM_HERE, base::Bind(&CloseBalloon, kNotificationPrefix + extension_id)); | 71 FROM_HERE, base::Bind(&CloseBalloon, id)); |
72 } | |
73 | |
74 void ScheduleCloseCrashBalloon(const std::string& extension_id) { | |
75 ScheduleCloseBalloon(kCrashNotificationPrefix + extension_id); | |
76 } | |
77 | |
78 void ScheduleCloseBalloons(const std::string& extension_id) { | |
79 ScheduleCloseBalloon(kMisbehaveNotificationPrefix + extension_id); | |
80 ScheduleCloseBalloon(kCrashNotificationPrefix + extension_id); | |
68 } | 81 } |
69 | 82 |
70 class CrashNotificationDelegate : public NotificationDelegate { | 83 class CrashNotificationDelegate : public NotificationDelegate { |
71 public: | 84 public: |
72 CrashNotificationDelegate(Profile* profile, | 85 CrashNotificationDelegate(Profile* profile, |
73 const Extension* extension) | 86 const Extension* extension) |
74 : profile_(profile), | 87 : profile_(profile), |
75 is_hosted_app_(extension->is_hosted_app()), | 88 is_hosted_app_(extension->is_hosted_app()), |
76 is_platform_app_(extension->is_platform_app()), | 89 is_platform_app_(extension->is_platform_app()), |
77 extension_id_(extension->id()) { | 90 extension_id_(extension->id()) { |
(...skipping 22 matching lines...) Expand all Loading... | |
100 service->LoadBackgroundContentsForExtension(profile_, | 113 service->LoadBackgroundContentsForExtension(profile_, |
101 copied_extension_id); | 114 copied_extension_id); |
102 } else if (is_platform_app_) { | 115 } else if (is_platform_app_) { |
103 apps::AppLoadService::Get(profile_)-> | 116 apps::AppLoadService::Get(profile_)-> |
104 RestartApplication(copied_extension_id); | 117 RestartApplication(copied_extension_id); |
105 } else { | 118 } else { |
106 extensions::ExtensionSystem::Get(profile_)->extension_service()-> | 119 extensions::ExtensionSystem::Get(profile_)->extension_service()-> |
107 ReloadExtension(copied_extension_id); | 120 ReloadExtension(copied_extension_id); |
108 } | 121 } |
109 | 122 |
110 // Closing the balloon here should be OK, but it causes a crash on Mac | 123 // Closing the balloon here should be OK, but it causes a crash on Mac |
bartfab (slow)
2013/08/26 13:26:53
Nit: "the balloon" is no longer unambiguous.
anitawoodruff
2013/08/26 21:45:23
Done.
| |
111 // http://crbug.com/78167 | 124 // http://crbug.com/78167 |
112 ScheduleCloseBalloon(copied_extension_id); | 125 ScheduleCloseCrashBalloon(copied_extension_id); |
113 } | 126 } |
114 | 127 |
115 virtual bool HasClickedListener() OVERRIDE { return true; } | 128 virtual bool HasClickedListener() OVERRIDE { return true; } |
116 | 129 |
117 virtual std::string id() const OVERRIDE { | 130 virtual std::string id() const OVERRIDE { |
118 return kNotificationPrefix + extension_id_; | 131 return kCrashNotificationPrefix + extension_id_; |
119 } | 132 } |
120 | 133 |
121 virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE { | 134 virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE { |
122 return NULL; | 135 return NULL; |
123 } | 136 } |
124 | 137 |
125 private: | 138 private: |
126 virtual ~CrashNotificationDelegate() {} | 139 virtual ~CrashNotificationDelegate() {} |
127 | 140 |
128 Profile* profile_; | 141 Profile* profile_; |
129 bool is_hosted_app_; | 142 bool is_hosted_app_; |
130 bool is_platform_app_; | 143 bool is_platform_app_; |
131 std::string extension_id_; | 144 std::string extension_id_; |
132 | 145 |
133 DISALLOW_COPY_AND_ASSIGN(CrashNotificationDelegate); | 146 DISALLOW_COPY_AND_ASSIGN(CrashNotificationDelegate); |
134 }; | 147 }; |
135 | 148 |
149 class MisbehaveNotificationDelegate : public NotificationDelegate { | |
bartfab (slow)
2013/08/26 13:26:53
Nit 1: #include "chrome/browser/notifications/noti
anitawoodruff
2013/08/26 21:45:23
Done.
| |
150 public: | |
151 explicit MisbehaveNotificationDelegate(const Extension* extension) | |
152 : extension_id_(extension->id()) { | |
153 } | |
154 | |
155 virtual void Display() OVERRIDE {} | |
156 | |
157 virtual void Error() OVERRIDE {} | |
158 | |
159 virtual void Close(bool by_user) OVERRIDE {} | |
160 | |
161 virtual void Click() OVERRIDE {} | |
162 | |
163 virtual bool HasClickedListener() OVERRIDE { return true; } | |
164 | |
165 virtual std::string id() const OVERRIDE { | |
166 return kMisbehaveNotificationPrefix + extension_id_; | |
167 } | |
168 | |
169 virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE { | |
170 return NULL; | |
171 } | |
172 | |
173 private: | |
174 virtual ~MisbehaveNotificationDelegate() {} | |
175 | |
176 std::string extension_id_; | |
177 | |
178 DISALLOW_COPY_AND_ASSIGN(MisbehaveNotificationDelegate); | |
179 }; | |
180 | |
136 #if defined(ENABLE_NOTIFICATIONS) | 181 #if defined(ENABLE_NOTIFICATIONS) |
137 void NotificationImageReady( | 182 void NotificationImageReady( |
138 const std::string extension_name, | 183 const std::string extension_name, |
139 const string16 message, | 184 const string16 message, |
140 const GURL extension_url, | 185 const GURL extension_url, |
141 scoped_refptr<CrashNotificationDelegate> delegate, | 186 scoped_refptr<NotificationDelegate> delegate, |
142 Profile* profile, | 187 Profile* profile, |
143 const gfx::Image& icon) { | 188 const gfx::Image& icon) { |
144 gfx::Image notification_icon(icon); | 189 gfx::Image notification_icon(icon); |
145 if (icon.IsEmpty()) { | 190 if (icon.IsEmpty()) { |
146 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 191 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
147 notification_icon = rb.GetImageNamed(IDR_EXTENSION_DEFAULT_ICON); | 192 notification_icon = rb.GetImageNamed(IDR_EXTENSION_DEFAULT_ICON); |
148 } | 193 } |
149 string16 title; // no notification title | 194 string16 title; // no notification title |
150 DesktopNotificationService::AddIconNotification(extension_url, | 195 DesktopNotificationService::AddIconNotification(extension_url, |
151 title, | 196 title, |
152 message, | 197 message, |
153 notification_icon, | 198 notification_icon, |
154 string16(), | 199 string16(), |
155 delegate.get(), | 200 delegate.get(), |
156 profile); | 201 profile); |
157 } | 202 } |
158 #endif | 203 #endif |
159 | 204 |
160 void ShowBalloon(const Extension* extension, Profile* profile) { | 205 void ReloadExtension(const Extension* extension, Profile* profile) { |
206 extensions::ExtensionSystem* extensionSystem = | |
207 extensions::ExtensionSystem::Get(profile); | |
208 if (extensionSystem && extensionSystem->extension_service()) | |
209 extensionSystem->extension_service()->ReloadExtension(extension->id()); | |
210 } | |
211 | |
212 void ShowBalloon(const Extension* extension, Profile* profile, bool isForced) { | |
bartfab (slow)
2013/08/26 13:26:53
Nit: Add a comment explaining the parameters. "isF
anitawoodruff
2013/08/26 21:45:23
Done.
| |
161 #if defined(ENABLE_NOTIFICATIONS) | 213 #if defined(ENABLE_NOTIFICATIONS) |
162 string16 message = l10n_util::GetStringFUTF16( | 214 string16 message; |
163 extension->is_app() ? IDS_BACKGROUND_CRASHED_APP_BALLOON_MESSAGE : | 215 if (isForced) { |
164 IDS_BACKGROUND_CRASHED_EXTENSION_BALLOON_MESSAGE, | 216 message = l10n_util::GetStringFUTF16( |
165 UTF8ToUTF16(extension->name())); | 217 extension->is_app() ? |
166 | 218 IDS_BACKGROUND_MISBEHAVING_APP_BALLOON_MESSAGE : |
219 IDS_BACKGROUND_MISBEHAVING_EXTENSION_BALLOON_MESSAGE, | |
220 UTF8ToUTF16(extension->name())); | |
221 } else { | |
222 message = l10n_util::GetStringFUTF16( | |
223 extension->is_app() ? IDS_BACKGROUND_CRASHED_APP_BALLOON_MESSAGE : | |
224 IDS_BACKGROUND_CRASHED_EXTENSION_BALLOON_MESSAGE, | |
225 UTF8ToUTF16(extension->name())); | |
226 } | |
167 extension_misc::ExtensionIcons size(extension_misc::EXTENSION_ICON_MEDIUM); | 227 extension_misc::ExtensionIcons size(extension_misc::EXTENSION_ICON_MEDIUM); |
168 extensions::ExtensionResource resource = | 228 extensions::ExtensionResource resource = |
169 extensions::IconsInfo::GetIconResource( | 229 extensions::IconsInfo::GetIconResource( |
170 extension, size, ExtensionIconSet::MATCH_SMALLER); | 230 extension, size, ExtensionIconSet::MATCH_SMALLER); |
171 scoped_refptr<CrashNotificationDelegate> delegate = | 231 scoped_refptr<NotificationDelegate> delegate = NULL; |
bartfab (slow)
2013/08/26 13:26:53
Nit 1: You could set the delegate in the if-block
anitawoodruff
2013/08/26 21:45:23
Done.
| |
172 new CrashNotificationDelegate(profile, extension); | 232 if (isForced) |
233 delegate = new MisbehaveNotificationDelegate(extension); | |
234 else | |
235 delegate = new CrashNotificationDelegate(profile, extension); | |
173 // We can't just load the image in the Observe method below because, despite | 236 // We can't just load the image in the Observe method below because, despite |
174 // what this method is called, it may call the callback synchronously. | 237 // what this method is called, it may call the callback synchronously. |
175 // However, it's possible that the extension went away during the interim, | 238 // However, it's possible that the extension went away during the interim, |
176 // so we'll bind all the pertinent data here. | 239 // so we'll bind all the pertinent data here. |
177 extensions::ImageLoader::Get(profile)->LoadImageAsync( | 240 extensions::ImageLoader::Get(profile)->LoadImageAsync( |
178 extension, | 241 extension, |
179 resource, | 242 resource, |
180 gfx::Size(size, size), | 243 gfx::Size(size, size), |
181 base::Bind( | 244 base::Bind( |
182 &NotificationImageReady, | 245 &NotificationImageReady, |
(...skipping 15 matching lines...) Expand all Loading... | |
198 // | 261 // |
199 // kRegisteredBackgroundContents: | 262 // kRegisteredBackgroundContents: |
200 // DictionaryValue { | 263 // DictionaryValue { |
201 // <appid_1>: { "url": <url1>, "name": <frame_name> }, | 264 // <appid_1>: { "url": <url1>, "name": <frame_name> }, |
202 // <appid_2>: { "url": <url2>, "name": <frame_name> }, | 265 // <appid_2>: { "url": <url2>, "name": <frame_name> }, |
203 // ... etc ... | 266 // ... etc ... |
204 // } | 267 // } |
205 const char kUrlKey[] = "url"; | 268 const char kUrlKey[] = "url"; |
206 const char kFrameNameKey[] = "name"; | 269 const char kFrameNameKey[] = "name"; |
207 | 270 |
271 /** Delay (in seconds) before restarting a forced extension that crashed **/ | |
bartfab (slow)
2013/08/26 13:26:53
Nit 1: s/forced/force-installed/
Nit 2: Move the c
anitawoodruff
2013/08/26 21:45:23
Done.
| |
272 base::TimeDelta BackgroundContentsService::restart_delay_ = | |
273 base::TimeDelta::FromSeconds(3); | |
274 | |
275 /** Seconds since a crash-reload during which we listen for further crashes **/ | |
bartfab (slow)
2013/08/26 13:26:53
This comment is not quite correct. With the defaul
anitawoodruff
2013/08/26 21:45:23
I know it's not, but I can't for the life of me th
bartfab (slow)
2013/08/27 09:21:29
It is OK to have a long comment if a variable is u
| |
276 base::TimeDelta BackgroundContentsService::crash_window_ = | |
277 base::TimeDelta::FromSeconds(1); | |
278 | |
208 BackgroundContentsService::BackgroundContentsService( | 279 BackgroundContentsService::BackgroundContentsService( |
209 Profile* profile, const CommandLine* command_line) | 280 Profile* profile, const CommandLine* command_line) |
210 : prefs_(NULL) { | 281 : prefs_(NULL) { |
211 // Don't load/store preferences if the proper switch is not enabled, or if | 282 // Don't load/store preferences if the proper switch is not enabled, or if |
212 // the parent profile is incognito. | 283 // the parent profile is incognito. |
213 if (!profile->IsOffTheRecord() && | 284 if (!profile->IsOffTheRecord() && |
214 !command_line->HasSwitch(switches::kDisableRestoreBackgroundContents)) | 285 !command_line->HasSwitch(switches::kDisableRestoreBackgroundContents)) |
215 prefs_ = profile->GetPrefs(); | 286 prefs_ = profile->GetPrefs(); |
216 | 287 |
217 // Listen for events to tell us when to load/unload persisted background | 288 // Listen for events to tell us when to load/unload persisted background |
218 // contents. | 289 // contents. |
219 StartObserving(profile); | 290 StartObserving(profile); |
220 } | 291 } |
221 | 292 |
222 BackgroundContentsService::~BackgroundContentsService() { | 293 BackgroundContentsService::~BackgroundContentsService() { |
223 // BackgroundContents should be shutdown before we go away, as otherwise | 294 // BackgroundContents should be shutdown before we go away, as otherwise |
224 // our browser process refcount will be off. | 295 // our browser process refcount will be off. |
225 DCHECK(contents_map_.empty()); | 296 DCHECK(contents_map_.empty()); |
226 } | 297 } |
227 | 298 |
299 // static | |
300 void BackgroundContentsService::SetCrashDelaysForTesting( | |
301 const base::TimeDelta& restart_delay, const base::TimeDelta& crash_window) { | |
302 restart_delay_ = restart_delay; | |
303 crash_window_ = crash_window; | |
304 } | |
305 | |
228 std::vector<BackgroundContents*> | 306 std::vector<BackgroundContents*> |
229 BackgroundContentsService::GetBackgroundContents() const | 307 BackgroundContentsService::GetBackgroundContents() const |
230 { | 308 { |
231 std::vector<BackgroundContents*> contents; | 309 std::vector<BackgroundContents*> contents; |
232 for (BackgroundContentsMap::const_iterator it = contents_map_.begin(); | 310 for (BackgroundContentsMap::const_iterator it = contents_map_.begin(); |
233 it != contents_map_.end(); ++it) | 311 it != contents_map_.end(); ++it) |
234 contents.push_back(it->second.contents); | 312 contents.push_back(it->second.contents); |
235 return contents; | 313 return contents; |
236 } | 314 } |
237 | 315 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 if (service && service->is_ready()) { | 420 if (service && service->is_ready()) { |
343 // Now load the manifest-specified background page. If service isn't | 421 // Now load the manifest-specified background page. If service isn't |
344 // ready, then the background page will be loaded from the | 422 // ready, then the background page will be loaded from the |
345 // EXTENSIONS_READY callback. | 423 // EXTENSIONS_READY callback. |
346 LoadBackgroundContents(profile, | 424 LoadBackgroundContents(profile, |
347 BackgroundInfo::GetBackgroundURL(extension), | 425 BackgroundInfo::GetBackgroundURL(extension), |
348 ASCIIToUTF16("background"), | 426 ASCIIToUTF16("background"), |
349 UTF8ToUTF16(extension->id())); | 427 UTF8ToUTF16(extension->id())); |
350 } | 428 } |
351 } | 429 } |
352 | |
353 // Remove any "This extension has crashed" balloons. | 430 // Remove any "This extension has crashed" balloons. |
354 ScheduleCloseBalloon(extension->id()); | 431 ScheduleCloseCrashBalloon(extension->id()); |
355 SendChangeNotification(profile); | 432 SendChangeNotification(profile); |
356 break; | 433 break; |
357 } | 434 } |
358 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: | 435 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: |
359 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED: { | 436 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED: { |
360 Profile* profile = content::Source<Profile>(source).ptr(); | 437 Profile* profile = content::Source<Profile>(source).ptr(); |
361 const Extension* extension = NULL; | 438 const Extension* extension = NULL; |
362 if (type == chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED) { | 439 if (type == chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED) { |
363 BackgroundContents* bg = | 440 BackgroundContents* bg = |
364 content::Details<BackgroundContents>(details).ptr(); | 441 content::Details<BackgroundContents>(details).ptr(); |
365 std::string extension_id = UTF16ToASCII( | 442 std::string extension_id = UTF16ToASCII( |
366 BackgroundContentsServiceFactory::GetForProfile(profile)-> | 443 BackgroundContentsServiceFactory::GetForProfile(profile)-> |
367 GetParentApplicationId(bg)); | 444 GetParentApplicationId(bg)); |
368 extension = | 445 extension = |
369 extensions::ExtensionSystem::Get(profile)->extension_service()-> | 446 extensions::ExtensionSystem::Get(profile)->extension_service()-> |
370 GetExtensionById(extension_id, false); | 447 GetExtensionById(extension_id, false); |
371 } else { | 448 } else { |
372 extensions::ExtensionHost* extension_host = | 449 extensions::ExtensionHost* extension_host = |
373 content::Details<extensions::ExtensionHost>(details).ptr(); | 450 content::Details<extensions::ExtensionHost>(details).ptr(); |
374 extension = extension_host->extension(); | 451 extension = extension_host->extension(); |
375 } | 452 } |
376 if (!extension) | 453 if (!extension) |
377 break; | 454 break; |
378 | 455 |
379 // When an extension crashes, EXTENSION_PROCESS_TERMINATED is followed by | 456 // When an extension crashes, EXTENSION_PROCESS_TERMINATED is followed by |
380 // an EXTENSION_UNLOADED notification. This UNLOADED signal causes all the | 457 // an EXTENSION_UNLOADED notification. We post the crash handling code as |
bartfab (slow)
2013/08/26 13:26:53
The previous comment had more information on why p
anitawoodruff
2013/08/26 21:45:23
Done.
| |
381 // notifications for this extension to be cancelled by | 458 // a task here so it is not executed before the EXTENSION_UNLOADED event. |
382 // DesktopNotificationService. For this reason, instead of showing the | 459 bool forceInstalled = |
383 // balloon right now, we schedule it to show a little later. | 460 extension->location() == |
384 base::MessageLoop::current()->PostTask( | 461 extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD; |
385 FROM_HERE, base::Bind(&ShowBalloon, extension, profile)); | 462 if (!forceInstalled) { |
463 // Notify user extension has crashed. | |
464 base::MessageLoop::current()->PostTask( | |
465 FROM_HERE, base::Bind(&ShowBalloon, extension, profile, false)); | |
466 } else { | |
467 // Restart the extension; notify user if crash recurs frequently. | |
bartfab (slow)
2013/08/26 13:26:53
I think this code is complex enough to warrant put
anitawoodruff
2013/08/26 21:45:23
Done.
| |
468 const std::string& id = extension->id(); | |
bartfab (slow)
2013/08/26 13:26:53
Nit: Why not call the variable extension_id?
anitawoodruff
2013/08/26 21:45:23
Done.
| |
469 const bool alreadyNotified = | |
470 misbehaving_extensions_.find(id) != misbehaving_extensions_.end(); | |
471 std::queue<base::TimeTicks>& crashes = extension_crashlog_map_[id]; | |
472 const base::TimeDelta duration = | |
473 kNCrashesShouldNotify * (restart_delay_ + crash_window_); | |
474 if (!alreadyNotified && crashes.size() == (kNCrashesShouldNotify - 1) && | |
bartfab (slow)
2013/08/26 13:26:53
Please put the calculation on its own line and exp
anitawoodruff
2013/08/26 21:45:23
Done.
| |
475 base::TimeTicks::Now() - crashes.front() < duration) { | |
476 base::MessageLoop::current()->PostTask(FROM_HERE, | |
477 base::Bind(&ShowBalloon, extension, profile, true)); | |
478 misbehaving_extensions_.insert(id); | |
479 extension_crashlog_map_.erase(id); | |
480 } else if (!alreadyNotified) { | |
481 while (!crashes.empty() && | |
482 base::TimeTicks::Now() - crashes.front() > duration) { | |
483 crashes.pop(); // Remove old timestamps. | |
484 } | |
485 crashes.push(base::TimeTicks::Now()); | |
486 if (crashes.size() == kNCrashesShouldNotify) | |
487 crashes.pop(); | |
488 } | |
489 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
bartfab (slow)
2013/08/26 13:26:53
This task will run 3s later. What if |extension| o
anitawoodruff
2013/08/26 21:45:23
I traced it through to BrowserContextKeyedBaseFact
bartfab (slow)
2013/08/27 09:21:29
Sounds like both issues may arise - we may end up
| |
490 base::Bind(&ReloadExtension, extension, profile), restart_delay_); | |
491 } | |
386 break; | 492 break; |
387 } | 493 } |
388 case chrome::NOTIFICATION_EXTENSION_UNLOADED: | 494 case chrome::NOTIFICATION_EXTENSION_UNLOADED: |
389 switch (content::Details<UnloadedExtensionInfo>(details)->reason) { | 495 switch (content::Details<UnloadedExtensionInfo>(details)->reason) { |
390 case extension_misc::UNLOAD_REASON_DISABLE: // Fall through. | 496 case extension_misc::UNLOAD_REASON_DISABLE: // Fall through. |
391 case extension_misc::UNLOAD_REASON_TERMINATE: // Fall through. | 497 case extension_misc::UNLOAD_REASON_TERMINATE: // Fall through. |
392 case extension_misc::UNLOAD_REASON_UNINSTALL: // Fall through. | 498 case extension_misc::UNLOAD_REASON_UNINSTALL: // Fall through. |
393 case extension_misc::UNLOAD_REASON_BLACKLIST: | 499 case extension_misc::UNLOAD_REASON_BLACKLIST: |
394 ShutdownAssociatedBackgroundContents( | 500 ShutdownAssociatedBackgroundContents( |
395 ASCIIToUTF16(content::Details<UnloadedExtensionInfo>(details)-> | 501 ASCIIToUTF16(content::Details<UnloadedExtensionInfo>(details)-> |
(...skipping 16 matching lines...) Expand all Loading... | |
412 default: | 518 default: |
413 NOTREACHED(); | 519 NOTREACHED(); |
414 ShutdownAssociatedBackgroundContents( | 520 ShutdownAssociatedBackgroundContents( |
415 ASCIIToUTF16(content::Details<UnloadedExtensionInfo>(details)-> | 521 ASCIIToUTF16(content::Details<UnloadedExtensionInfo>(details)-> |
416 extension->id())); | 522 extension->id())); |
417 break; | 523 break; |
418 } | 524 } |
419 break; | 525 break; |
420 | 526 |
421 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: { | 527 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: { |
528 const std::string& extension_id = | |
529 content::Details<const Extension>(details).ptr()->id(); | |
422 // Remove any "This extension has crashed" balloons. | 530 // Remove any "This extension has crashed" balloons. |
423 ScheduleCloseBalloon( | 531 ScheduleCloseBalloons(extension_id); |
424 content::Details<const Extension>(details).ptr()->id()); | 532 misbehaving_extensions_.erase(extension_id); |
533 extension_crashlog_map_.erase(extension_id); | |
425 break; | 534 break; |
426 } | 535 } |
427 | 536 |
428 default: | 537 default: |
429 NOTREACHED(); | 538 NOTREACHED(); |
430 break; | 539 break; |
431 } | 540 } |
432 } | 541 } |
433 | 542 |
434 // Loads all background contents whose urls have been stored in prefs. | 543 // Loads all background contents whose urls have been stored in prefs. |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
646 } | 755 } |
647 | 756 |
648 void BackgroundContentsService::BackgroundContentsOpened( | 757 void BackgroundContentsService::BackgroundContentsOpened( |
649 BackgroundContentsOpenedDetails* details) { | 758 BackgroundContentsOpenedDetails* details) { |
650 // Add the passed object to our list. Should not already be tracked. | 759 // Add the passed object to our list. Should not already be tracked. |
651 DCHECK(!IsTracked(details->contents)); | 760 DCHECK(!IsTracked(details->contents)); |
652 DCHECK(!details->application_id.empty()); | 761 DCHECK(!details->application_id.empty()); |
653 contents_map_[details->application_id].contents = details->contents; | 762 contents_map_[details->application_id].contents = details->contents; |
654 contents_map_[details->application_id].frame_name = details->frame_name; | 763 contents_map_[details->application_id].frame_name = details->frame_name; |
655 | 764 |
656 ScheduleCloseBalloon(UTF16ToASCII(details->application_id)); | 765 ScheduleCloseBalloons(UTF16ToASCII(details->application_id)); |
bartfab (slow)
2013/08/26 13:26:53
Will this not close the "misbehaving app" balloon
anitawoodruff
2013/08/26 21:45:23
Done.
| |
657 } | 766 } |
658 | 767 |
659 // Used by test code and debug checks to verify whether a given | 768 // Used by test code and debug checks to verify whether a given |
660 // BackgroundContents is being tracked by this instance. | 769 // BackgroundContents is being tracked by this instance. |
661 bool BackgroundContentsService::IsTracked( | 770 bool BackgroundContentsService::IsTracked( |
662 BackgroundContents* background_contents) const { | 771 BackgroundContents* background_contents) const { |
663 return !GetParentApplicationId(background_contents).empty(); | 772 return !GetParentApplicationId(background_contents).empty(); |
664 } | 773 } |
665 | 774 |
666 void BackgroundContentsService::BackgroundContentsShutdown( | 775 void BackgroundContentsService::BackgroundContentsShutdown( |
(...skipping 27 matching lines...) Expand all Loading... | |
694 bool user_gesture, | 803 bool user_gesture, |
695 bool* was_blocked) { | 804 bool* was_blocked) { |
696 Browser* browser = chrome::FindLastActiveWithProfile( | 805 Browser* browser = chrome::FindLastActiveWithProfile( |
697 Profile::FromBrowserContext(new_contents->GetBrowserContext()), | 806 Profile::FromBrowserContext(new_contents->GetBrowserContext()), |
698 chrome::GetActiveDesktop()); | 807 chrome::GetActiveDesktop()); |
699 if (browser) { | 808 if (browser) { |
700 chrome::AddWebContents(browser, NULL, new_contents, disposition, | 809 chrome::AddWebContents(browser, NULL, new_contents, disposition, |
701 initial_pos, user_gesture, was_blocked); | 810 initial_pos, user_gesture, was_blocked); |
702 } | 811 } |
703 } | 812 } |
OLD | NEW |