blob: 3dbf249eb593162ced019574f2169d79289f5fcb [file] [log] [blame]
// 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"
class InfoBarService;
namespace content {
class BrowserContext;
class WebContents;
}
namespace infobars {
class InfoBar;
}
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. Users are not prompted
// for extensions which can be enabled in incognito mode. However 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,
base::OnceCallback<void(bool)> callback);
private:
struct TabContext {
TabContext();
~TabContext();
// TabContext can't be copied since the callbacks are OnceCallback (and
// hence, move-only).
TabContext(const TabContext& other) = delete;
TabContext& operator=(const TabContext&) = delete;
// The infobar being shown in a given tab. The InfoBarService 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::OnceCallback<void(bool)>> callbacks;
};
friend class BrowserContextKeyedAPIFactory<IncognitoConnectability>;
explicit IncognitoConnectability(content::BrowserContext* context);
~IncognitoConnectability() override;
using ExtensionToOriginsMap = std::map<std::string, std::set<GURL>>;
using ExtensionOriginPair = std::pair<std::string, GURL>;
using PendingOrigin = std::map<InfoBarService*, TabContext>;
using PendingOriginMap = std::map<ExtensionOriginPair, PendingOrigin>;
// 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,
InfoBarService* infobar_service,
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_{this};
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_MESSAGING_INCOGNITO_CONNECTABILITY_H_