summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/api/messaging/incognito_connectability.h
blob: 026ade958ec2f2306ace5d55ba34f34eaf0d3681 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_EXTENSIONS_API_MESSAGING_INCOGNITO_CONNECTABILITY_H_
#define CHROME_BROWSER_EXTENSIONS_API_MESSAGING_INCOGNITO_CONNECTABILITY_H_

#include <set>

#include "base/memory/weak_ptr.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "url/gurl.h"

namespace content {
class BrowserContext;
class WebContents;
}

namespace infobars {
class InfoBar;
class InfoBarManager;
}

namespace extensions {
class Extension;

// Tracks the web connectability of domains to extensions in incognito mode.
//
// The most important functionality is prompting the user to allow or disallow
// connections from incognito tabs to extensions or apps. Even if an extension
// hasn't been enabled in incognito mode, it's still useful for web sites to be
// able to send messages to them, with user constent. For apps, it's essential
// we have this functionality because there is no way for them to be enabled in
// incognito.
class IncognitoConnectability : public BrowserContextKeyedAPI {
 public:
  // While in scope, immediately either accepts or denies the alerts that show
  // up, and counts the number of times it was invoked.
  class ScopedAlertTracker {
   public:
    enum Mode {
      INTERACTIVE,
      ALWAYS_ALLOW,
      ALWAYS_DENY,
    };

    explicit ScopedAlertTracker(Mode mode);

    ~ScopedAlertTracker();

    // Returns the number of times the alert has been shown since
    // GetAndResetAlertCount was last called.
    int GetAndResetAlertCount();

   private:
    int last_checked_invocation_count_;
  };

  // Returns the IncognitoConnectability object for |context|. |context| must
  // be off-the-record.
  static IncognitoConnectability* Get(content::BrowserContext* context);

  // Passes true to the provided callback if |url| is allowed to connect from
  // this profile, false otherwise. If unknown, the user will be prompted before
  // an answer is returned.
  void Query(const Extension* extension,
             content::WebContents* web_contents,
             const GURL& url,
             const base::Callback<void(bool)>& callback);

 private:
  struct TabContext {
    TabContext();
    TabContext(const TabContext& other);
    ~TabContext();

    // The infobar being shown in a given tab. The InfoBarManager maintains
    // ownership of this object. This struct must always be destroyed before the
    // infobar it tracks.
    infobars::InfoBar* infobar;
    // Connectability queries outstanding on this infobar.
    std::vector<base::Callback<void(bool)>> callbacks;
  };

  friend class BrowserContextKeyedAPIFactory<IncognitoConnectability>;

  explicit IncognitoConnectability(content::BrowserContext* context);
  ~IncognitoConnectability() override;

  typedef std::map<std::string, std::set<GURL> > ExtensionToOriginsMap;
  typedef std::pair<std::string, GURL> ExtensionOriginPair;
  typedef std::map<infobars::InfoBarManager*, TabContext> PendingOrigin;
  typedef std::map<ExtensionOriginPair, PendingOrigin> PendingOriginMap;

  // Called with the user's selection from the infobar.
  // |response == INTERACTIVE| indicates that the user closed the infobar
  // without selecting allow or deny.
  void OnInteractiveResponse(const std::string& extension_id,
                             const GURL& origin,
                             infobars::InfoBarManager* infobar_manager,
                             ScopedAlertTracker::Mode response);

  // Returns true if the (|extension|, |origin|) pair appears in the map.
  bool IsInMap(const Extension* extension,
               const GURL& origin,
               const ExtensionToOriginsMap& map);

  // BrowserContextKeyedAPI implementation.
  static BrowserContextKeyedAPIFactory<IncognitoConnectability>*
      GetFactoryInstance();
  static const char* service_name() {
    return "Messaging.IncognitoConnectability";
  }
  static const bool kServiceHasOwnInstanceInIncognito = true;
  static const bool kServiceIsCreatedWithBrowserContext = false;

  // The origins that have been prompted for and either allowed or disallowed.
  // These are deliberately stored in-memory so that they're reset when the
  // profile is destroyed (i.e. when the last incognito window is closed).
  ExtensionToOriginsMap allowed_origins_;
  ExtensionToOriginsMap disallowed_origins_;

  // This maps extension/origin pairs to the tabs with an infobar prompting for
  // incognito connectability on them. This also stores a reference to the
  // infobar and the set of callbacks (passed to Query) that will be called when
  // the query is resolved.
  PendingOriginMap pending_origins_;

  base::WeakPtrFactory<IncognitoConnectability> weak_factory_;
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_API_MESSAGING_INCOGNITO_CONNECTABILITY_H_