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

Side by Side Diff: chrome/browser/chromeos/login/merge_session_throttle.cc

Issue 23678007: OAuth2LoginManager+MergeSessionThrottle hardening, multi-profle support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/chromeos/login/merge_session_throttle.h" 5 #include "chrome/browser/chromeos/login/merge_session_throttle.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
8 #include "base/logging.h" 9 #include "base/logging.h"
9 #include "base/memory/singleton.h" 10 #include "base/memory/singleton.h"
10 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
11 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
12 #include "chrome/browser/chromeos/login/login_utils.h" 13 #include "base/threading/non_thread_safe.h"
14 #include "base/time/time.h"
15 #include "chrome/browser/chromeos/login/oauth2_login_manager.h"
16 #include "chrome/browser/chromeos/login/oauth2_login_manager_factory.h"
17 #include "chrome/browser/chromeos/login/user_manager.h"
18 #include "chrome/browser/chromeos/login/user_manager.h"
13 #include "chrome/browser/google/google_util.h" 19 #include "chrome/browser/google/google_util.h"
14 #include "chrome/browser/net/chrome_url_request_context.h" 20 #include "chrome/browser/net/chrome_url_request_context.h"
15 #include "chrome/common/url_constants.h" 21 #include "chrome/common/url_constants.h"
16 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_view_host.h" 23 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/resource_controller.h" 24 #include "content/public/browser/resource_controller.h"
19 #include "content/public/browser/resource_request_info.h" 25 #include "content/public/browser/resource_request_info.h"
20 #include "content/public/browser/web_contents.h" 26 #include "content/public/browser/web_contents.h"
21 #include "net/base/net_errors.h" 27 #include "net/base/net_errors.h"
22 #include "net/base/net_util.h" 28 #include "net/base/net_util.h"
23 #include "net/base/network_change_notifier.h" 29 #include "net/base/network_change_notifier.h"
24 #include "net/url_request/url_request.h" 30 #include "net/url_request/url_request.h"
25 #include "net/url_request/url_request_context.h" 31 #include "net/url_request/url_request_context.h"
26 32
27 using content::BrowserThread; 33 using content::BrowserThread;
28 using content::RenderViewHost; 34 using content::RenderViewHost;
29 using content::WebContents; 35 using content::WebContents;
30 36
31 namespace { 37 namespace {
32 38
33 void ShowDeleayedLoadingPage( 39 const int64 kMaxSessionRestoreTimeInSec = 60;
34 int render_process_id,
35 int render_view_id,
36 const GURL& url,
37 const chromeos::MergeSessionLoadPage::CompletionCallback& callback) {
38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
39 40
40 // Check again on UI thread and proceed if it's connected. 41 // The set of blocked profiles.
41 if (chromeos::UserManager::Get()->GetMergeSessionState() != 42 class ProfileSet : public base::NonThreadSafe,
42 chromeos::UserManager::MERGE_STATUS_IN_PROCESS) { 43 public std::set<Profile*> {
43 BrowserThread::PostTask( 44 public:
44 BrowserThread::IO, FROM_HERE, callback); 45 ProfileSet();
45 } else { 46 virtual ~ProfileSet();
46 RenderViewHost* render_view_host = 47 static ProfileSet* Get();
47 RenderViewHost::FromID(render_process_id, render_view_id); 48
48 WebContents* web_contents = render_view_host ? 49 private:
49 WebContents::FromRenderViewHost(render_view_host) : NULL; 50 friend struct ::base::DefaultLazyInstanceTraits<ProfileSet>;
50 // There is a chance that the tab closed after we decided to show 51 };
51 // the offline page on the IO thread and before we actually show the 52
52 // offline page here on the UI thread. 53 // Set of all of profiles for which restore session is in progress.
53 if (web_contents) 54 // This static member is accessible only form UI thread.
54 (new chromeos::MergeSessionLoadPage(web_contents, url, callback))->Show(); 55 static base::LazyInstance<ProfileSet> g_blocked_profiles =
55 } 56 LAZY_INSTANCE_INITIALIZER;
57
58 ProfileSet::ProfileSet() {
59 }
60
61 ProfileSet::~ProfileSet() {
62 }
63
64 ProfileSet* ProfileSet::Get() {
65 return g_blocked_profiles.Pointer();
56 } 66 }
57 67
58 } // namespace 68 } // namespace
59 69
70 base::AtomicRefCount MergeSessionThrottle::all_profiles_restored_(0);
71
60 MergeSessionThrottle::MergeSessionThrottle(net::URLRequest* request) 72 MergeSessionThrottle::MergeSessionThrottle(net::URLRequest* request)
61 : request_(request) { 73 : request_(request) {
62 } 74 }
63 75
64 MergeSessionThrottle::~MergeSessionThrottle() { 76 MergeSessionThrottle::~MergeSessionThrottle() {
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
66 } 78 }
67 79
68 void MergeSessionThrottle::WillStartRequest(bool* defer) { 80 void MergeSessionThrottle::WillStartRequest(bool* defer) {
81 DCHECK(request_->url().SchemeIsHTTPOrHTTPS());
69 if (!ShouldShowMergeSessionPage(request_->url())) 82 if (!ShouldShowMergeSessionPage(request_->url()))
70 return; 83 return;
71 84
72 DVLOG(1) << "WillStartRequest: url=" << request_->url(); 85 DVLOG(1) << "WillStartRequest: defer " << request_->url();
73 const content::ResourceRequestInfo* info = 86 const content::ResourceRequestInfo* info =
74 content::ResourceRequestInfo::ForRequest(request_); 87 content::ResourceRequestInfo::ForRequest(request_);
75 BrowserThread::PostTask( 88 BrowserThread::PostTask(
76 BrowserThread::UI, 89 BrowserThread::UI,
77 FROM_HERE, 90 FROM_HERE,
78 base::Bind( 91 base::Bind(
79 &ShowDeleayedLoadingPage, 92 &MergeSessionThrottle::ShowDeleayedLoadingPageOnUIThread,
80 info->GetChildID(), 93 info->GetChildID(),
81 info->GetRouteID(), 94 info->GetRouteID(),
82 request_->url(), 95 request_->url(),
83 base::Bind( 96 base::Bind(
84 &MergeSessionThrottle::OnBlockingPageComplete, 97 &MergeSessionThrottle::OnBlockingPageComplete,
85 AsWeakPtr()))); 98 AsWeakPtr())));
86 *defer = true; 99 *defer = true;
87 } 100 }
88 101
102 // static.
103 bool MergeSessionThrottle::AreAllSessionMergedAlready() {
104 return !base::AtomicRefCountIsZero(&all_profiles_restored_);
105 }
106
89 void MergeSessionThrottle::OnBlockingPageComplete() { 107 void MergeSessionThrottle::OnBlockingPageComplete() {
90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
91 controller()->Resume(); 109 controller()->Resume();
92 } 110 }
93 111
94 bool MergeSessionThrottle::ShouldShowMergeSessionPage(const GURL& url) const { 112 bool MergeSessionThrottle::ShouldShowMergeSessionPage(const GURL& url) const {
95 // If we are loading google properties while merge session is in progress, 113 // If we are loading google properties while merge session is in progress,
96 // we will show delayed loading page instead. 114 // we will show delayed loading page instead.
97 return !net::NetworkChangeNotifier::IsOffline() && 115 return !net::NetworkChangeNotifier::IsOffline() &&
98 chromeos::UserManager::Get()->GetMergeSessionState() == 116 !AreAllSessionMergedAlready() &&
99 chromeos::UserManager::MERGE_STATUS_IN_PROCESS &&
100 google_util::IsGoogleHostname(url.host(), 117 google_util::IsGoogleHostname(url.host(),
101 google_util::ALLOW_SUBDOMAIN); 118 google_util::ALLOW_SUBDOMAIN);
102 } 119 }
120
121 // static
122 void MergeSessionThrottle::BlockProfile(Profile* profile) {
123 // Add a new profile to the list of those that we are currently blocking
124 // blocking page loading for.
125 if (ProfileSet::Get()->find(profile) == ProfileSet::Get()->end()) {
126 DVLOG(1) << "Blocking profile " << profile;
127 ProfileSet::Get()->insert(profile);
128
129 // Since a new profile just got blocked, we can not assume that
130 // all sessions are merged anymore.
131 if (AreAllSessionMergedAlready()) {
132 base::AtomicRefCountDec(&all_profiles_restored_);
133 DVLOG(1) << "Marking all sessions unmerged!";
134 }
135 }
136 }
137
138 // static
139 void MergeSessionThrottle::UnblockProfile(Profile* profile) {
140 // Have we blocked loading of pages for this this profile
141 // before?
142 DVLOG(1) << "Unblocking profile " << profile;
143 ProfileSet::Get()->erase(profile);
144
145 // Check if there is any other profile to block on.
146 if (ProfileSet::Get()->size() == 0) {
147 base::AtomicRefCountInc(&all_profiles_restored_);
148 DVLOG(1) << "All profiles merged " << all_profiles_restored_;
149 }
150 }
151
152 // static
153 bool MergeSessionThrottle::ShouldShowInterstitialPage(
154 int render_process_id,
155 int render_view_id) {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
157
158 if (!chromeos::UserManager::Get()->IsUserLoggedIn()) {
159 return false;
160 } else if (!chromeos::UserManager::Get()->IsLoggedInAsRegularUser()) {
161 // This is not a regular user session, let's remove the throttle
162 // permanently.
163 if (!AreAllSessionMergedAlready())
164 base::AtomicRefCountInc(&all_profiles_restored_);
165
166 return false;
167 }
168
169 RenderViewHost* render_view_host =
170 RenderViewHost::FromID(render_process_id, render_view_id);
171 if (!render_view_host)
172 return false;
173
174 WebContents* web_contents =
175 WebContents::FromRenderViewHost(render_view_host);
176 if (!web_contents)
177 return false;
178
179 content::BrowserContext* browser_context =
180 web_contents->GetBrowserContext();
181 if (!browser_context)
182 return false;
183
184 Profile* profile = Profile::FromBrowserContext(browser_context);
185 if (!profile)
186 return false;
187
188 chromeos::OAuth2LoginManager* login_manager =
189 chromeos::OAuth2LoginManagerFactory::GetInstance()->GetForProfile(
190 profile);
191 if (!login_manager)
192 return false;
193
194 switch (login_manager->state()) {
195 case chromeos::OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED:
196 // The session restore for this profile hasn't even started yet. Don't
197 // block for now.
198 // In theory this should not happen since we should
199 // kick off the session restore process for the newly added profile
200 // before we attempt loading any page.
201 if (chromeos::UserManager::Get()->IsLoggedInAsRegularUser() &&
202 !chromeos::UserManager::Get()->IsLoggedInAsStub()) {
203 LOG(WARNING) << "Loading content for a profile without "
204 << "session restore?";
205 }
206 return false;
207 case chromeos::OAuth2LoginManager::SESSION_RESTORE_PREPARING:
208 case chromeos::OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS: {
209 // Check if the session restore has been going on for a while already.
210 // If so, don't attempt to block page loading.
211 if ((base::Time::Now() -
212 login_manager->session_restore_start()).InSeconds() >
213 kMaxSessionRestoreTimeInSec) {
214 UnblockProfile(profile);
215 return false;
216 }
217
218 // Add a new profile to the list of those that we are currently blocking
219 // blocking page loading for.
220 BlockProfile(profile);
221 return true;
222 }
223 case chromeos::OAuth2LoginManager::SESSION_RESTORE_DONE:
224 case chromeos::OAuth2LoginManager::SESSION_RESTORE_FAILED: {
225 UnblockProfile(profile);
226 return false;
227 }
228 }
229
230 NOTREACHED();
231 return false;
232 }
233
234 // static.
235 void MergeSessionThrottle::ShowDeleayedLoadingPageOnUIThread(
236 int render_process_id,
237 int render_view_id,
238 const GURL& url,
239 const chromeos::MergeSessionLoadPage::CompletionCallback& callback) {
240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
241
242 if (ShouldShowInterstitialPage(render_process_id, render_view_id)) {
243 // There is a chance that the tab closed after we decided to show
244 // the offline page on the IO thread and before we actually show the
245 // offline page here on the UI thread.
246 RenderViewHost* render_view_host =
247 RenderViewHost::FromID(render_process_id, render_view_id);
248 WebContents* web_contents = render_view_host ?
249 WebContents::FromRenderViewHost(render_view_host) : NULL;
250 if (web_contents)
251 (new chromeos::MergeSessionLoadPage(web_contents, url, callback))->Show();
252 } else {
253 BrowserThread::PostTask(
254 BrowserThread::IO, FROM_HERE, callback);
255 }
256 }
257
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/login/merge_session_throttle.h ('k') | chrome/browser/chromeos/login/mock_user_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698