forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bind open firewall ports to visible application windows.
To prevent an application from continuing to listen for TCP connections or incoming UDP packets when the user is not aware that it is still running this patch observes the state of its associated AppWindows and opens and closes ports as necessary. The socket itself is left open so that state is not lost. BUG=435404 Review URL: https://codereview.chromium.org/1022663003 Cr-Commit-Position: refs/heads/master@{#321911}
- Loading branch information
Showing
8 changed files
with
315 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
166 changes: 166 additions & 0 deletions
166
extensions/browser/api/socket/app_firewall_hole_manager.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
// Copyright 2015 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. | ||
|
||
#include "extensions/browser/api/socket/app_firewall_hole_manager.h" | ||
|
||
#include <utility> | ||
|
||
#include "base/bind.h" | ||
#include "base/stl_util.h" | ||
#include "components/keyed_service/content/browser_context_dependency_manager.h" | ||
#include "content/public/browser/browser_context.h" | ||
#include "extensions/browser/app_window/app_window.h" | ||
|
||
using chromeos::FirewallHole; | ||
using content::BrowserContext; | ||
|
||
namespace extensions { | ||
|
||
namespace { | ||
|
||
class AppFirewallHoleManagerFactory : public BrowserContextKeyedServiceFactory { | ||
public: | ||
static AppFirewallHoleManager* GetForBrowserContext(BrowserContext* context, | ||
bool create) { | ||
return static_cast<AppFirewallHoleManager*>( | ||
GetInstance()->GetServiceForBrowserContext(context, create)); | ||
} | ||
|
||
static AppFirewallHoleManagerFactory* GetInstance() { | ||
return Singleton<AppFirewallHoleManagerFactory>::get(); | ||
} | ||
|
||
AppFirewallHoleManagerFactory() | ||
: BrowserContextKeyedServiceFactory( | ||
"AppFirewallHoleManager", | ||
BrowserContextDependencyManager::GetInstance()) { | ||
DependsOn(AppWindowRegistry::Factory::GetInstance()); | ||
} | ||
|
||
~AppFirewallHoleManagerFactory() override {} | ||
|
||
private: | ||
// BrowserContextKeyedServiceFactory | ||
KeyedService* BuildServiceInstanceFor( | ||
BrowserContext* context) const override { | ||
return new AppFirewallHoleManager(context); | ||
} | ||
|
||
BrowserContext* GetBrowserContextToUse( | ||
BrowserContext* context) const override { | ||
return context; | ||
} | ||
}; | ||
|
||
bool HasVisibleAppWindows(BrowserContext* context, | ||
const std::string& extension_id) { | ||
AppWindowRegistry* registry = AppWindowRegistry::Get(context); | ||
|
||
for (const AppWindow* window : registry->GetAppWindowsForApp(extension_id)) { | ||
if (!window->is_hidden()) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
} // namespace | ||
|
||
AppFirewallHole::~AppFirewallHole() { | ||
manager_->Close(this); | ||
} | ||
|
||
AppFirewallHole::AppFirewallHole(AppFirewallHoleManager* manager, | ||
PortType type, | ||
uint16_t port, | ||
const std::string& extension_id) | ||
: type_(type), | ||
port_(port), | ||
extension_id_(extension_id), | ||
manager_(manager), | ||
weak_factory_(this) { | ||
} | ||
|
||
void AppFirewallHole::SetVisible(bool app_visible) { | ||
app_visible_ = app_visible; | ||
if (app_visible_) { | ||
if (!firewall_hole_) { | ||
FirewallHole::Open(type_, port_, "" /* all interfaces */, | ||
base::Bind(&AppFirewallHole::OnFirewallHoleOpened, | ||
weak_factory_.GetWeakPtr())); | ||
} | ||
} else { | ||
firewall_hole_.reset(nullptr); | ||
} | ||
} | ||
|
||
void AppFirewallHole::OnFirewallHoleOpened( | ||
scoped_ptr<FirewallHole> firewall_hole) { | ||
if (app_visible_) { | ||
DCHECK(!firewall_hole_); | ||
firewall_hole_ = firewall_hole.Pass(); | ||
} | ||
} | ||
|
||
AppFirewallHoleManager::AppFirewallHoleManager(BrowserContext* context) | ||
: context_(context), observer_(this) { | ||
observer_.Add(AppWindowRegistry::Get(context)); | ||
} | ||
|
||
AppFirewallHoleManager::~AppFirewallHoleManager() { | ||
STLDeleteValues(&tracked_holes_); | ||
} | ||
|
||
AppFirewallHoleManager* AppFirewallHoleManager::Get(BrowserContext* context) { | ||
return AppFirewallHoleManagerFactory::GetForBrowserContext(context, true); | ||
} | ||
|
||
scoped_ptr<AppFirewallHole> AppFirewallHoleManager::Open( | ||
AppFirewallHole::PortType type, | ||
uint16_t port, | ||
const std::string& extension_id) { | ||
scoped_ptr<AppFirewallHole> hole( | ||
new AppFirewallHole(this, type, port, extension_id)); | ||
tracked_holes_.insert(std::make_pair(extension_id, hole.get())); | ||
if (HasVisibleAppWindows(context_, extension_id)) { | ||
hole->SetVisible(true); | ||
} | ||
return hole.Pass(); | ||
} | ||
|
||
void AppFirewallHoleManager::Close(AppFirewallHole* hole) { | ||
auto range = tracked_holes_.equal_range(hole->extension_id()); | ||
for (auto iter = range.first; iter != range.second; ++iter) { | ||
if (iter->second == hole) { | ||
tracked_holes_.erase(iter); | ||
return; | ||
} | ||
} | ||
NOTREACHED(); | ||
} | ||
|
||
void AppFirewallHoleManager::OnAppWindowRemoved(AppWindow* app_window) { | ||
OnAppWindowHidden(app_window); | ||
} | ||
|
||
void AppFirewallHoleManager::OnAppWindowHidden(AppWindow* app_window) { | ||
DCHECK(context_ == app_window->browser_context()); | ||
if (!HasVisibleAppWindows(context_, app_window->extension_id())) { | ||
const auto& range = tracked_holes_.equal_range(app_window->extension_id()); | ||
for (auto iter = range.first; iter != range.second; ++iter) { | ||
iter->second->SetVisible(false); | ||
} | ||
} | ||
} | ||
|
||
void AppFirewallHoleManager::OnAppWindowShown(AppWindow* app_window, | ||
bool was_hidden) { | ||
const auto& range = tracked_holes_.equal_range(app_window->extension_id()); | ||
for (auto iter = range.first; iter != range.second; ++iter) { | ||
iter->second->SetVisible(true); | ||
} | ||
} | ||
|
||
} // namespace extensions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Copyright 2015 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 EXTENSIONS_BROWSER_API_SOCKET_APP_FIREWALL_HOLE_MANAGER_H_ | ||
#define EXTENSIONS_BROWSER_API_SOCKET_APP_FIREWALL_HOLE_MANAGER_H_ | ||
|
||
#include <map> | ||
|
||
#include "base/scoped_observer.h" | ||
#include "chromeos/network/firewall_hole.h" | ||
#include "extensions/browser/app_window/app_window_registry.h" | ||
|
||
namespace content { | ||
class BrowserContext; | ||
} | ||
|
||
namespace extensions { | ||
|
||
class AppFirewallHoleManager; | ||
|
||
// Represents an open port in the system firewall that will be opened and closed | ||
// automatically when the application has a visible window or not. The hole is | ||
// closed on destruction. | ||
class AppFirewallHole { | ||
public: | ||
typedef chromeos::FirewallHole::PortType PortType; | ||
|
||
~AppFirewallHole(); | ||
|
||
PortType type() const { return type_; } | ||
uint16_t port() const { return port_; } | ||
const std::string& extension_id() const { return extension_id_; } | ||
|
||
private: | ||
friend class AppFirewallHoleManager; | ||
|
||
AppFirewallHole(AppFirewallHoleManager* manager, | ||
PortType type, | ||
uint16_t port, | ||
const std::string& extension_id); | ||
|
||
void SetVisible(bool app_visible); | ||
void OnFirewallHoleOpened(scoped_ptr<chromeos::FirewallHole> firewall_hole); | ||
|
||
PortType type_; | ||
uint16_t port_; | ||
std::string extension_id_; | ||
bool app_visible_ = false; | ||
|
||
// This object is destroyed when the AppFirewallHoleManager that owns it is | ||
// destroyed and so a raw pointer is okay here. | ||
AppFirewallHoleManager* manager_; | ||
|
||
// This will hold the FirewallHole object if one is opened. | ||
scoped_ptr<chromeos::FirewallHole> firewall_hole_; | ||
|
||
base::WeakPtrFactory<AppFirewallHole> weak_factory_; | ||
}; | ||
|
||
// Tracks ports in the system firewall opened by an application so that they | ||
// may be automatically opened and closed only when the application has a | ||
// visible window. | ||
class AppFirewallHoleManager : public KeyedService, | ||
public AppWindowRegistry::Observer { | ||
public: | ||
explicit AppFirewallHoleManager(content::BrowserContext* context); | ||
~AppFirewallHoleManager() override; | ||
|
||
// Returns the instance for a given browser context, or NULL if none. | ||
static AppFirewallHoleManager* Get(content::BrowserContext* context); | ||
|
||
// Takes ownership of the AppFirewallHole and will open a port on the system | ||
// firewall if the associated application is currently visible. | ||
scoped_ptr<AppFirewallHole> Open(AppFirewallHole::PortType type, | ||
uint16_t port, | ||
const std::string& extension_id); | ||
|
||
private: | ||
friend class AppFirewallHole; | ||
|
||
void Close(AppFirewallHole* hole); | ||
|
||
// AppWindowRegistry::Observer | ||
void OnAppWindowRemoved(AppWindow* app_window) override; | ||
void OnAppWindowHidden(AppWindow* app_window) override; | ||
void OnAppWindowShown(AppWindow* app_window, bool was_hidden) override; | ||
|
||
content::BrowserContext* context_; | ||
ScopedObserver<AppWindowRegistry, AppWindowRegistry::Observer> observer_; | ||
std::multimap<std::string, AppFirewallHole*> tracked_holes_; | ||
}; | ||
|
||
} // namespace extensions | ||
|
||
#endif // EXTENSIONS_BROWSER_API_SOCKET_APP_FIREWALL_HOLE_MANAGER_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.