1// Copyright 2014 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#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_MERGE_SESSION_THROTTLE_H_
6#define CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_MERGE_SESSION_THROTTLE_H_
7
8#include <set>
9
10#include "base/atomic_ref_count.h"
11#include "base/memory/ref_counted.h"
12#include "base/memory/weak_ptr.h"
13#include "content/public/browser/resource_throttle.h"
14#include "content/public/common/resource_type.h"
15#include "net/base/completion_callback.h"
16
17class Profile;
18
19namespace net {
20class URLRequest;
21}
22
23namespace chromeos {
24class OAuth2LoginManager;
25}
26
27// Used to show an interstitial page while merge session process (cookie
28// reconstruction from OAuth2 refresh token in ChromeOS login) is still in
29// progress while we are attempting to load a google property.
30class MergeSessionThrottle
31    : public content::ResourceThrottle,
32      public base::SupportsWeakPtr<MergeSessionThrottle> {
33 public:
34  // Passed a boolean indicating whether or not it is OK to proceed with the
35  // page load.
36  typedef base::Closure CompletionCallback;
37
38  explicit MergeSessionThrottle(net::URLRequest* request,
39                                content::ResourceType resource_type);
40  virtual ~MergeSessionThrottle();
41
42  // content::ResourceThrottle implementation:
43  virtual void WillStartRequest(bool* defer) OVERRIDE;
44  virtual const char* GetNameForLogging() const OVERRIDE;
45
46  // Checks if session is already merged.
47  static bool AreAllSessionMergedAlready();
48
49 private:
50
51  // MergeSessionLoadPage callback.
52  void OnBlockingPageComplete();
53
54  // Erase the state associated with a deferred load request.
55  void ClearRequestInfo();
56  bool IsRemote(const GURL& url) const;
57
58  // True if we |url| loading should be delayed. The function
59  // is safe to be called on any thread.
60  bool ShouldDelayUrl(const GURL& url) const;
61
62  // Adds/removes |profile| to/from the blocking profiles set.
63  static void BlockProfile(Profile* profile);
64  static void UnblockProfile(Profile* profile);
65
66  // Helper method that checks if we should delay reasource loading based on
67  // the state of the Profile that's derived from |render_process_id| and
68  // |render_view_id|.
69  static bool ShouldDelayRequest(int render_process_id,
70                                 int render_view_id);
71
72  // Tests merge session status and if needed generates request
73  // waiter (for content::RESOURCE_TYPE_XHR content) or shows interstitial page
74  // (for content::RESOURCE_TYPE_MAIN_FRAME).
75  // The function must be called from UI thread.
76  static void DeleayResourceLoadingOnUIThread(
77      content::ResourceType resource_type,
78      int render_process_id,
79      int render_view_id,
80      const GURL& url,
81      const MergeSessionThrottle::CompletionCallback& callback);
82
83  net::URLRequest* request_;
84  content::ResourceType resource_type_;
85
86  // Global counter that keeps the track of session merge status for all
87  // encountered profiles. This is used to determine if a throttle should
88  // even be even added to new requests. Value of 0 (initial) means that we
89  // probably have some profiles to restore, while 1 means that all known
90  // profiles are restored.
91  static base::AtomicRefCount all_profiles_restored_;
92
93  DISALLOW_COPY_AND_ASSIGN(MergeSessionThrottle);
94};
95
96#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_MERGE_SESSION_THROTTLE_H_
97