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

Side by Side Diff: chrome/browser/background_contents_service.cc

Issue 2866034: Refactor shutdown code to allow win/linux to run after last browser closes. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: Uploaded patch that resolves merge issue Created 10 years, 5 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
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/background_contents_service.h ('k') | chrome/browser/background_contents_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698