extension_util.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/extension_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/scoped_ptr.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util-inl.h"
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/version.h"
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/extensions/extension_prefs.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extensions_service.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/protocol/extension_specifics.pb.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace browser_sync {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionType GetExtensionType(const Extension& extension) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension.is_theme()) {
24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return THEME;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension.is_app()) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return APP;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension.converted_from_user_script()) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension.update_url().is_empty()) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return LOCAL_USER_SCRIPT;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UPDATEABLE_USER_SCRIPT;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Otherwise, we just have a regular extension.
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return EXTENSION;
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Keep this in sync with the above function.
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// TODO(akalin): Or just hurry up and remove this!
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochExtensionType GetExtensionTypeFromUninstalledExtensionInfo(
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UninstalledExtensionInfo& uninstalled_extension_info) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (uninstalled_extension_info.is_theme) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return THEME;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (uninstalled_extension_info.is_app) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return APP;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (uninstalled_extension_info.converted_from_user_script) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (uninstalled_extension_info.update_url.is_empty()) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return LOCAL_USER_SCRIPT;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UPDATEABLE_USER_SCRIPT;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return EXTENSION;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsExtensionValid(const Extension& extension) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(akalin): Figure out if we need to allow some other types.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension.location() != Extension::INTERNAL) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have a non-standard location.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disallow extensions with non-gallery auto-update URLs for now.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(akalin): Relax this restriction once we've put in UI to
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // approve synced extensions.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension.update_url().is_empty() &&
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (extension.update_url() !=
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       GURL(extension_urls::kGalleryUpdateHttpUrl)) &&
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (extension.update_url() !=
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       GURL(extension_urls::kGalleryUpdateHttpsUrl))) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disallow extensions with native code plugins.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(akalin): Relax this restriction once we've put in UI to
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // approve synced extensions.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension.plugins().empty()) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsExtensionValidAndSyncable(const Extension& extension,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const ExtensionTypeSet& allowed_types) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IsExtensionValid(extension) &&
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContainsKey(allowed_types, GetExtensionType(extension));
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ExtensionSpecificsToString(
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sync_pb::ExtensionSpecifics& specifics) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::stringstream ss;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ss << "{ ";
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ss << "id: "                   << specifics.id()                << ", ";
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ss << "version: "              << specifics.version()           << ", ";
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ss << "update_url: "           << specifics.update_url()        << ", ";
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ss << "enabled: "              << specifics.enabled()           << ", ";
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ss << "incognito_enabled: "    << specifics.incognito_enabled() << ", ";
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ss << "name: "                 << specifics.name();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ss << " }";
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ss.str();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsExtensionSpecificsValid(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sync_pb::ExtensionSpecifics& specifics) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Extension::IdIsValid(specifics.id())) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Version> version(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Version::GetVersionFromString(specifics.version()));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!version.get()) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The update URL must be either empty or valid.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL update_url(specifics.update_url());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!update_url.is_empty() && !update_url.is_valid()) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DcheckIsExtensionSpecificsValid(
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sync_pb::ExtensionSpecifics& specifics) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsExtensionSpecificsValid(specifics))
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << ExtensionSpecificsToString(specifics);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AreExtensionSpecificsEqual(const sync_pb::ExtensionSpecifics& a,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const sync_pb::ExtensionSpecifics& b) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(akalin): Figure out if we have to worry about version/URL
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // strings that are not identical but map to the same object.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ((a.id() == b.id()) &&
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (a.version() == b.version()) &&
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          (a.update_url() == b.update_url()) &&
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (a.enabled() == b.enabled()) &&
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (a.incognito_enabled() == b.incognito_enabled()) &&
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (a.name() == b.name()));
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsExtensionSpecificsUnset(
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sync_pb::ExtensionSpecifics& specifics) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AreExtensionSpecificsEqual(specifics,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    sync_pb::ExtensionSpecifics());
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyUserProperties(
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sync_pb::ExtensionSpecifics& specifics,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sync_pb::ExtensionSpecifics* dest_specifics) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(dest_specifics);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dest_specifics->set_enabled(specifics.enabled());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dest_specifics->set_incognito_enabled(specifics.incognito_enabled());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CopyNonUserProperties(
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const sync_pb::ExtensionSpecifics& specifics,
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::ExtensionSpecifics* dest_specifics) {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(dest_specifics);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sync_pb::ExtensionSpecifics old_dest_specifics(*dest_specifics);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *dest_specifics = specifics;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CopyUserProperties(old_dest_specifics, dest_specifics);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AreExtensionSpecificsUserPropertiesEqual(
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const sync_pb::ExtensionSpecifics& a,
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const sync_pb::ExtensionSpecifics& b) {
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  sync_pb::ExtensionSpecifics a_user_properties, b_user_properties;
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CopyUserProperties(a, &a_user_properties);
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CopyUserProperties(b, &b_user_properties);
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return AreExtensionSpecificsEqual(a_user_properties, b_user_properties);
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool AreExtensionSpecificsNonUserPropertiesEqual(
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const sync_pb::ExtensionSpecifics& a,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sync_pb::ExtensionSpecifics& b) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_pb::ExtensionSpecifics a_non_user_properties, b_non_user_properties;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CopyNonUserProperties(a, &a_non_user_properties);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CopyNonUserProperties(b, &b_non_user_properties);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AreExtensionSpecificsEqual(
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      a_non_user_properties, b_non_user_properties);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetExtensionSpecifics(const Extension& extension,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ExtensionPrefs* extension_prefs,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           sync_pb::ExtensionSpecifics* specifics) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& id = extension.id();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enabled =
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_prefs->GetExtensionState(id) == Extension::ENABLED;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool incognito_enabled = extension_prefs->IsIncognitoEnabled(id);
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetExtensionSpecificsHelper(extension, enabled, incognito_enabled,
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              specifics);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetExtensionSpecificsHelper(const Extension& extension,
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 bool enabled, bool incognito_enabled,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 sync_pb::ExtensionSpecifics* specifics) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsExtensionValid(extension));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& id = extension.id();
211  specifics->set_id(id);
212  specifics->set_version(extension.VersionString());
213  specifics->set_update_url(extension.update_url().spec());
214  specifics->set_enabled(enabled);
215  specifics->set_incognito_enabled(incognito_enabled);
216  specifics->set_name(extension.name());
217  DcheckIsExtensionSpecificsValid(*specifics);
218}
219
220bool IsExtensionOutdated(const Extension& extension,
221                         const sync_pb::ExtensionSpecifics& specifics) {
222  DCHECK(IsExtensionValid(extension));
223  DcheckIsExtensionSpecificsValid(specifics);
224  scoped_ptr<Version> specifics_version(
225      Version::GetVersionFromString(specifics.version()));
226  if (!specifics_version.get()) {
227    // If version is invalid, assume we're up-to-date.
228    return false;
229  }
230  return extension.version()->CompareTo(*specifics_version) < 0;
231}
232
233void SetExtensionProperties(
234    const sync_pb::ExtensionSpecifics& specifics,
235    ExtensionsService* extensions_service, Extension* extension) {
236  DcheckIsExtensionSpecificsValid(specifics);
237  CHECK(extensions_service);
238  CHECK(extension);
239  DCHECK(IsExtensionValid(*extension));
240  const std::string& id = extension->id();
241  GURL update_url(specifics.update_url());
242  if (update_url != extension->update_url()) {
243    LOG(WARNING) << "specifics for extension " << id
244                 << "has a different update URL than the extension: "
245                 << update_url.spec() << " vs. " << extension->update_url();
246  }
247  ExtensionPrefs* extension_prefs = extensions_service->extension_prefs();
248  bool enabled = extension_prefs->GetExtensionState(id) == Extension::ENABLED;
249  if (enabled && !specifics.enabled()) {
250    extensions_service->DisableExtension(id);
251  } else if (!enabled && specifics.enabled()) {
252    extensions_service->EnableExtension(id);
253  }
254  bool incognito_enabled = extension_prefs->IsIncognitoEnabled(id);
255  if (incognito_enabled != specifics.incognito_enabled()) {
256    extensions_service->SetIsIncognitoEnabled(
257        extension, specifics.incognito_enabled());
258  }
259  if (specifics.name() != extension->name()) {
260    LOG(WARNING) << "specifics for extension " << id
261                 << "has a different name than the extension: "
262                 << specifics.name() << " vs. " << extension->name();
263  }
264}
265
266void MergeExtensionSpecifics(
267    const sync_pb::ExtensionSpecifics& specifics,
268    bool merge_user_properties,
269    sync_pb::ExtensionSpecifics* merged_specifics) {
270  DcheckIsExtensionSpecificsValid(*merged_specifics);
271  DcheckIsExtensionSpecificsValid(specifics);
272  DCHECK_EQ(specifics.id(), merged_specifics->id());
273  // TODO(akalin): Merge enabled permissions when we sync those.
274  scoped_ptr<Version> version(
275      Version::GetVersionFromString(specifics.version()));
276  CHECK(version.get());
277  scoped_ptr<Version> merged_version(
278      Version::GetVersionFromString(merged_specifics->version()));
279  CHECK(merged_version.get());
280  if (version->CompareTo(*merged_version) >= 0) {
281    // |specifics| has a more recent or the same version, so merge it
282    // in.
283    CopyNonUserProperties(specifics, merged_specifics);
284    if (merge_user_properties) {
285      CopyUserProperties(specifics, merged_specifics);
286    }
287  }
288}
289
290}  // namespace browser_sync
291