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
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/login/merge_session_throttle.h"
6
7#include "base/bind.h"
8#include "base/logging.h"
9#include "base/memory/singleton.h"
10#include "base/metrics/histogram.h"
11#include "base/strings/string_util.h"
12#include "chrome/browser/chromeos/login/login_utils.h"
13#include "chrome/browser/google/google_util.h"
14#include "chrome/browser/net/chrome_url_request_context.h"
15#include "chrome/common/url_constants.h"
16#include "content/public/browser/browser_thread.h"
17#include "content/public/browser/render_view_host.h"
18#include "content/public/browser/resource_controller.h"
19#include "content/public/browser/web_contents.h"
20#include "net/base/net_errors.h"
21#include "net/base/net_util.h"
22#include "net/base/network_change_notifier.h"
23#include "net/url_request/url_request.h"
24#include "net/url_request/url_request_context.h"
25
26using content::BrowserThread;
27using content::RenderViewHost;
28using content::WebContents;
29
30namespace {
31
32void ShowDeleayedLoadingPage(
33    int render_process_id,
34    int render_view_id,
35    const GURL& url,
36    const chromeos::MergeSessionLoadPage::CompletionCallback& callback) {
37  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
38
39  // Check again on UI thread and proceed if it's connected.
40  if (chromeos::UserManager::Get()->GetMergeSessionState() !=
41          chromeos::UserManager::MERGE_STATUS_IN_PROCESS) {
42    BrowserThread::PostTask(
43        BrowserThread::IO, FROM_HERE, callback);
44  } else {
45    RenderViewHost* render_view_host =
46        RenderViewHost::FromID(render_process_id, render_view_id);
47    WebContents* web_contents = render_view_host ?
48        WebContents::FromRenderViewHost(render_view_host) : NULL;
49    // There is a chance that the tab closed after we decided to show
50    // the offline page on the IO thread and before we actually show the
51    // offline page here on the UI thread.
52    if (web_contents)
53      (new chromeos::MergeSessionLoadPage(web_contents, url, callback))->Show();
54  }
55}
56
57}  // namespace
58
59MergeSessionThrottle::MergeSessionThrottle(int render_process_id,
60                                           int render_view_id,
61                                           net::URLRequest* request)
62    : render_process_id_(render_process_id),
63      render_view_id_(render_view_id),
64      request_(request) {
65}
66
67MergeSessionThrottle::~MergeSessionThrottle() {
68  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
69}
70
71void MergeSessionThrottle::WillStartRequest(bool* defer) {
72  if (!ShouldShowMergeSessionPage(request_->url()))
73    return;
74
75  DVLOG(1) << "WillStartRequest: url=" << request_->url();
76  BrowserThread::PostTask(
77      BrowserThread::UI,
78      FROM_HERE,
79      base::Bind(
80          &ShowDeleayedLoadingPage,
81          render_process_id_,
82          render_view_id_,
83          request_->url(),
84          base::Bind(
85              &MergeSessionThrottle::OnBlockingPageComplete,
86              AsWeakPtr())));
87  *defer = true;
88}
89
90void MergeSessionThrottle::OnBlockingPageComplete() {
91  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
92  controller()->Resume();
93}
94
95bool MergeSessionThrottle::ShouldShowMergeSessionPage(const GURL& url) const {
96  // If we are loading google properties while merge session is in progress,
97  // we will show delayed loading page instead.
98  return !net::NetworkChangeNotifier::IsOffline() &&
99         chromeos::UserManager::Get()->GetMergeSessionState() ==
100             chromeos::UserManager::MERGE_STATUS_IN_PROCESS &&
101         google_util::IsGoogleHostname(url.host(),
102                                       google_util::ALLOW_SUBDOMAIN);
103}
104