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/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 "chrome/browser/extensions/extension_host.h" | 8 #include "chrome/browser/extensions/extension_host.h" |
9 #include "chrome/browser/extensions/extension_process_manager.h" | 9 #include "chrome/browser/extensions/extension_process_manager.h" |
10 #include "chrome/browser/extensions/extension_service.h" | 10 #include "chrome/browser/extensions/extension_service.h" |
11 #include "chrome/browser/extensions/extension_system.h" | |
11 #include "chrome/browser/extensions/extension_tab_util.h" | 12 #include "chrome/browser/extensions/extension_tab_util.h" |
12 #include "chrome/browser/extensions/process_map.h" | 13 #include "chrome/browser/extensions/process_map.h" |
13 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
14 #include "chrome/browser/tab_contents/tab_util.h" | 15 #include "chrome/browser/tab_contents/tab_util.h" |
15 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 16 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
16 #include "chrome/common/chrome_notification_types.h" | 17 #include "chrome/common/chrome_notification_types.h" |
17 #include "chrome/common/chrome_view_type.h" | 18 #include "chrome/common/chrome_view_type.h" |
18 #include "chrome/common/extensions/extension.h" | 19 #include "chrome/common/extensions/extension.h" |
19 #include "chrome/common/extensions/extension_messages.h" | 20 #include "chrome/common/extensions/extension_messages.h" |
20 #include "content/public/browser/notification_service.h" | 21 #include "content/public/browser/notification_service.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
58 const PendingTask& task) { | 59 const PendingTask& task) { |
59 PendingTasksList* tasks_list = NULL; | 60 PendingTasksList* tasks_list = NULL; |
60 PendingTasksKey key(profile, extension_id); | 61 PendingTasksKey key(profile, extension_id); |
61 PendingTasksMap::iterator it = pending_tasks_.find(key); | 62 PendingTasksMap::iterator it = pending_tasks_.find(key); |
62 if (it == pending_tasks_.end()) { | 63 if (it == pending_tasks_.end()) { |
63 tasks_list = new PendingTasksList(); | 64 tasks_list = new PendingTasksList(); |
64 pending_tasks_[key] = linked_ptr<PendingTasksList>(tasks_list); | 65 pending_tasks_[key] = linked_ptr<PendingTasksList>(tasks_list); |
65 | 66 |
66 // If this is the first enqueued task, ensure the background page | 67 // If this is the first enqueued task, ensure the background page |
67 // is loaded. | 68 // is loaded. |
68 const Extension* extension = profile->GetExtensionService()-> | 69 const Extension* extension = |
69 extensions()->GetByID(extension_id); | 70 ExtensionSystem::Get(profile)->extension_service()-> |
71 extensions()->GetByID(extension_id); | |
70 DCHECK(extension->has_lazy_background_page()); | 72 DCHECK(extension->has_lazy_background_page()); |
71 ExtensionProcessManager* pm = profile->GetExtensionProcessManager(); | 73 ExtensionProcessManager* pm = |
74 ExtensionSystem::Get(profile)->process_manager(); | |
72 pm->IncrementLazyKeepaliveCount(extension); | 75 pm->IncrementLazyKeepaliveCount(extension); |
73 pm->CreateBackgroundHost(extension, extension->GetBackgroundURL()); | 76 pm->CreateBackgroundHost(extension, extension->GetBackgroundURL()); |
74 } else { | 77 } else { |
75 tasks_list = it->second.get(); | 78 tasks_list = it->second.get(); |
76 } | 79 } |
77 | 80 |
78 tasks_list->push_back(task); | 81 tasks_list->push_back(task); |
79 } | 82 } |
80 | 83 |
81 void LazyBackgroundTaskQueue::ProcessPendingTasks(ExtensionHost* host) { | 84 void LazyBackgroundTaskQueue::ProcessPendingTasks( |
82 PendingTasksKey key(host->profile(), host->extension()->id()); | 85 ExtensionHost* host, |
86 Profile* profile, | |
87 const Extension* extension) { | |
88 if (!profile->IsSameProfile(profile_) || | |
89 !extension->has_lazy_background_page()) | |
90 return; | |
91 | |
92 PendingTasksKey key(profile, extension->id()); | |
83 PendingTasksMap::iterator map_it = pending_tasks_.find(key); | 93 PendingTasksMap::iterator map_it = pending_tasks_.find(key); |
84 if (map_it == pending_tasks_.end()) { | 94 if (map_it == pending_tasks_.end()) { |
85 NOTREACHED(); // lazy page should not load without any pending tasks | 95 CHECK(!host); // lazy page should not load without any pending tasks |
86 return; | 96 return; |
87 } | 97 } |
88 | 98 |
89 PendingTasksList* tasks = map_it->second.get(); | 99 PendingTasksList* tasks = map_it->second.get(); |
90 for (PendingTasksList::const_iterator it = tasks->begin(); | 100 for (PendingTasksList::const_iterator it = tasks->begin(); |
91 it != tasks->end(); ++it) { | 101 it != tasks->end(); ++it) { |
92 it->Run(host); | 102 it->Run(host); |
93 } | 103 } |
94 | 104 |
95 tasks->clear(); | 105 tasks->clear(); |
96 pending_tasks_.erase(map_it); | 106 pending_tasks_.erase(map_it); |
97 | 107 |
98 // Balance the keepalive in AddPendingTask. | 108 // Balance the keepalive in AddPendingTask. Note we don't do this on a |
99 host->profile()->GetExtensionProcessManager()-> | 109 // failure to load, because the keepalive count is reset in that case. |
Yoyo Zhou
2012/04/13 20:43:52
Where is it reset?
Matt Perry
2012/04/13 21:19:09
In ExtensionProcessManager's handler for the chrom
| |
100 DecrementLazyKeepaliveCount(host->extension()); | 110 if (host) { |
111 ExtensionSystem::Get(profile)->process_manager()-> | |
112 DecrementLazyKeepaliveCount(extension); | |
113 } | |
101 } | 114 } |
102 | 115 |
103 void LazyBackgroundTaskQueue::Observe( | 116 void LazyBackgroundTaskQueue::Observe( |
104 int type, | 117 int type, |
105 const content::NotificationSource& source, | 118 const content::NotificationSource& source, |
106 const content::NotificationDetails& details) { | 119 const content::NotificationDetails& details) { |
107 switch (type) { | 120 switch (type) { |
108 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: { | 121 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: { |
109 // If an on-demand background page finished loading, dispatch queued up | 122 // If an on-demand background page finished loading, dispatch queued up |
110 // events for it. | 123 // events for it. |
111 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); | 124 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); |
112 if (host->profile()->IsSameProfile(profile_) && | 125 if (host->extension_host_type() == |
113 host->extension_host_type() == | 126 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { |
114 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE && | |
115 host->extension()->has_lazy_background_page()) { | |
116 CHECK(host->did_stop_loading()); | 127 CHECK(host->did_stop_loading()); |
117 ProcessPendingTasks(host); | 128 ProcessPendingTasks(host, host->profile(), host->extension()); |
118 } | 129 } |
119 break; | 130 break; |
120 } | 131 } |
121 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { | 132 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { |
122 // Clear pending tasks when the background host dies. This can happen | 133 // Notify consumers about the load failure when the background host dies. |
123 // if the extension crashes. This is not strictly necessary, since we | 134 // This can happen if the extension crashes. This is not strictly |
124 // also unload the extension in that case (which clears the tasks below), | 135 // necessary, since we also unload the extension in that case (which |
125 // but is a good extra precaution. | 136 // dispatches the tasks below), but is a good extra precaution. |
126 Profile* profile = content::Source<Profile>(source).ptr(); | 137 Profile* profile = content::Source<Profile>(source).ptr(); |
127 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); | 138 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); |
128 if (host->extension_host_type() == | 139 if (host->extension_host_type() == |
129 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { | 140 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { |
130 pending_tasks_.erase(PendingTasksKey(profile, host->extension()->id())); | 141 ProcessPendingTasks(NULL, profile, host->extension()); |
131 } | 142 } |
132 break; | 143 break; |
133 } | 144 } |
134 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | 145 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
135 // Clear pending tasks for this extension. | 146 // Notify consumers that the page failed to load. |
136 Profile* profile = content::Source<Profile>(source).ptr(); | 147 Profile* profile = content::Source<Profile>(source).ptr(); |
137 UnloadedExtensionInfo* unloaded = | 148 UnloadedExtensionInfo* unloaded = |
138 content::Details<UnloadedExtensionInfo>(details).ptr(); | 149 content::Details<UnloadedExtensionInfo>(details).ptr(); |
139 pending_tasks_.erase(PendingTasksKey( | 150 ProcessPendingTasks(NULL, profile, unloaded->extension); |
140 profile, unloaded->extension->id())); | 151 if (profile->HasOffTheRecordProfile()) { |
141 if (profile->HasOffTheRecordProfile()) | 152 ProcessPendingTasks(NULL, profile->GetOffTheRecordProfile(), |
142 pending_tasks_.erase(PendingTasksKey( | 153 unloaded->extension); |
143 profile->GetOffTheRecordProfile(), unloaded->extension->id())); | 154 } |
144 break; | 155 break; |
145 } | 156 } |
146 default: | 157 default: |
147 NOTREACHED(); | 158 NOTREACHED(); |
148 break; | 159 break; |
149 } | 160 } |
150 } | 161 } |
151 | 162 |
152 } // namespace extensions | 163 } // namespace extensions |
OLD | NEW |