1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_info_map.h"
6
7#include "chrome/common/extensions/extension.h"
8#include "chrome/common/url_constants.h"
9#include "content/browser/browser_thread.h"
10
11namespace {
12
13static void CheckOnValidThread() {
14  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
15}
16
17}  // namespace
18
19ExtensionInfoMap::ExtensionInfoMap() {
20}
21
22ExtensionInfoMap::~ExtensionInfoMap() {
23}
24
25void ExtensionInfoMap::AddExtension(const Extension* extension) {
26  CheckOnValidThread();
27  extension_info_[extension->id()] = extension;
28  Map::iterator iter = disabled_extension_info_.find(extension->id());
29  if (iter != disabled_extension_info_.end())
30    disabled_extension_info_.erase(iter);
31}
32
33void ExtensionInfoMap::RemoveExtension(const std::string& id,
34    const UnloadedExtensionInfo::Reason reason) {
35  CheckOnValidThread();
36  Map::iterator iter = extension_info_.find(id);
37  if (iter != extension_info_.end()) {
38    if (reason == UnloadedExtensionInfo::DISABLE)
39      disabled_extension_info_[id] = (*iter).second;
40    extension_info_.erase(iter);
41  } else if (reason != UnloadedExtensionInfo::DISABLE) {
42    // If the extension was uninstalled, make sure it's removed from the map of
43    // disabled extensions.
44    disabled_extension_info_.erase(id);
45  } else {
46    // NOTE: This can currently happen if we receive multiple unload
47    // notifications, e.g. setting incognito-enabled state for a
48    // disabled extension (e.g., via sync).  See
49    // http://code.google.com/p/chromium/issues/detail?id=50582 .
50    NOTREACHED() << id;
51  }
52}
53
54
55std::string ExtensionInfoMap::GetNameForExtension(const std::string& id) const {
56  Map::const_iterator iter = extension_info_.find(id);
57  if (iter != extension_info_.end())
58    return iter->second->name();
59  else
60    return std::string();
61}
62
63FilePath ExtensionInfoMap::GetPathForExtension(const std::string& id) const {
64  Map::const_iterator iter = extension_info_.find(id);
65  if (iter != extension_info_.end())
66    return iter->second->path();
67  else
68    return FilePath();
69}
70
71FilePath ExtensionInfoMap::GetPathForDisabledExtension(
72    const std::string& id) const {
73  Map::const_iterator iter = disabled_extension_info_.find(id);
74  if (iter != disabled_extension_info_.end())
75    return iter->second->path();
76  else
77    return FilePath();
78}
79
80bool ExtensionInfoMap::ExtensionHasWebExtent(const std::string& id) const {
81  Map::const_iterator iter = extension_info_.find(id);
82  return iter != extension_info_.end() &&
83      !iter->second->web_extent().is_empty();
84}
85
86bool ExtensionInfoMap::ExtensionCanLoadInIncognito(
87    const std::string& id) const {
88  Map::const_iterator iter = extension_info_.find(id);
89  // Only split-mode extensions can load in incognito profiles.
90  return iter != extension_info_.end() && iter->second->incognito_split_mode();
91}
92
93std::string ExtensionInfoMap::GetDefaultLocaleForExtension(
94    const std::string& id) const {
95  Map::const_iterator iter = extension_info_.find(id);
96  std::string result;
97  if (iter != extension_info_.end())
98    result = iter->second->default_locale();
99
100  return result;
101}
102
103ExtensionExtent ExtensionInfoMap::GetEffectiveHostPermissionsForExtension(
104    const std::string& id) const {
105  Map::const_iterator iter = extension_info_.find(id);
106  ExtensionExtent result;
107  if (iter != extension_info_.end())
108    result = iter->second->GetEffectiveHostPermissions();
109
110  return result;
111}
112
113bool ExtensionInfoMap::CheckURLAccessToExtensionPermission(
114    const GURL& url,
115    const char* permission_name) const {
116  Map::const_iterator info;
117  if (url.SchemeIs(chrome::kExtensionScheme)) {
118    // If the url is an extension scheme, we just look it up by extension id.
119    std::string id = url.host();
120    info = extension_info_.find(id);
121  } else {
122    // Otherwise, we scan for a matching extent. Overlapping extents are
123    // disallowed, so only one will match.
124    info = extension_info_.begin();
125    while (info != extension_info_.end() &&
126           !info->second->web_extent().ContainsURL(url))
127      ++info;
128  }
129
130  if (info == extension_info_.end())
131    return false;
132
133  return info->second->api_permissions().count(permission_name) != 0;
134}
135
136bool ExtensionInfoMap::URLIsForExtensionIcon(const GURL& url) const {
137  DCHECK(url.SchemeIs(chrome::kExtensionScheme));
138
139  Map::const_iterator iter = extension_info_.find(url.host());
140  if (iter == extension_info_.end()) {
141    iter = disabled_extension_info_.find(url.host());
142    if (iter == disabled_extension_info_.end())
143      return false;
144  }
145
146  std::string path = url.path();
147  DCHECK(path.length() > 0 && path[0] == '/');
148  path = path.substr(1);
149  return iter->second->icons().ContainsPath(path);
150}
151