diff options
Diffstat (limited to 'chromium/extensions/browser/api/socket/app_firewall_hole_manager.cc')
-rw-r--r-- | chromium/extensions/browser/api/socket/app_firewall_hole_manager.cc | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/chromium/extensions/browser/api/socket/app_firewall_hole_manager.cc b/chromium/extensions/browser/api/socket/app_firewall_hole_manager.cc new file mode 100644 index 00000000000..f5973734081 --- /dev/null +++ b/chromium/extensions/browser/api/socket/app_firewall_hole_manager.cc @@ -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 base::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_ = std::move(firewall_hole); + } +} + +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; +} + +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 |