root/apps/app_window_registry.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetWindowKeyForRenderViewHost
  2. devtools_callback_
  3. Get
  4. AddAppWindow
  5. AppWindowIconChanged
  6. AppWindowActivated
  7. RemoveAppWindow
  8. AddObserver
  9. RemoveObserver
  10. GetAppWindowsForApp
  11. CloseAllAppWindowsForApp
  12. GetAppWindowForRenderViewHost
  13. GetAppWindowForNativeWindow
  14. GetCurrentAppWindowForApp
  15. GetAppWindowForAppAndKey
  16. HadDevToolsAttached
  17. GetAppWindowForNativeWindowAnyProfile
  18. IsAppWindowRegisteredInAnyProfile
  19. OnDevToolsStateChanged
  20. AddAppWindowToList
  21. BringToFront
  22. GetForBrowserContext
  23. GetInstance
  24. BuildServiceInstanceFor
  25. ServiceIsCreatedWithBrowserContext
  26. ServiceIsNULLWhileTesting
  27. GetBrowserContextToUse

// Copyright 2014 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 "apps/app_window.h"
#include "apps/app_window_registry.h"
#include "apps/apps_client.h"
#include "apps/ui/native_app_window.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_manager.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/common/extension.h"

namespace {

// Create a key that identifies a AppWindow in a RenderViewHost across App
// reloads. If the window was given an id in CreateParams, the key is the
// extension id, a colon separator, and the AppWindow's |id|. If there is no
// |id|, the chrome-extension://extension-id/page.html URL will be used. If the
// RenderViewHost is not for a AppWindow, return an empty string.
std::string GetWindowKeyForRenderViewHost(
    const apps::AppWindowRegistry* registry,
    content::RenderViewHost* render_view_host) {
  apps::AppWindow* app_window =
      registry->GetAppWindowForRenderViewHost(render_view_host);
  if (!app_window)
    return std::string();  // Not a AppWindow.

  if (app_window->window_key().empty())
    return app_window->web_contents()->GetURL().possibly_invalid_spec();

  std::string key = app_window->extension()->id();
  key += ':';
  key += app_window->window_key();
  return key;
}

}  // namespace

namespace apps {

AppWindowRegistry::AppWindowRegistry(content::BrowserContext* context)
    : context_(context),
      devtools_callback_(base::Bind(&AppWindowRegistry::OnDevToolsStateChanged,
                                    base::Unretained(this))) {
  content::DevToolsManager::GetInstance()->AddAgentStateCallback(
      devtools_callback_);
}

AppWindowRegistry::~AppWindowRegistry() {
  content::DevToolsManager::GetInstance()->RemoveAgentStateCallback(
      devtools_callback_);
}

// static
AppWindowRegistry* AppWindowRegistry::Get(content::BrowserContext* context) {
  return Factory::GetForBrowserContext(context, true /* create */);
}

void AppWindowRegistry::AddAppWindow(AppWindow* app_window) {
  BringToFront(app_window);
  FOR_EACH_OBSERVER(Observer, observers_, OnAppWindowAdded(app_window));
}

void AppWindowRegistry::AppWindowIconChanged(AppWindow* app_window) {
  AddAppWindowToList(app_window);
  FOR_EACH_OBSERVER(Observer, observers_, OnAppWindowIconChanged(app_window));
}

void AppWindowRegistry::AppWindowActivated(AppWindow* app_window) {
  BringToFront(app_window);
}

void AppWindowRegistry::RemoveAppWindow(AppWindow* app_window) {
  const AppWindowList::iterator it =
      std::find(app_windows_.begin(), app_windows_.end(), app_window);
  if (it != app_windows_.end())
    app_windows_.erase(it);
  FOR_EACH_OBSERVER(Observer, observers_, OnAppWindowRemoved(app_window));
}

void AppWindowRegistry::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void AppWindowRegistry::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

AppWindowRegistry::AppWindowList AppWindowRegistry::GetAppWindowsForApp(
    const std::string& app_id) const {
  AppWindowList app_windows;
  for (AppWindowList::const_iterator i = app_windows_.begin();
       i != app_windows_.end();
       ++i) {
    if ((*i)->extension_id() == app_id)
      app_windows.push_back(*i);
  }
  return app_windows;
}

void AppWindowRegistry::CloseAllAppWindowsForApp(const std::string& app_id) {
  for (AppWindowList::const_iterator i = app_windows_.begin();
       i != app_windows_.end();) {
    AppWindow* app_window = *(i++);
    if (app_window->extension_id() == app_id)
      app_window->GetBaseWindow()->Close();
  }
}

AppWindow* AppWindowRegistry::GetAppWindowForRenderViewHost(
    content::RenderViewHost* render_view_host) const {
  for (AppWindowList::const_iterator i = app_windows_.begin();
       i != app_windows_.end();
       ++i) {
    if ((*i)->web_contents()->GetRenderViewHost() == render_view_host)
      return *i;
  }

  return NULL;
}

AppWindow* AppWindowRegistry::GetAppWindowForNativeWindow(
    gfx::NativeWindow window) const {
  for (AppWindowList::const_iterator i = app_windows_.begin();
       i != app_windows_.end();
       ++i) {
    if ((*i)->GetNativeWindow() == window)
      return *i;
  }

  return NULL;
}

AppWindow* AppWindowRegistry::GetCurrentAppWindowForApp(
    const std::string& app_id) const {
  AppWindow* result = NULL;
  for (AppWindowList::const_iterator i = app_windows_.begin();
       i != app_windows_.end();
       ++i) {
    if ((*i)->extension()->id() == app_id) {
      result = *i;
      if (result->GetBaseWindow()->IsActive())
        return result;
    }
  }

  return result;
}

AppWindow* AppWindowRegistry::GetAppWindowForAppAndKey(
    const std::string& app_id,
    const std::string& window_key) const {
  AppWindow* result = NULL;
  for (AppWindowList::const_iterator i = app_windows_.begin();
       i != app_windows_.end();
       ++i) {
    if ((*i)->extension()->id() == app_id && (*i)->window_key() == window_key) {
      result = *i;
      if (result->GetBaseWindow()->IsActive())
        return result;
    }
  }
  return result;
}

bool AppWindowRegistry::HadDevToolsAttached(
    content::RenderViewHost* render_view_host) const {
  std::string key = GetWindowKeyForRenderViewHost(this, render_view_host);
  return key.empty() ? false : inspected_windows_.count(key) != 0;
}

// static
AppWindow* AppWindowRegistry::GetAppWindowForNativeWindowAnyProfile(
    gfx::NativeWindow window) {
  std::vector<content::BrowserContext*> contexts =
      AppsClient::Get()->GetLoadedBrowserContexts();
  for (std::vector<content::BrowserContext*>::const_iterator i =
           contexts.begin();
       i != contexts.end();
       ++i) {
    AppWindowRegistry* registry =
        Factory::GetForBrowserContext(*i, false /* create */);
    if (!registry)
      continue;

    AppWindow* app_window = registry->GetAppWindowForNativeWindow(window);
    if (app_window)
      return app_window;
  }

  return NULL;
}

// static
bool AppWindowRegistry::IsAppWindowRegisteredInAnyProfile(
    int window_type_mask) {
  std::vector<content::BrowserContext*> contexts =
      AppsClient::Get()->GetLoadedBrowserContexts();
  for (std::vector<content::BrowserContext*>::const_iterator i =
           contexts.begin();
       i != contexts.end();
       ++i) {
    AppWindowRegistry* registry =
        Factory::GetForBrowserContext(*i, false /* create */);
    if (!registry)
      continue;

    const AppWindowList& app_windows = registry->app_windows();
    if (app_windows.empty())
      continue;

    if (window_type_mask == 0)
      return true;

    for (const_iterator j = app_windows.begin(); j != app_windows.end(); ++j) {
      if ((*j)->window_type() & window_type_mask)
        return true;
    }
  }

  return false;
}

void AppWindowRegistry::OnDevToolsStateChanged(
    content::DevToolsAgentHost* agent_host,
    bool attached) {
  content::RenderViewHost* rvh = agent_host->GetRenderViewHost();
  // Ignore unrelated notifications.
  if (!rvh ||
      rvh->GetSiteInstance()->GetProcess()->GetBrowserContext() != context_)
    return;

  std::string key = GetWindowKeyForRenderViewHost(this, rvh);
  if (key.empty())
    return;

  if (attached)
    inspected_windows_.insert(key);
  else
    inspected_windows_.erase(key);
}

void AppWindowRegistry::AddAppWindowToList(AppWindow* app_window) {
  const AppWindowList::iterator it =
      std::find(app_windows_.begin(), app_windows_.end(), app_window);
  if (it != app_windows_.end())
    return;
  app_windows_.push_back(app_window);
}

void AppWindowRegistry::BringToFront(AppWindow* app_window) {
  const AppWindowList::iterator it =
      std::find(app_windows_.begin(), app_windows_.end(), app_window);
  if (it != app_windows_.end())
    app_windows_.erase(it);
  app_windows_.push_front(app_window);
}

///////////////////////////////////////////////////////////////////////////////
// Factory boilerplate

// static
AppWindowRegistry* AppWindowRegistry::Factory::GetForBrowserContext(
    content::BrowserContext* context,
    bool create) {
  return static_cast<AppWindowRegistry*>(
      GetInstance()->GetServiceForBrowserContext(context, create));
}

AppWindowRegistry::Factory* AppWindowRegistry::Factory::GetInstance() {
  return Singleton<AppWindowRegistry::Factory>::get();
}

AppWindowRegistry::Factory::Factory()
    : BrowserContextKeyedServiceFactory(
          "AppWindowRegistry",
          BrowserContextDependencyManager::GetInstance()) {}

AppWindowRegistry::Factory::~Factory() {}

KeyedService* AppWindowRegistry::Factory::BuildServiceInstanceFor(
    content::BrowserContext* context) const {
  return new AppWindowRegistry(context);
}

bool AppWindowRegistry::Factory::ServiceIsCreatedWithBrowserContext() const {
  return true;
}

bool AppWindowRegistry::Factory::ServiceIsNULLWhileTesting() const {
  return false;
}

content::BrowserContext* AppWindowRegistry::Factory::GetBrowserContextToUse(
    content::BrowserContext* context) const {
  return extensions::ExtensionsBrowserClient::Get()->GetOriginalContext(
      context);
}

}  // namespace extensions

/* [<][>][^][v][top][bottom][index][help] */