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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/login/merge_session_throttle.cc
diff --git a/chrome/browser/chromeos/login/merge_session_throttle.cc b/chrome/browser/chromeos/login/merge_session_throttle.cc
index 01f178ad6f709dab510989700386235c176ce7a5..ab08cc6dd40ddb6d7fe3ac5fdad2b276d90a7398 100644
--- a/chrome/browser/chromeos/login/merge_session_throttle.cc
+++ b/chrome/browser/chromeos/login/merge_session_throttle.cc
@@ -5,11 +5,17 @@
#include "chrome/browser/chromeos/login/merge_session_throttle.h"
#include "base/bind.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
-#include "chrome/browser/chromeos/login/login_utils.h"
+#include "base/threading/non_thread_safe.h"
+#include "base/time/time.h"
+#include "chrome/browser/chromeos/login/oauth2_login_manager.h"
+#include "chrome/browser/chromeos/login/oauth2_login_manager_factory.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/common/url_constants.h"
@@ -30,33 +36,39 @@ using content::WebContents;
namespace {
-void ShowDeleayedLoadingPage(
- int render_process_id,
- int render_view_id,
- const GURL& url,
- const chromeos::MergeSessionLoadPage::CompletionCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+const int64 kMaxSessionRestoreTimeInSec = 60;
- // Check again on UI thread and proceed if it's connected.
- if (chromeos::UserManager::Get()->GetMergeSessionState() !=
- chromeos::UserManager::MERGE_STATUS_IN_PROCESS) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE, callback);
- } else {
- RenderViewHost* render_view_host =
- RenderViewHost::FromID(render_process_id, render_view_id);
- WebContents* web_contents = render_view_host ?
- WebContents::FromRenderViewHost(render_view_host) : NULL;
- // There is a chance that the tab closed after we decided to show
- // the offline page on the IO thread and before we actually show the
- // offline page here on the UI thread.
- if (web_contents)
- (new chromeos::MergeSessionLoadPage(web_contents, url, callback))->Show();
- }
+// The set of blocked profiles.
+class ProfileSet : public base::NonThreadSafe,
+ public std::set<Profile*> {
+ public:
+ ProfileSet();
+ virtual ~ProfileSet();
+ static ProfileSet* Get();
+
+ private:
+ friend struct ::base::DefaultLazyInstanceTraits<ProfileSet>;
+};
+
+// Set of all of profiles for which restore session is in progress.
+// This static member is accessible only form UI thread.
+static base::LazyInstance<ProfileSet> g_blocked_profiles =
+ LAZY_INSTANCE_INITIALIZER;
+
+ProfileSet::ProfileSet() {
+}
+
+ProfileSet::~ProfileSet() {
+}
+
+ProfileSet* ProfileSet::Get() {
+ return g_blocked_profiles.Pointer();
}
} // namespace
+base::AtomicRefCount MergeSessionThrottle::all_profiles_restored_(0);
+
MergeSessionThrottle::MergeSessionThrottle(net::URLRequest* request)
: request_(request) {
}
@@ -66,17 +78,18 @@ MergeSessionThrottle::~MergeSessionThrottle() {
}
void MergeSessionThrottle::WillStartRequest(bool* defer) {
+ DCHECK(request_->url().SchemeIsHTTPOrHTTPS());
if (!ShouldShowMergeSessionPage(request_->url()))
return;
- DVLOG(1) << "WillStartRequest: url=" << request_->url();
+ DVLOG(1) << "WillStartRequest: defer " << request_->url();
const content::ResourceRequestInfo* info =
- content::ResourceRequestInfo::ForRequest(request_);
+ content::ResourceRequestInfo::ForRequest(request_);
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(
- &ShowDeleayedLoadingPage,
+ &MergeSessionThrottle::ShowDeleayedLoadingPageOnUIThread,
info->GetChildID(),
info->GetRouteID(),
request_->url(),
@@ -86,6 +99,11 @@ void MergeSessionThrottle::WillStartRequest(bool* defer) {
*defer = true;
}
+// static.
+bool MergeSessionThrottle::AreAllSessionMergedAlready() {
+ return !base::AtomicRefCountIsZero(&all_profiles_restored_);
+}
+
void MergeSessionThrottle::OnBlockingPageComplete() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
controller()->Resume();
@@ -95,8 +113,145 @@ bool MergeSessionThrottle::ShouldShowMergeSessionPage(const GURL& url) const {
// If we are loading google properties while merge session is in progress,
// we will show delayed loading page instead.
return !net::NetworkChangeNotifier::IsOffline() &&
- chromeos::UserManager::Get()->GetMergeSessionState() ==
- chromeos::UserManager::MERGE_STATUS_IN_PROCESS &&
+ !AreAllSessionMergedAlready() &&
google_util::IsGoogleHostname(url.host(),
google_util::ALLOW_SUBDOMAIN);
}
+
+// static
+void MergeSessionThrottle::BlockProfile(Profile* profile) {
+ // Add a new profile to the list of those that we are currently blocking
+ // blocking page loading for.
+ if (ProfileSet::Get()->find(profile) == ProfileSet::Get()->end()) {
+ DVLOG(1) << "Blocking profile " << profile;
+ ProfileSet::Get()->insert(profile);
+
+ // Since a new profile just got blocked, we can not assume that
+ // all sessions are merged anymore.
+ if (AreAllSessionMergedAlready()) {
+ base::AtomicRefCountDec(&all_profiles_restored_);
+ DVLOG(1) << "Marking all sessions unmerged!";
+ }
+ }
+}
+
+// static
+void MergeSessionThrottle::UnblockProfile(Profile* profile) {
+ // Have we blocked loading of pages for this this profile
+ // before?
+ DVLOG(1) << "Unblocking profile " << profile;
+ ProfileSet::Get()->erase(profile);
+
+ // Check if there is any other profile to block on.
+ if (ProfileSet::Get()->size() == 0) {
+ base::AtomicRefCountInc(&all_profiles_restored_);
+ DVLOG(1) << "All profiles merged " << all_profiles_restored_;
+ }
+}
+
+// static
+bool MergeSessionThrottle::ShouldShowInterstitialPage(
+ int render_process_id,
+ int render_view_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!chromeos::UserManager::Get()->IsUserLoggedIn()) {
+ return false;
+ } else if (!chromeos::UserManager::Get()->IsLoggedInAsRegularUser()) {
+ // This is not a regular user session, let's remove the throttle
+ // permanently.
+ if (!AreAllSessionMergedAlready())
+ base::AtomicRefCountInc(&all_profiles_restored_);
+
+ return false;
+ }
+
+ RenderViewHost* render_view_host =
+ RenderViewHost::FromID(render_process_id, render_view_id);
+ if (!render_view_host)
+ return false;
+
+ WebContents* web_contents =
+ WebContents::FromRenderViewHost(render_view_host);
+ if (!web_contents)
+ return false;
+
+ content::BrowserContext* browser_context =
+ web_contents->GetBrowserContext();
+ if (!browser_context)
+ return false;
+
+ Profile* profile = Profile::FromBrowserContext(browser_context);
+ if (!profile)
+ return false;
+
+ chromeos::OAuth2LoginManager* login_manager =
+ chromeos::OAuth2LoginManagerFactory::GetInstance()->GetForProfile(
+ profile);
+ if (!login_manager)
+ return false;
+
+ switch (login_manager->state()) {
+ case chromeos::OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED:
+ // The session restore for this profile hasn't even started yet. Don't
+ // block for now.
+ // In theory this should not happen since we should
+ // kick off the session restore process for the newly added profile
+ // before we attempt loading any page.
+ if (chromeos::UserManager::Get()->IsLoggedInAsRegularUser() &&
+ !chromeos::UserManager::Get()->IsLoggedInAsStub()) {
+ LOG(WARNING) << "Loading content for a profile without "
+ << "session restore?";
+ }
+ return false;
+ case chromeos::OAuth2LoginManager::SESSION_RESTORE_PREPARING:
+ case chromeos::OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS: {
+ // Check if the session restore has been going on for a while already.
+ // If so, don't attempt to block page loading.
+ if ((base::Time::Now() -
+ login_manager->session_restore_start()).InSeconds() >
+ kMaxSessionRestoreTimeInSec) {
+ UnblockProfile(profile);
+ return false;
+ }
+
+ // Add a new profile to the list of those that we are currently blocking
+ // blocking page loading for.
+ BlockProfile(profile);
+ return true;
+ }
+ case chromeos::OAuth2LoginManager::SESSION_RESTORE_DONE:
+ case chromeos::OAuth2LoginManager::SESSION_RESTORE_FAILED: {
+ UnblockProfile(profile);
+ return false;
+ }
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+// static.
+void MergeSessionThrottle::ShowDeleayedLoadingPageOnUIThread(
+ int render_process_id,
+ int render_view_id,
+ const GURL& url,
+ const chromeos::MergeSessionLoadPage::CompletionCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (ShouldShowInterstitialPage(render_process_id, render_view_id)) {
+ // There is a chance that the tab closed after we decided to show
+ // the offline page on the IO thread and before we actually show the
+ // offline page here on the UI thread.
+ RenderViewHost* render_view_host =
+ RenderViewHost::FromID(render_process_id, render_view_id);
+ WebContents* web_contents = render_view_host ?
+ WebContents::FromRenderViewHost(render_view_host) : NULL;
+ if (web_contents)
+ (new chromeos::MergeSessionLoadPage(web_contents, url, callback))->Show();
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE, callback);
+ }
+}
+
« 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