Index: extensions/browser/api/socket/app_firewall_hole_manager.cc |
diff --git a/extensions/browser/api/socket/app_firewall_hole_manager.cc b/extensions/browser/api/socket/app_firewall_hole_manager.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ce7ff2a19c065eda9ba51bf00c6dbe38135b624b |
--- /dev/null |
+++ b/extensions/browser/api/socket/app_firewall_hole_manager.cc |
@@ -0,0 +1,164 @@ |
+// 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() { |
rpaquay
2015/03/23 18:29:07
nit: Move destructor after constructor?
Reilly Grant (use Gerrit)
2015/03/23 20:09:31
This matches the order in the header file.
|
+ 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); |
+} |
+ |
+AppFirewallHole* AppFirewallHoleManager::Open(AppFirewallHole::PortType type, |
+ uint16_t port, |
+ const std::string& extension_id) { |
+ AppFirewallHole* hole = new AppFirewallHole(this, type, port, extension_id); |
+ tracked_holes_.insert(std::make_pair(extension_id, hole)); |
+ 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 |