1702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul// Copyright 2014 The Chromium Authors. All rights reserved. 2702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul// Use of this source code is governed by a BSD-style license that can be 3702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul// found in the LICENSE file. 4702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 5702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "extensions/browser/content_verifier.h" 6702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 7702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include <algorithm> 8702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 9702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "base/files/file_path.h" 10702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "base/stl_util.h" 11702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "base/strings/string_util.h" 12702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "content/public/browser/browser_thread.h" 13702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "extensions/browser/content_hash_fetcher.h" 14702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "extensions/browser/content_hash_reader.h" 15702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "extensions/browser/content_verifier_delegate.h" 16702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "extensions/browser/content_verifier_io_data.h" 17702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "extensions/browser/extension_registry.h" 18702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "extensions/common/constants.h" 19702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul#include "extensions/common/extension_l10n_util.h" 20702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 21702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paulnamespace extensions { 22702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 23702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian PaulContentVerifier::ContentVerifier(content::BrowserContext* context, 24702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul ContentVerifierDelegate* delegate) 25702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul : shutdown_(false), 26702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul context_(context), 27702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul delegate_(delegate), 28702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul fetcher_(new ContentHashFetcher( 29702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul context, 30702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul delegate, 31702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::Bind(&ContentVerifier::OnFetchComplete, this))), 32702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul observer_(this), 33702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul io_data_(new ContentVerifierIOData) { 34702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 35702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 36702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian PaulContentVerifier::~ContentVerifier() { 37702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 38702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 39702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paulvoid ContentVerifier::Start() { 40702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul ExtensionRegistry* registry = ExtensionRegistry::Get(context_); 41702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul observer_.Add(registry); 42702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 43702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 44702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paulvoid ContentVerifier::Shutdown() { 45702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul shutdown_ = true; 46702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserThread::PostTask( 47702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserThread::IO, 48702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul FROM_HERE, 49702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::Bind(&ContentVerifierIOData::Clear, io_data_)); 50702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul observer_.RemoveAll(); 51702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul fetcher_.reset(); 52702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 53702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 54702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian PaulContentVerifyJob* ContentVerifier::CreateJobFor( 55702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const std::string& extension_id, 56702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const base::FilePath& extension_root, 57702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const base::FilePath& relative_path) { 58702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 59702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 60702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const ContentVerifierIOData::ExtensionData* data = 61702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul io_data_->GetData(extension_id); 62702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (!data) 63702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return NULL; 64702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 65702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul std::set<base::FilePath> paths; 66702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul paths.insert(relative_path); 67702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (!ShouldVerifyAnyPaths(extension_id, extension_root, paths)) 68702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return NULL; 69702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 70702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // TODO(asargent) - we can probably get some good performance wins by having 71702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // a cache of ContentHashReader's that we hold onto past the end of each job. 72702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return new ContentVerifyJob( 73702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul new ContentHashReader(extension_id, 74702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul data->version, 75702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul extension_root, 76702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul relative_path, 77702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul delegate_->PublicKey()), 78702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::Bind(&ContentVerifier::VerifyFailed, this, extension_id)); 79702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 80702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 81702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paulvoid ContentVerifier::VerifyFailed(const std::string& extension_id, 82702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul ContentVerifyJob::FailureReason reason) { 83702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { 84702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserThread::PostTask( 85702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserThread::UI, 86702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul FROM_HERE, 87702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::Bind(&ContentVerifier::VerifyFailed, this, extension_id, reason)); 88702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return; 89702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul } 90702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (shutdown_) 91702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return; 92702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 93702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul VLOG(1) << "VerifyFailed " << extension_id << " reason:" << reason; 94702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 95702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul ExtensionRegistry* registry = ExtensionRegistry::Get(context_); 96702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const Extension* extension = 97702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul registry->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); 98702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 99702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (!extension) 100702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return; 101702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 102702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (reason == ContentVerifyJob::MISSING_ALL_HASHES) { 103702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // If we failed because there were no hashes yet for this extension, just 104702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // request some. 105702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul fetcher_->DoFetch(extension, true /* force */); 106702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul } else { 107702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul delegate_->VerifyFailed(extension_id, reason); 108702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul } 109702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 110702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 111702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paulstatic base::FilePath MakeImagePathRelative(const base::FilePath& path) { 112702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (path.ReferencesParent()) 113702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return base::FilePath(); 114702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 115702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul std::vector<base::FilePath::StringType> parts; 116702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul path.GetComponents(&parts); 117702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (parts.empty()) 118702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return base::FilePath(); 119702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 120702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // Remove the first component if it is '.' or '/' or '//'. 121702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const base::FilePath::StringType separators( 122702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::FilePath::kSeparators, base::FilePath::kSeparatorsLength); 123702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (!parts[0].empty() && 124702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul (parts[0] == base::FilePath::kCurrentDirectory || 125702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul parts[0].find_first_not_of(separators) == std::string::npos)) 126702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul parts.erase(parts.begin()); 127702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 128702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // Note that elsewhere we always normalize path separators to '/' so this 129702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // should work for all platforms. 130702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return base::FilePath(JoinString(parts, '/')); 131702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 132702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 133702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paulvoid ContentVerifier::OnExtensionLoaded( 134702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserContext* browser_context, 135702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const Extension* extension) { 136702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (shutdown_) 137702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return; 138702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 139702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension); 140702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (mode != ContentVerifierDelegate::NONE) { 141702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // The browser image paths from the extension may not be relative (eg 142702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // they might have leading '/' or './'), so we strip those to make 143702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // comparing to actual relative paths work later on. 144702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul std::set<base::FilePath> original_image_paths = 145702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul delegate_->GetBrowserImagePaths(extension); 146702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 147702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul scoped_ptr<std::set<base::FilePath>> image_paths( 148702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul new std::set<base::FilePath>); 149702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul for (const auto& path : original_image_paths) { 150702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul image_paths->insert(MakeImagePathRelative(path)); 151702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul } 152702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 153702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul scoped_ptr<ContentVerifierIOData::ExtensionData> data( 154702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul new ContentVerifierIOData::ExtensionData( 155702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul image_paths.Pass(), 156702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul extension->version() ? *extension->version() : base::Version())); 157702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserThread::PostTask(content::BrowserThread::IO, 158702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul FROM_HERE, 159702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::Bind(&ContentVerifierIOData::AddData, 160702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul io_data_, 161702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul extension->id(), 162702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::Passed(&data))); 163702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul fetcher_->ExtensionLoaded(extension); 164702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul } 165702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 166702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 167702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paulvoid ContentVerifier::OnExtensionUnloaded( 168702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserContext* browser_context, 169702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const Extension* extension, 170702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul UnloadedExtensionInfo::Reason reason) { 171702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (shutdown_) 172702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return; 173702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserThread::PostTask( 174702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserThread::IO, 175702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul FROM_HERE, 176702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::Bind( 177702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul &ContentVerifierIOData::RemoveData, io_data_, extension->id())); 178702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (fetcher_) 179702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul fetcher_->ExtensionUnloaded(extension); 180702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 181702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 182702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paulvoid ContentVerifier::OnFetchCompleteHelper(const std::string& extension_id, 183702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul bool shouldVerifyAnyPathsResult) { 184702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (shouldVerifyAnyPathsResult) 185702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul delegate_->VerifyFailed(extension_id, ContentVerifyJob::MISSING_ALL_HASHES); 186702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 187702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 188702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paulvoid ContentVerifier::OnFetchComplete( 189702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const std::string& extension_id, 190702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul bool success, 191702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul bool was_force_check, 192702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const std::set<base::FilePath>& hash_mismatch_paths) { 193702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (shutdown_) 194702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return; 195702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 196702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul VLOG(1) << "OnFetchComplete " << extension_id << " success:" << success; 197702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 198702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul ExtensionRegistry* registry = ExtensionRegistry::Get(context_); 199702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const Extension* extension = 200702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul registry->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); 201702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (!delegate_ || !extension) 202702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return; 203702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 204702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension); 205702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (was_force_check && !success && 206702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul mode == ContentVerifierDelegate::ENFORCE_STRICT) { 207702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // We weren't able to get verified_contents.json or weren't able to compute 208702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // hashes. 209702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul delegate_->VerifyFailed(extension_id, ContentVerifyJob::MISSING_ALL_HASHES); 210702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul } else { 211702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserThread::PostTaskAndReplyWithResult( 212702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul content::BrowserThread::IO, 213702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul FROM_HERE, 214702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::Bind(&ContentVerifier::ShouldVerifyAnyPaths, 215702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul this, 216702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul extension_id, 217702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul extension->path(), 218702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul hash_mismatch_paths), 219702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::Bind( 220702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul &ContentVerifier::OnFetchCompleteHelper, this, extension_id)); 221702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul } 222702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 223702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 224702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paulbool ContentVerifier::ShouldVerifyAnyPaths( 225702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const std::string& extension_id, 226702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const base::FilePath& extension_root, 227702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const std::set<base::FilePath>& relative_paths) { 228702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 229702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const ContentVerifierIOData::ExtensionData* data = 230702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul io_data_->GetData(extension_id); 231702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (!data) 232702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return false; 233702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 234702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const std::set<base::FilePath>& browser_images = *(data->browser_image_paths); 235702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 236702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::FilePath locales_dir = extension_root.Append(kLocaleFolder); 237702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul scoped_ptr<std::set<std::string> > all_locales; 238702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 239702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul for (std::set<base::FilePath>::const_iterator i = relative_paths.begin(); 240702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul i != relative_paths.end(); 241702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul ++i) { 242702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul const base::FilePath& relative_path = *i; 243702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 244702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (relative_path == base::FilePath(kManifestFilename)) 245702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul continue; 246702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 247702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (ContainsKey(browser_images, relative_path)) 248702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul continue; 249702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 250702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul base::FilePath full_path = extension_root.Append(relative_path); 251702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (locales_dir.IsParent(full_path)) { 252702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (!all_locales) { 253702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // TODO(asargent) - see if we can cache this list longer to avoid 254702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // having to fetch it more than once for a given run of the 255702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // browser. Maybe it can never change at runtime? (Or if it can, maybe 256702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // there is an event we can listen for to know to drop our cache). 257702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul all_locales.reset(new std::set<std::string>); 258702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul extension_l10n_util::GetAllLocales(all_locales.get()); 259702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul } 260702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 261702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // Since message catalogs get transcoded during installation, we want 262702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul // to skip those paths. 263702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul if (full_path.DirName().DirName() == locales_dir && 264702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul !extension_l10n_util::ShouldSkipValidation( 265702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul locales_dir, full_path.DirName(), *all_locales)) 266702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul continue; 267702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul } 268702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return true; 269702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul } 270702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul return false; 271702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} 272702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul 273702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul} // namespace extensions 274702b5b076b7591560e7e701e0c9ff2eeb30fa966Brian Paul