| 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. |
| 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 |