chrome_permission_message_provider.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/common/extensions/permissions/chrome_permission_message_provider.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/stringprintf.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "extensions/common/extensions_client.h"
109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "extensions/common/permissions/permission_message.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "extensions/common/permissions/permission_message_util.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/permissions/permission_set.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "extensions/common/url_pattern.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "extensions/common/url_pattern_set.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ui/base/l10n/l10n_util.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "url/gurl.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace {
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)typedef std::set<PermissionMessage> PermissionMsgSet;
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ShouldWarnAllHosts(const PermissionSet* permissions) {
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (permissions->HasEffectiveAccessToAllHosts())
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return true;
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const URLPatternSet& effective_hosts = permissions->effective_hosts();
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (URLPatternSet::const_iterator iter = effective_hosts.begin();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != effective_hosts.end();
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++iter) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If this doesn't even match subdomains, it can't possibly imply all hosts.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!iter->match_subdomains())
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If iter->host() is a recognized TLD, this will be 0. We don't include
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // private TLDs, so that, e.g., *.appspot.com does not imply all hosts.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t registry_length =
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::registry_controlled_domains::GetRegistryLength(
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            iter->host(),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there was more than just a TLD in the host (e.g., *.foobar.com), it
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // doesn't imply all hosts.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (registry_length > 0)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // At this point the host could either be just a TLD ("com") or some unknown
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // TLD-like string ("notatld"). To disambiguate between them construct a
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // fake URL, and check the registry. This returns 0 if the TLD is
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // unrecognized, or the length of the recognized TLD.
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    registry_length = net::registry_controlled_domains::GetRegistryLength(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringPrintf("foo.%s", iter->host().c_str()),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we recognized this TLD, then this is a pattern like *.com, and it
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // should imply all hosts.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (registry_length > 0)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T>
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typename T::iterator FindMessageByID(T& messages, int id) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (typename T::iterator it = messages.begin();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != messages.end(); ++it) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->id() == id)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return it;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return messages.end();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T>
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SuppressMessage(T& messages,
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     int suppressing_message,
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     int suppressed_message) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typename T::iterator suppressed = FindMessageByID(messages,
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                    suppressed_message);
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (suppressed != messages.end() &&
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FindMessageByID(messages, suppressing_message) != messages.end()) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    messages.erase(suppressed);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromePermissionMessageProvider::ChromePermissionMessageProvider() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromePermissionMessageProvider::~ChromePermissionMessageProvider() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PermissionMessages ChromePermissionMessageProvider::GetPermissionMessages(
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PermissionSet* permissions,
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Manifest::Type extension_type) const {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PermissionMessages messages;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (permissions->HasEffectiveFullAccess()) {
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    messages.push_back(PermissionMessage(
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PermissionMessage::kFullAccess,
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS)));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return messages;
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionMsgSet host_msgs =
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetHostPermissionMessages(permissions, extension_type);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionMsgSet api_msgs = GetAPIPermissionMessages(permissions);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionMsgSet manifest_permission_msgs =
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetManifestPermissionMessages(permissions);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  messages.insert(messages.end(), host_msgs.begin(), host_msgs.end());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  messages.insert(messages.end(), api_msgs.begin(), api_msgs.end());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  messages.insert(messages.end(), manifest_permission_msgs.begin(),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  manifest_permission_msgs.end());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some warnings are more generic and/or powerful and superseed other
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // warnings. In that case, suppress the superseeded warning.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SuppressMessage(messages,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PermissionMessage::kBookmarks,
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  PermissionMessage::kOverrideBookmarksUI);
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Both tabs and history already allow reading favicons.
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SuppressMessage(messages,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PermissionMessage::kTabs,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PermissionMessage::kFavicon);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SuppressMessage(messages,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PermissionMessage::kBrowsingHistory,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PermissionMessage::kFavicon);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Warning for history permission already covers warning for tabs permission.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SuppressMessage(messages,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PermissionMessage::kBrowsingHistory,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PermissionMessage::kTabs);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return messages;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
138c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochstd::vector<base::string16> ChromePermissionMessageProvider::GetWarningMessages(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PermissionSet* permissions,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Manifest::Type extension_type) const {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::string16> message_strings;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionMessages messages =
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetPermissionMessages(permissions, extension_type);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool audio_capture = false;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool video_capture = false;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool media_galleries_read = false;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool media_galleries_copy_to = false;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool media_galleries_delete = false;
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (PermissionMessages::const_iterator i = messages.begin();
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       i != messages.end(); ++i) {
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    switch (i->id()) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PermissionMessage::kAudioCapture:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        audio_capture = true;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PermissionMessage::kVideoCapture:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        video_capture = true;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PermissionMessage::kMediaGalleriesAllGalleriesRead:
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        media_galleries_read = true;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PermissionMessage::kMediaGalleriesAllGalleriesCopyTo:
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        media_galleries_copy_to = true;
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case PermissionMessage::kMediaGalleriesAllGalleriesDelete:
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        media_galleries_delete = true;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PermissionMessages::const_iterator i = messages.begin();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != messages.end(); ++i) {
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int id = i->id();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (audio_capture && video_capture) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (id == PermissionMessage::kAudioCapture) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_strings.push_back(l10n_util::GetStringUTF16(
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            IDS_EXTENSION_PROMPT_WARNING_AUDIO_AND_VIDEO_CAPTURE));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (id == PermissionMessage::kVideoCapture) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The combined message will be pushed above.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (media_galleries_read &&
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (media_galleries_copy_to || media_galleries_delete)) {
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (id == PermissionMessage::kMediaGalleriesAllGalleriesRead) {
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        int m_id = media_galleries_copy_to ?
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            IDS_EXTENSION_PROMPT_WARNING_MEDIA_GALLERIES_READ_WRITE :
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            IDS_EXTENSION_PROMPT_WARNING_MEDIA_GALLERIES_READ_DELETE;
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        message_strings.push_back(l10n_util::GetStringUTF16(m_id));
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        continue;
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      } else if (id == PermissionMessage::kMediaGalleriesAllGalleriesCopyTo ||
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 id == PermissionMessage::kMediaGalleriesAllGalleriesDelete) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The combined message will be pushed above.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_strings.push_back(i->message());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return message_strings;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::vector<base::string16>
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ChromePermissionMessageProvider::GetWarningMessagesDetails(
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const PermissionSet* permissions,
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Manifest::Type extension_type) const {
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<base::string16> message_strings;
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PermissionMessages messages =
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetPermissionMessages(permissions, extension_type);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PermissionMessages::const_iterator i = messages.begin();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != messages.end(); ++i)
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    message_strings.push_back(i->details());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return message_strings;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool ChromePermissionMessageProvider::IsPrivilegeIncrease(
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PermissionSet* old_permissions,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PermissionSet* new_permissions,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Manifest::Type extension_type) const {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Things can't get worse than native code access.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_permissions->HasEffectiveFullAccess())
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Otherwise, it's a privilege increase if the new one has full access.
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (new_permissions->HasEffectiveFullAccess())
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return true;
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsHostPrivilegeIncrease(old_permissions, new_permissions, extension_type))
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (IsAPIPrivilegeIncrease(old_permissions, new_permissions))
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsManifestPermissionPrivilegeIncrease(old_permissions, new_permissions))
2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::set<PermissionMessage>
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromePermissionMessageProvider::GetAPIPermissionMessages(
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PermissionSet* permissions) const {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionMsgSet messages;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (APIPermissionSet::const_iterator permission_it =
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           permissions->apis().begin();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       permission_it != permissions->apis().end(); ++permission_it) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (permission_it->HasMessages()) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PermissionMessages new_messages = permission_it->GetMessages();
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      messages.insert(new_messages.begin(), new_messages.end());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A special hack: If kFileSystemWriteDirectory would be displayed, hide
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kFileSystemDirectory as the write directory message implies it.
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(sammc): Remove this. See http://crbug.com/284849.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SuppressMessage(messages,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PermissionMessage::kFileSystemWriteDirectory,
264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                  PermissionMessage::kFileSystemDirectory);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A special hack: The warning message for declarativeWebRequest
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // permissions speaks about blocking parts of pages, which is a
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // subset of what the "<all_urls>" access allows. Therefore we
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // display only the "<all_urls>" warning message if both permissions
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // are required.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldWarnAllHosts(permissions)) {
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    messages.erase(
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PermissionMessage(
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PermissionMessage::kDeclarativeWebRequest, base::string16()));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return messages;
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::set<PermissionMessage>
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ChromePermissionMessageProvider::GetManifestPermissionMessages(
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PermissionSet* permissions) const {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionMsgSet messages;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ManifestPermissionSet::const_iterator permission_it =
283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           permissions->manifest_permissions().begin();
284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      permission_it != permissions->manifest_permissions().end();
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++permission_it) {
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (permission_it->HasMessages()) {
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PermissionMessages new_messages = permission_it->GetMessages();
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      messages.insert(new_messages.begin(), new_messages.end());
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return messages;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::set<PermissionMessage>
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromePermissionMessageProvider::GetHostPermissionMessages(
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PermissionSet* permissions,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Manifest::Type extension_type) const {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionMsgSet messages;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since platform apps always use isolated storage, they can't (silently)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // access user data on other domains, so there's no need to prompt.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: this must remain consistent with IsHostPrivilegeIncrease.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See crbug.com/255229.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension_type == Manifest::TYPE_PLATFORM_APP)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return messages;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldWarnAllHosts(permissions)) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    messages.insert(PermissionMessage(
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PermissionMessage::kHostsAll,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS)));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    URLPatternSet regular_hosts;
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ExtensionsClient::Get()->FilterHostPermissions(
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        permissions->effective_hosts(), &regular_hosts, &messages);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<std::string> hosts =
3165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        permission_message_util::GetDistinctHosts(regular_hosts, true, true);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!hosts.empty())
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      messages.insert(permission_message_util::CreateFromHostList(hosts));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return messages;
321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool ChromePermissionMessageProvider::IsAPIPrivilegeIncrease(
324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const PermissionSet* old_permissions,
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const PermissionSet* new_permissions) const {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_permissions == NULL)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionMsgSet old_warnings = GetAPIPermissionMessages(old_permissions);
330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PermissionMsgSet new_warnings = GetAPIPermissionMessages(new_permissions);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PermissionMsgSet delta_warnings =
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::STLSetDifference<PermissionMsgSet>(new_warnings, old_warnings);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A special hack: kFileSystemWriteDirectory implies kFileSystemDirectory.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sammc): Remove this. See http://crbug.com/284849.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_warnings.find(PermissionMessage(
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PermissionMessage::kFileSystemWriteDirectory, base::string16())) !=
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      old_warnings.end()) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delta_warnings.erase(
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PermissionMessage(PermissionMessage::kFileSystemDirectory,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::string16()));
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // It is a privilege increase if there are additional warnings present.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !delta_warnings.empty();
346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChromePermissionMessageProvider::IsManifestPermissionPrivilegeIncrease(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PermissionSet* old_permissions,
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const PermissionSet* new_permissions) const {
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (new_permissions == NULL)
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PermissionMsgSet old_warnings =
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetManifestPermissionMessages(old_permissions);
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PermissionMsgSet new_warnings =
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetManifestPermissionMessages(new_permissions);
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PermissionMsgSet delta_warnings =
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::STLSetDifference<PermissionMsgSet>(new_warnings, old_warnings);
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // It is a privilege increase if there are additional warnings present.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !delta_warnings.empty();
363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChromePermissionMessageProvider::IsHostPrivilegeIncrease(
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PermissionSet* old_permissions,
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PermissionSet* new_permissions,
368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Manifest::Type extension_type) const {
369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Platform apps host permission changes do not count as privilege increases.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: this must remain consistent with GetHostPermissionMessages.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension_type == Manifest::TYPE_PLATFORM_APP)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the old permission set can access any host, then it can't be elevated.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_permissions->HasEffectiveAccessToAllHosts())
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Likewise, if the new permission set has full host access, then it must be
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a privilege increase.
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_permissions->HasEffectiveAccessToAllHosts())
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
382c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
383c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  const URLPatternSet& old_list = old_permissions->effective_hosts();
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const URLPatternSet& new_list = new_permissions->effective_hosts();
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jstritar): This is overly conservative with respect to subdomains.
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For example, going from *.google.com to www.google.com will be
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // considered an elevation, even though it is not (http://crbug.com/65337).
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> new_hosts_set(
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      permission_message_util::GetDistinctHosts(new_list, false, false));
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> old_hosts_set(
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      permission_message_util::GetDistinctHosts(old_list, false, false));
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::set<std::string> new_hosts_only =
3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::STLSetDifference<std::set<std::string> >(new_hosts_set,
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                     old_hosts_set);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !new_hosts_only.empty();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace extensions
4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)