OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_contents_service.h" | 5 #include "chrome/browser/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/browser_process.h" | 12 #include "chrome/browser/browser_list.h" |
13 #include "chrome/browser/extensions/extensions_service.h" | 13 #include "chrome/browser/extensions/extensions_service.h" |
14 #include "chrome/browser/pref_service.h" | 14 #include "chrome/browser/pref_service.h" |
15 #include "chrome/browser/profile.h" | 15 #include "chrome/browser/profile.h" |
16 #include "chrome/browser/renderer_host/render_view_host.h" | 16 #include "chrome/browser/renderer_host/render_view_host.h" |
17 #include "chrome/browser/renderer_host/site_instance.h" | 17 #include "chrome/browser/renderer_host/site_instance.h" |
18 #include "chrome/browser/tab_contents/background_contents.h" | 18 #include "chrome/browser/tab_contents/background_contents.h" |
19 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
20 #include "chrome/common/extensions/extension.h" | 20 #include "chrome/common/extensions/extension.h" |
21 #include "chrome/common/notification_service.h" | 21 #include "chrome/common/notification_service.h" |
22 #include "chrome/common/notification_type.h" | 22 #include "chrome/common/notification_type.h" |
23 #include "chrome/common/pref_names.h" | 23 #include "chrome/common/pref_names.h" |
24 | 24 |
25 // Keys for the information we store about individual BackgroundContents in | 25 // Keys for the information we store about individual BackgroundContents in |
26 // prefs. There is one top-level DictionaryValue (stored at | 26 // prefs. There is one top-level DictionaryValue (stored at |
27 // prefs::kRegisteredBackgroundContents). Information about each | 27 // prefs::kRegisteredBackgroundContents). Information about each |
28 // BackgroundContents is stored under that top-level DictionaryValue, keyed | 28 // BackgroundContents is stored under that top-level DictionaryValue, keyed |
29 // by the parent application ID for easy lookup. | 29 // by the parent application ID for easy lookup. |
30 // | 30 // |
31 // kRegisteredBackgroundContents: | 31 // kRegisteredBackgroundContents: |
32 // DictionaryValue { | 32 // DictionaryValue { |
33 // <appid_1>: { "url": <url1>, "name": <frame_name> }, | 33 // <appid_1>: { "url": <url1>, "name": <frame_name> }, |
34 // <appid_2>: { "url": <url2>, "name": <frame_name> }, | 34 // <appid_2>: { "url": <url2>, "name": <frame_name> }, |
35 // ... etc ... | 35 // ... etc ... |
36 // } | 36 // } |
37 const wchar_t kUrlKey[] = L"url"; | 37 const wchar_t kUrlKey[] = L"url"; |
38 const wchar_t kFrameNameKey[] = L"name"; | 38 const wchar_t kFrameNameKey[] = L"name"; |
39 | 39 |
40 BackgroundContentsService::BackgroundContentsService( | 40 BackgroundContentsService::BackgroundContentsService( |
41 Profile* profile, const CommandLine* command_line) | 41 Profile* profile, const CommandLine* command_line) |
42 : prefs_(NULL) { | 42 : prefs_(NULL), |
| 43 always_keep_alive_(command_line->HasSwitch(switches::kKeepAliveForTest)) { |
43 // Don't load/store preferences if the proper switch is not enabled, or if | 44 // Don't load/store preferences if the proper switch is not enabled, or if |
44 // the parent profile is off the record. | 45 // the parent profile is off the record. |
45 if (!profile->IsOffTheRecord() && | 46 if (!profile->IsOffTheRecord() && |
46 command_line->HasSwitch(switches::kRestoreBackgroundContents)) | 47 command_line->HasSwitch(switches::kRestoreBackgroundContents)) |
47 prefs_ = profile->GetPrefs(); | 48 prefs_ = profile->GetPrefs(); |
48 | 49 |
49 // Listen for events to tell us when to load/unload persisted background | 50 // Listen for events to tell us when to load/unload persisted background |
50 // contents. | 51 // contents. |
51 StartObserving(profile); | 52 StartObserving(profile); |
52 } | 53 } |
(...skipping 23 matching lines...) Expand all Loading... |
76 Source<Profile>(profile)); | 77 Source<Profile>(profile)); |
77 // Track when the BackgroundContents navigates to a new URL so we can update | 78 // Track when the BackgroundContents navigates to a new URL so we can update |
78 // our persisted information as appropriate. | 79 // our persisted information as appropriate. |
79 registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_NAVIGATED, | 80 registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_NAVIGATED, |
80 Source<Profile>(profile)); | 81 Source<Profile>(profile)); |
81 | 82 |
82 // Listen for extensions to be unloaded so we can shutdown associated | 83 // Listen for extensions to be unloaded so we can shutdown associated |
83 // BackgroundContents. | 84 // BackgroundContents. |
84 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, | 85 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, |
85 Source<Profile>(profile)); | 86 Source<Profile>(profile)); |
| 87 |
| 88 if (always_keep_alive_ && !profile->IsOffTheRecord()) { |
| 89 // For testing, keep the browser process alive until there is an explicit |
| 90 // shutdown. |
| 91 registrar_.Add(this, NotificationType::APP_TERMINATING, |
| 92 NotificationService::AllSources()); |
| 93 BrowserList::StartKeepAlive(); |
| 94 } |
86 } | 95 } |
87 | 96 |
88 void BackgroundContentsService::Observe(NotificationType type, | 97 void BackgroundContentsService::Observe(NotificationType type, |
89 const NotificationSource& source, | 98 const NotificationSource& source, |
90 const NotificationDetails& details) { | 99 const NotificationDetails& details) { |
91 switch (type.value) { | 100 switch (type.value) { |
92 case NotificationType::EXTENSIONS_READY: | 101 case NotificationType::EXTENSIONS_READY: |
93 LoadBackgroundContentsFromPrefs(Source<Profile>(source).ptr()); | 102 LoadBackgroundContentsFromPrefs(Source<Profile>(source).ptr()); |
94 break; | 103 break; |
95 case NotificationType::BACKGROUND_CONTENTS_DELETED: | 104 case NotificationType::BACKGROUND_CONTENTS_DELETED: |
96 BackgroundContentsShutdown(Details<BackgroundContents>(details).ptr()); | 105 BackgroundContentsShutdown(Details<BackgroundContents>(details).ptr()); |
97 break; | 106 break; |
98 case NotificationType::BACKGROUND_CONTENTS_OPENED: | 107 case NotificationType::BACKGROUND_CONTENTS_OPENED: |
99 BackgroundContentsOpened( | 108 BackgroundContentsOpened( |
100 Details<BackgroundContentsOpenedDetails>(details).ptr()); | 109 Details<BackgroundContentsOpenedDetails>(details).ptr()); |
101 break; | 110 break; |
102 case NotificationType::BACKGROUND_CONTENTS_CLOSED: | 111 case NotificationType::BACKGROUND_CONTENTS_CLOSED: |
103 DCHECK(IsTracked(Details<BackgroundContents>(details).ptr())); | 112 DCHECK(IsTracked(Details<BackgroundContents>(details).ptr())); |
104 UnregisterBackgroundContents(Details<BackgroundContents>(details).ptr()); | 113 UnregisterBackgroundContents(Details<BackgroundContents>(details).ptr()); |
105 break; | 114 break; |
106 case NotificationType::BACKGROUND_CONTENTS_NAVIGATED: | 115 case NotificationType::BACKGROUND_CONTENTS_NAVIGATED: |
107 DCHECK(IsTracked(Details<BackgroundContents>(details).ptr())); | 116 DCHECK(IsTracked(Details<BackgroundContents>(details).ptr())); |
108 RegisterBackgroundContents(Details<BackgroundContents>(details).ptr()); | 117 RegisterBackgroundContents(Details<BackgroundContents>(details).ptr()); |
109 break; | 118 break; |
110 case NotificationType::EXTENSION_UNLOADED: | 119 case NotificationType::EXTENSION_UNLOADED: |
111 ShutdownAssociatedBackgroundContents( | 120 ShutdownAssociatedBackgroundContents( |
112 ASCIIToUTF16(Details<Extension>(details)->id())); | 121 ASCIIToUTF16(Details<Extension>(details)->id())); |
113 break; | 122 break; |
| 123 case NotificationType::APP_TERMINATING: |
| 124 // Performing an explicit shutdown, so allow the browser process to exit. |
| 125 DCHECK(always_keep_alive_); |
| 126 BrowserList::EndKeepAlive(); |
| 127 break; |
114 default: | 128 default: |
115 NOTREACHED(); | 129 NOTREACHED(); |
116 break; | 130 break; |
117 } | 131 } |
118 } | 132 } |
119 | 133 |
120 // Loads all background contents whose urls have been stored in prefs. | 134 // Loads all background contents whose urls have been stored in prefs. |
121 void BackgroundContentsService::LoadBackgroundContentsFromPrefs( | 135 void BackgroundContentsService::LoadBackgroundContentsFromPrefs( |
122 Profile* profile) { | 136 Profile* profile) { |
123 if (!prefs_) | 137 if (!prefs_) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 // unregistered via the EXTENSIONS_UNLOADED notification, unless there's a | 179 // unregistered via the EXTENSIONS_UNLOADED notification, unless there's a |
166 // crash before we could save our prefs. | 180 // crash before we could save our prefs. |
167 NOTREACHED() << "No extension found for BackgroundContents - id = " << | 181 NOTREACHED() << "No extension found for BackgroundContents - id = " << |
168 application_id; | 182 application_id; |
169 return; | 183 return; |
170 } | 184 } |
171 | 185 |
172 BackgroundContents* contents = new BackgroundContents( | 186 BackgroundContents* contents = new BackgroundContents( |
173 SiteInstance::CreateSiteInstanceForURL(profile, url), MSG_ROUTING_NONE); | 187 SiteInstance::CreateSiteInstanceForURL(profile, url), MSG_ROUTING_NONE); |
174 | 188 |
175 contents_map_[application_id].contents = contents; | 189 // TODO(atwilson): Change this to send a BACKGROUND_CONTENTS_CREATED |
176 contents_map_[application_id].frame_name = frame_name; | 190 // notification when we have a listener outside of BackgroundContentsService. |
| 191 BackgroundContentsOpenedDetails details = {contents, |
| 192 frame_name, |
| 193 application_id}; |
| 194 BackgroundContentsOpened(&details); |
177 | 195 |
178 RenderViewHost* render_view_host = contents->render_view_host(); | 196 RenderViewHost* render_view_host = contents->render_view_host(); |
179 // TODO(atwilson): Create RenderViews asynchronously to avoid increasing | 197 // TODO(atwilson): Create RenderViews asynchronously to avoid increasing |
180 // startup latency (http://crbug.com/47236). | 198 // startup latency (http://crbug.com/47236). |
181 render_view_host->CreateRenderView(profile->GetRequestContext(), frame_name); | 199 render_view_host->CreateRenderView(profile->GetRequestContext(), frame_name); |
182 render_view_host->NavigateToURL(url); | 200 render_view_host->NavigateToURL(url); |
183 } | 201 } |
184 | 202 |
185 void BackgroundContentsService::RegisterBackgroundContents( | 203 void BackgroundContentsService::RegisterBackgroundContents( |
186 BackgroundContents* background_contents) { | 204 BackgroundContents* background_contents) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 UnregisterBackgroundContents(contents); | 244 UnregisterBackgroundContents(contents); |
227 // Background contents destructor shuts down the renderer. | 245 // Background contents destructor shuts down the renderer. |
228 delete contents; | 246 delete contents; |
229 } | 247 } |
230 } | 248 } |
231 | 249 |
232 void BackgroundContentsService::BackgroundContentsOpened( | 250 void BackgroundContentsService::BackgroundContentsOpened( |
233 BackgroundContentsOpenedDetails* details) { | 251 BackgroundContentsOpenedDetails* details) { |
234 // If this is the first BackgroundContents loaded, kick ourselves into | 252 // If this is the first BackgroundContents loaded, kick ourselves into |
235 // persistent mode. | 253 // persistent mode. |
236 // TODO(atwilson): Enable this when we support running with no active windows | 254 if (contents_map_.empty()) |
237 // on all platforms (http://crbug.com/45275). | 255 BrowserList::StartKeepAlive(); |
238 // if (contents_map_.empty()) | |
239 // g_browser_process->AddRefModule(); | |
240 | 256 |
241 // Add the passed object to our list. Should not already be tracked. | 257 // Add the passed object to our list. Should not already be tracked. |
242 DCHECK(!IsTracked(details->contents)); | 258 DCHECK(!IsTracked(details->contents)); |
243 DCHECK(!details->application_id.empty()); | 259 DCHECK(!details->application_id.empty()); |
244 contents_map_[details->application_id].contents = details->contents; | 260 contents_map_[details->application_id].contents = details->contents; |
245 contents_map_[details->application_id].frame_name = details->frame_name; | 261 contents_map_[details->application_id].frame_name = details->frame_name; |
246 } | 262 } |
247 | 263 |
248 // Used by test code and debug checks to verify whether a given | 264 // Used by test code and debug checks to verify whether a given |
249 // BackgroundContents is being tracked by this instance. | 265 // BackgroundContents is being tracked by this instance. |
250 bool BackgroundContentsService::IsTracked( | 266 bool BackgroundContentsService::IsTracked( |
251 BackgroundContents* background_contents) const { | 267 BackgroundContents* background_contents) const { |
252 return !GetParentApplicationId(background_contents).empty(); | 268 return !GetParentApplicationId(background_contents).empty(); |
253 } | 269 } |
254 | 270 |
255 void BackgroundContentsService::BackgroundContentsShutdown( | 271 void BackgroundContentsService::BackgroundContentsShutdown( |
256 BackgroundContents* background_contents) { | 272 BackgroundContents* background_contents) { |
257 // Remove the passed object from our list. | 273 // Remove the passed object from our list. |
258 DCHECK(IsTracked(background_contents)); | 274 DCHECK(IsTracked(background_contents)); |
259 string16 appid = GetParentApplicationId(background_contents); | 275 string16 appid = GetParentApplicationId(background_contents); |
260 contents_map_.erase(appid); | 276 contents_map_.erase(appid); |
261 // If we have no more BackgroundContents active, then stop keeping the browser | 277 // If we have no more BackgroundContents active, then stop keeping the browser |
262 // process alive. | 278 // process alive. |
263 // TODO(atwilson): Enable this when we support running with no active windows | 279 if (contents_map_.empty()) |
264 // on all platforms (http://crbug.com/45275). | 280 BrowserList::EndKeepAlive(); |
265 // if (contents_map_.empty()) | |
266 // g_browser_process->ReleaseModule(); | |
267 } | 281 } |
268 | 282 |
269 BackgroundContents* BackgroundContentsService::GetAppBackgroundContents( | 283 BackgroundContents* BackgroundContentsService::GetAppBackgroundContents( |
270 const string16& application_id) { | 284 const string16& application_id) { |
271 BackgroundContentsMap::const_iterator it = contents_map_.find(application_id); | 285 BackgroundContentsMap::const_iterator it = contents_map_.find(application_id); |
272 return (it != contents_map_.end()) ? it->second.contents : NULL; | 286 return (it != contents_map_.end()) ? it->second.contents : NULL; |
273 } | 287 } |
274 | 288 |
275 const string16& BackgroundContentsService::GetParentApplicationId( | 289 const string16& BackgroundContentsService::GetParentApplicationId( |
276 BackgroundContents* contents) const { | 290 BackgroundContents* contents) const { |
277 for (BackgroundContentsMap::const_iterator it = contents_map_.begin(); | 291 for (BackgroundContentsMap::const_iterator it = contents_map_.begin(); |
278 it != contents_map_.end(); ++it) { | 292 it != contents_map_.end(); ++it) { |
279 if (contents == it->second.contents) | 293 if (contents == it->second.contents) |
280 return it->first; | 294 return it->first; |
281 } | 295 } |
282 return EmptyString16(); | 296 return EmptyString16(); |
283 } | 297 } |
284 | 298 |
285 // static | 299 // static |
286 void BackgroundContentsService::RegisterUserPrefs(PrefService* prefs) { | 300 void BackgroundContentsService::RegisterUserPrefs(PrefService* prefs) { |
287 prefs->RegisterDictionaryPref(prefs::kRegisteredBackgroundContents); | 301 prefs->RegisterDictionaryPref(prefs::kRegisteredBackgroundContents); |
288 } | 302 } |
OLD | NEW |