1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Use of this source code is governed by a BSD-style license that can be
3731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// found in the LICENSE file.
4731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_info_map.h"
6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/common/extensions/extension.h"
8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/url_constants.h"
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
11731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace {
12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstatic void CheckOnValidThread() {
14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
16731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace
18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
19731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionInfoMap::ExtensionInfoMap() {
20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
22731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionInfoMap::~ExtensionInfoMap() {
23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
25513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ExtensionInfoMap::AddExtension(const Extension* extension) {
26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  CheckOnValidThread();
27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  extension_info_[extension->id()] = extension;
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Map::iterator iter = disabled_extension_info_.find(extension->id());
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (iter != disabled_extension_info_.end())
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    disabled_extension_info_.erase(iter);
31731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionInfoMap::RemoveExtension(const std::string& id,
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const UnloadedExtensionInfo::Reason reason) {
35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  CheckOnValidThread();
36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Map::iterator iter = extension_info_.find(id);
37731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (iter != extension_info_.end()) {
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (reason == UnloadedExtensionInfo::DISABLE)
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      disabled_extension_info_[id] = (*iter).second;
40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    extension_info_.erase(iter);
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (reason != UnloadedExtensionInfo::DISABLE) {
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If the extension was uninstalled, make sure it's removed from the map of
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // disabled extensions.
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    disabled_extension_info_.erase(id);
45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  } else {
46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // NOTE: This can currently happen if we receive multiple unload
47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // notifications, e.g. setting incognito-enabled state for a
48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // disabled extension (e.g., via sync).  See
49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // http://code.google.com/p/chromium/issues/detail?id=50582 .
50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    NOTREACHED() << id;
51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::string ExtensionInfoMap::GetNameForExtension(const std::string& id) const {
56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Map::const_iterator iter = extension_info_.find(id);
57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (iter != extension_info_.end())
58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return iter->second->name();
59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  else
60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return std::string();
61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
62731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
63731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickFilePath ExtensionInfoMap::GetPathForExtension(const std::string& id) const {
64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Map::const_iterator iter = extension_info_.find(id);
65731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (iter != extension_info_.end())
66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return iter->second->path();
67731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  else
68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return FilePath();
69731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFilePath ExtensionInfoMap::GetPathForDisabledExtension(
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& id) const {
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Map::const_iterator iter = disabled_extension_info_.find(id);
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (iter != disabled_extension_info_.end())
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return iter->second->path();
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  else
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return FilePath();
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ExtensionInfoMap::ExtensionHasWebExtent(const std::string& id) const {
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Map::const_iterator iter = extension_info_.find(id);
82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return iter != extension_info_.end() &&
83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      !iter->second->web_extent().is_empty();
84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ExtensionInfoMap::ExtensionCanLoadInIncognito(
87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& id) const {
88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Map::const_iterator iter = extension_info_.find(id);
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Only split-mode extensions can load in incognito profiles.
90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return iter != extension_info_.end() && iter->second->incognito_split_mode();
91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::string ExtensionInfoMap::GetDefaultLocaleForExtension(
94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& id) const {
95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Map::const_iterator iter = extension_info_.find(id);
96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::string result;
97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (iter != extension_info_.end())
98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    result = iter->second->default_locale();
99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return result;
101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
103731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionExtent ExtensionInfoMap::GetEffectiveHostPermissionsForExtension(
104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& id) const {
105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Map::const_iterator iter = extension_info_.find(id);
106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ExtensionExtent result;
107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (iter != extension_info_.end())
108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    result = iter->second->GetEffectiveHostPermissions();
109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return result;
111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ExtensionInfoMap::CheckURLAccessToExtensionPermission(
114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const GURL& url,
115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const char* permission_name) const {
116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Map::const_iterator info;
117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (url.SchemeIs(chrome::kExtensionScheme)) {
118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // If the url is an extension scheme, we just look it up by extension id.
119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::string id = url.host();
120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    info = extension_info_.find(id);
121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  } else {
122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Otherwise, we scan for a matching extent. Overlapping extents are
123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // disallowed, so only one will match.
124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    info = extension_info_.begin();
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    while (info != extension_info_.end() &&
126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch           !info->second->web_extent().ContainsURL(url))
127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      ++info;
128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (info == extension_info_.end())
131731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return false;
132731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return info->second->api_permissions().count(permission_name) != 0;
134731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
135731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
136731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ExtensionInfoMap::URLIsForExtensionIcon(const GURL& url) const {
137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(url.SchemeIs(chrome::kExtensionScheme));
138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Map::const_iterator iter = extension_info_.find(url.host());
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (iter == extension_info_.end()) {
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    iter = disabled_extension_info_.find(url.host());
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (iter == disabled_extension_info_.end())
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::string path = url.path();
147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(path.length() > 0 && path[0] == '/');
148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  path = path.substr(1);
149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return iter->second->icons().ContainsPath(path);
150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
151