Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: chrome/browser/extensions/lazy_background_task_queue.cc

Issue 10114015: Fix bug where transient pages would miss events dispatched while it was (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/lazy_background_task_queue.h" 5 #include "chrome/browser/extensions/lazy_background_task_queue.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/message_loop.h"
8 #include "chrome/browser/extensions/extension_host.h" 9 #include "chrome/browser/extensions/extension_host.h"
9 #include "chrome/browser/extensions/extension_process_manager.h" 10 #include "chrome/browser/extensions/extension_process_manager.h"
10 #include "chrome/browser/extensions/extension_service.h" 11 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/extension_system.h" 12 #include "chrome/browser/extensions/extension_system.h"
12 #include "chrome/browser/extensions/extension_tab_util.h" 13 #include "chrome/browser/extensions/extension_tab_util.h"
13 #include "chrome/browser/extensions/process_map.h" 14 #include "chrome/browser/extensions/process_map.h"
14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/tab_contents/tab_util.h" 16 #include "chrome/browser/tab_contents/tab_util.h"
16 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 17 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
17 #include "chrome/common/chrome_notification_types.h" 18 #include "chrome/common/chrome_notification_types.h"
(...skipping 18 matching lines...) Expand all
36 content::Source<Profile>(profile)); 37 content::Source<Profile>(profile));
37 } 38 }
38 39
39 LazyBackgroundTaskQueue::~LazyBackgroundTaskQueue() { 40 LazyBackgroundTaskQueue::~LazyBackgroundTaskQueue() {
40 } 41 }
41 42
42 bool LazyBackgroundTaskQueue::ShouldEnqueueTask( 43 bool LazyBackgroundTaskQueue::ShouldEnqueueTask(
43 Profile* profile, const Extension* extension) { 44 Profile* profile, const Extension* extension) {
44 DCHECK(extension); 45 DCHECK(extension);
45 if (extension->has_lazy_background_page()) { 46 if (extension->has_lazy_background_page()) {
46 ExtensionProcessManager* pm = profile->GetExtensionProcessManager(); 47 ExtensionProcessManager* pm =
48 ExtensionSystem::Get(profile)->process_manager();
47 ExtensionHost* background_host = 49 ExtensionHost* background_host =
48 pm->GetBackgroundHostForExtension(extension->id()); 50 pm->GetBackgroundHostForExtension(extension->id());
49 if (!background_host || !background_host->did_stop_loading()) 51 if (!background_host || !background_host->did_stop_loading() ||
52 pm->IsBackgroundHostClosing(extension->id()))
50 return true; 53 return true;
51 } 54 }
52 55
53 return false; 56 return false;
54 } 57 }
55 58
56 void LazyBackgroundTaskQueue::AddPendingTask( 59 void LazyBackgroundTaskQueue::AddPendingTask(
57 Profile* profile, 60 Profile* profile,
58 const std::string& extension_id, 61 const std::string& extension_id,
59 const PendingTask& task) { 62 const PendingTask& task) {
60 PendingTasksList* tasks_list = NULL; 63 PendingTasksList* tasks_list = NULL;
61 PendingTasksKey key(profile, extension_id); 64 PendingTasksKey key(profile, extension_id);
62 PendingTasksMap::iterator it = pending_tasks_.find(key); 65 PendingTasksMap::iterator it = pending_tasks_.find(key);
63 if (it == pending_tasks_.end()) { 66 if (it == pending_tasks_.end()) {
64 tasks_list = new PendingTasksList(); 67 tasks_list = new PendingTasksList();
65 pending_tasks_[key] = linked_ptr<PendingTasksList>(tasks_list); 68 pending_tasks_[key] = linked_ptr<PendingTasksList>(tasks_list);
66 69
67 // If this is the first enqueued task, ensure the background page 70 // If this is the first enqueued task, ensure the background page
Yoyo Zhou 2012/04/19 21:47:13 This comment needs an "and we are not waiting for
Matt Perry 2012/04/19 22:21:53 Done.
68 // is loaded. 71 // is loaded.
69 const Extension* extension = 72 if (pending_page_loads_.count(key) == 0)
70 ExtensionSystem::Get(profile)->extension_service()-> 73 StartLazyBackgroundPage(profile, extension_id);
71 extensions()->GetByID(extension_id);
72 DCHECK(extension->has_lazy_background_page());
73 ExtensionProcessManager* pm =
74 ExtensionSystem::Get(profile)->process_manager();
75 pm->IncrementLazyKeepaliveCount(extension);
76 pm->CreateBackgroundHost(extension, extension->GetBackgroundURL());
77 } else { 74 } else {
78 tasks_list = it->second.get(); 75 tasks_list = it->second.get();
79 } 76 }
80 77
81 tasks_list->push_back(task); 78 tasks_list->push_back(task);
82 } 79 }
83 80
81 void LazyBackgroundTaskQueue::StartLazyBackgroundPage(
82 Profile* profile, const std::string& extension_id) {
83 ExtensionProcessManager* pm =
84 ExtensionSystem::Get(profile)->process_manager();
85 if (pm->IsBackgroundHostClosing(extension_id)) {
86 // When the background host finishes closing, we will reload it.
87 pending_page_loads_.insert(PendingTasksKey(profile, extension_id));
88 return;
89 }
90
91 const Extension* extension =
92 ExtensionSystem::Get(profile)->extension_service()->
93 extensions()->GetByID(extension_id);
94 DCHECK(extension->has_lazy_background_page());
95 pm->IncrementLazyKeepaliveCount(extension);
96 pm->CreateBackgroundHost(extension, extension->GetBackgroundURL());
97
98 pending_page_loads_.erase(PendingTasksKey(profile, extension_id));
99 }
100
84 void LazyBackgroundTaskQueue::ProcessPendingTasks( 101 void LazyBackgroundTaskQueue::ProcessPendingTasks(
85 ExtensionHost* host, 102 ExtensionHost* host,
86 Profile* profile, 103 Profile* profile,
87 const Extension* extension) { 104 const Extension* extension) {
88 if (!profile->IsSameProfile(profile_) || 105 if (!profile->IsSameProfile(profile_) ||
89 !extension->has_lazy_background_page()) 106 !extension->has_lazy_background_page())
90 return; 107 return;
91 108
92 PendingTasksKey key(profile, extension->id()); 109 PendingTasksKey key(profile, extension->id());
93 PendingTasksMap::iterator map_it = pending_tasks_.find(key); 110 PendingTasksMap::iterator map_it = pending_tasks_.find(key);
(...skipping 29 matching lines...) Expand all
123 // events for it. 140 // events for it.
124 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); 141 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
125 if (host->extension_host_type() == 142 if (host->extension_host_type() ==
126 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { 143 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
127 CHECK(host->did_stop_loading()); 144 CHECK(host->did_stop_loading());
128 ProcessPendingTasks(host, host->profile(), host->extension()); 145 ProcessPendingTasks(host, host->profile(), host->extension());
129 } 146 }
130 break; 147 break;
131 } 148 }
132 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { 149 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
133 // Notify consumers about the load failure when the background host dies.
134 // This can happen if the extension crashes. This is not strictly
135 // necessary, since we also unload the extension in that case (which
136 // dispatches the tasks below), but is a good extra precaution.
137 Profile* profile = content::Source<Profile>(source).ptr(); 150 Profile* profile = content::Source<Profile>(source).ptr();
138 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); 151 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
139 if (host->extension_host_type() == 152 if (host->extension_host_type() ==
140 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { 153 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
141 ProcessPendingTasks(NULL, profile, host->extension()); 154 PendingTasksKey key(profile, host->extension()->id());
155 if (pending_page_loads_.count(key) > 0) {
156 // We were waiting for the background page to unload. We can start it
157 // up again and dispatch any queued events.
158 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
159 &LazyBackgroundTaskQueue::StartLazyBackgroundPage,
160 base::Unretained(this), profile, host->extension()->id()));
Yoyo Zhou 2012/04/19 21:47:13 If we might be receiving this notification near sh
Matt Perry 2012/04/19 22:21:53 Done.
161 } else {
162 // This may be a load failure (e.g. a crash). In that case, notify
163 // consumers about the load failure. This is not strictly necessary,
164 // since we also unload the extension in that case (which dispatches
165 // the tasks below), but is a good extra precaution.
166 ProcessPendingTasks(NULL, profile, host->extension());
167 }
142 } 168 }
143 break; 169 break;
144 } 170 }
145 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 171 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
146 // Notify consumers that the page failed to load. 172 // Notify consumers that the page failed to load.
147 Profile* profile = content::Source<Profile>(source).ptr(); 173 Profile* profile = content::Source<Profile>(source).ptr();
148 UnloadedExtensionInfo* unloaded = 174 UnloadedExtensionInfo* unloaded =
149 content::Details<UnloadedExtensionInfo>(details).ptr(); 175 content::Details<UnloadedExtensionInfo>(details).ptr();
150 ProcessPendingTasks(NULL, profile, unloaded->extension); 176 ProcessPendingTasks(NULL, profile, unloaded->extension);
151 if (profile->HasOffTheRecordProfile()) { 177 if (profile->HasOffTheRecordProfile()) {
152 ProcessPendingTasks(NULL, profile->GetOffTheRecordProfile(), 178 ProcessPendingTasks(NULL, profile->GetOffTheRecordProfile(),
153 unloaded->extension); 179 unloaded->extension);
154 } 180 }
155 break; 181 break;
156 } 182 }
157 default: 183 default:
158 NOTREACHED(); 184 NOTREACHED();
159 break; 185 break;
160 } 186 }
161 } 187 }
162 188
163 } // namespace extensions 189 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698