| 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);
|
| + }
|
| +}
|
| +
|
|
|