1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Copyright 2014 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) 5a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/browser/extension_protocols.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include <string> 9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/base64.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/format_macros.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/metrics/field_trial.h" 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/metrics/histogram.h" 210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/metrics/sparse_histogram.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/sha1.h" 2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/timer/elapsed_timer.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/resource_request_info.h" 34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "crypto/secure_hash.h" 35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "crypto/sha2.h" 36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/browser/content_verifier.h" 37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/browser/content_verify_job.h" 38a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/browser/extensions_browser_client.h" 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/info_map.h" 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/url_request_util.h" 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h" 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/extension_resource.h" 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/file_util.h" 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/background_info.h" 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/csp_info.h" 47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.h" 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/incognito_info.h" 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/shared_module_info.h" 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/manifest_handlers/web_accessible_resources_info.h" 51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "net/base/io_buffer.h" 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "net/http/http_request_headers.h" 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h" 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_info.h" 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_error_job.h" 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_file_job.h" 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_simple_job.h" 597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/url_util.h" 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using content::BrowserThread; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::ResourceRequestInfo; 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing content::ResourceType; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using extensions::SharedModuleInfo; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 67a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace extensions { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GeneratedBackgroundPageJob : public net::URLRequestSimpleJob { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GeneratedBackgroundPageJob(net::URLRequest* request, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::NetworkDelegate* network_delegate, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<const Extension> extension, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& content_security_policy) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : net::URLRequestSimpleJob(request, network_delegate), 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_(extension) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool send_cors_headers = false; 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Leave cache headers out of generated background page jobs. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_info_.headers = BuildHttpHeaders(content_security_policy, 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) send_cors_headers, 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Time()); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Overridden from URLRequestSimpleJob: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int GetData(std::string* mime_type, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* charset, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* data, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::CompletionCallback& callback) const OVERRIDE { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *mime_type = "text/html"; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *charset = "utf-8"; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *data = "<!DOCTYPE html>\n<body>\n"; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<std::string>& background_scripts = 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extensions::BackgroundInfo::GetBackgroundScripts(extension_.get()); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < background_scripts.size(); ++i) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *data += "<script src=\""; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *data += background_scripts[i]; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *data += "\"></script>\n"; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net::OK; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *info = response_info_; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GeneratedBackgroundPageJob() {} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<const Extension> extension_; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::HttpResponseInfo response_info_; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)base::Time GetFileLastModifiedTime(const base::FilePath& filename) { 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (base::PathExists(filename)) { 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::File::Info info; 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (base::GetFileInfo(filename, &info)) 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return info.last_modified; 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return base::Time(); 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)base::Time GetFileCreationTime(const base::FilePath& filename) { 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (base::PathExists(filename)) { 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::File::Info info; 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (base::GetFileInfo(filename, &info)) 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return info.creation_time; 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return base::Time(); 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ReadResourceFilePathAndLastModifiedTime( 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const extensions::ExtensionResource& resource, 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::FilePath& directory, 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FilePath* file_path, 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Time* last_modified_time) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *file_path = resource.GetFilePath(); 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *last_modified_time = GetFileLastModifiedTime(*file_path); 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // While we're here, log the delta between extension directory 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // creation time and the resource's last modification time. 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::ElapsedTimer query_timer; 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Time dir_creation_time = GetFileCreationTime(directory); 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UMA_HISTOGRAM_TIMES("Extensions.ResourceDirectoryTimestampQueryLatency", 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) query_timer.Elapsed()); 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64 delta_seconds = (*last_modified_time - dir_creation_time).InSeconds(); 148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (delta_seconds >= 0) { 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.ResourceLastModifiedDelta", 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) delta_seconds, 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 0, 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::TimeDelta::FromDays(30).InSeconds(), 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 50); 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.ResourceLastModifiedNegativeDelta", 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) -delta_seconds, 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1, 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::TimeDelta::FromDays(30).InSeconds(), 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 50); 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class URLRequestExtensionJob : public net::URLRequestFileJob { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequestExtensionJob(net::URLRequest* request, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::NetworkDelegate* network_delegate, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& directory_path, 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& relative_path, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& content_security_policy, 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool send_cors_header, 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool follow_symlinks_anywhere, 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ContentVerifyJob* verify_job) 174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : net::URLRequestFileJob( 175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch request, 176a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch network_delegate, 177a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::FilePath(), 178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( 179a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), 180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) verify_job_(verify_job), 181a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch seek_position_(0), 182a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bytes_read_(0), 183a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch directory_path_(directory_path), 184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // TODO(tc): Move all of these files into resources.pak so we don't 185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // break when updating on Linux. 186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch resource_(extension_id, directory_path, relative_path), 187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch content_security_policy_(content_security_policy), 188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch send_cors_header_(send_cors_header), 189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch weak_factory_(this) { 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (follow_symlinks_anywhere) { 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) resource_.set_follow_symlinks_anywhere(); 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *info = response_info_; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Start() OVERRIDE { 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch request_timer_.reset(new base::ElapsedTimer()); 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath* read_file_path = new base::FilePath; 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Time* last_modified_time = new base::Time(); 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool posted = BrowserThread::PostBlockingPoolTaskAndReply( 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 205a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::Bind(&ReadResourceFilePathAndLastModifiedTime, 206a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch resource_, 207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) directory_path_, 208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Unretained(read_file_path), 209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Unretained(last_modified_time)), 210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&URLRequestExtensionJob::OnFilePathAndLastModifiedTimeRead, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.GetWeakPtr(), 212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Owned(read_file_path), 2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Owned(last_modified_time))); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(posted); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175b892326406927b709cdaf6c384d4ababf456332Ben Murdoch virtual bool IsRedirectResponse(GURL* location, 2185b892326406927b709cdaf6c384d4ababf456332Ben Murdoch int* http_status_code) override { 2195b892326406927b709cdaf6c384d4ababf456332Ben Murdoch return false; 2205b892326406927b709cdaf6c384d4ababf456332Ben Murdoch } 2215b892326406927b709cdaf6c384d4ababf456332Ben Murdoch 222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) virtual void SetExtraRequestHeaders( 223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const net::HttpRequestHeaders& headers) OVERRIDE { 224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // TODO(asargent) - we'll need to add proper support for range headers. 225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // crbug.com/369895. 226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::string range_header; 227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (verify_job_.get()) 229010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) verify_job_ = NULL; 230010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) URLRequestFileJob::SetExtraRequestHeaders(headers); 232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 234a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch virtual void OnSeekComplete(int64 result) OVERRIDE { 235a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DCHECK_EQ(seek_position_, 0); 236a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch seek_position_ = result; 237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // TODO(asargent) - we'll need to add proper support for range headers. 238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // crbug.com/369895. 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result > 0 && verify_job_.get()) 240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) verify_job_ = NULL; 241a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 242a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 243a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch virtual void OnReadComplete(net::IOBuffer* buffer, int result) OVERRIDE { 2440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (result >= 0) 2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.OnReadCompleteResult", result); 2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch else 2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch UMA_HISTOGRAM_SPARSE_SLOWLY("ExtensionUrlRequest.OnReadCompleteError", 2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch -result); 249a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (result > 0) { 250a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bytes_read_ += result; 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (verify_job_.get()) { 252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) verify_job_->BytesRead(result, buffer->data()); 253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!remaining_bytes()) 254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) verify_job_->DoneReading(); 255a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 256a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 257a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 258a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 260a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch virtual ~URLRequestExtensionJob() { 261a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.TotalKbRead", bytes_read_ / 1024); 262a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.SeekPosition", seek_position_); 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (request_timer_.get()) 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UMA_HISTOGRAM_TIMES("ExtensionUrlRequest.Latency", 265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch request_timer_->Elapsed()); 266a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void OnFilePathAndLastModifiedTimeRead(base::FilePath* read_file_path, 269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Time* last_modified_time) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_path_ = *read_file_path; 271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) response_info_.headers = BuildHttpHeaders( 272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content_security_policy_, 273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) send_cors_header_, 274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *last_modified_time); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequestFileJob::Start(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_refptr<ContentVerifyJob> verify_job_; 279a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<base::ElapsedTimer> request_timer_; 281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 282a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // The position we seeked to in the file. 283a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch int64 seek_position_; 284a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 285a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // The number of bytes of content we read from the file. 286a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch int bytes_read_; 287a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::HttpResponseInfo response_info_; 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::FilePath directory_path_; 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ExtensionResource resource_; 291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string content_security_policy_; 292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool send_cors_header_; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WeakPtrFactory<URLRequestExtensionJob> weak_factory_; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionCanLoadInIncognito(const ResourceRequestInfo* info, 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::InfoMap* extension_info_map) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension_info_map->IsIncognitoEnabled(extension_id)) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only allow incognito toplevel navigations to extension resources in 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // split mode. In spanning mode, the extension must run in a single process, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and an incognito tab prevents that. 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_info_map->extensions().GetByID(extension_id); 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return extension && extensions::IncognitoInfo::IsSplitMode(extension); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if an chrome-extension:// resource should be allowed to load. 315a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Pass true for |is_incognito| only for incognito profiles and not Chrome OS 316a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// guest mode profiles. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(aa): This should be moved into ExtensionResourceRequestPolicy, but we 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// first need to find a way to get CanLoadInIncognito state into the renderers. 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AllowExtensionResourceLoad(net::URLRequest* request, 320a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool is_incognito, 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Extension* extension, 322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::InfoMap* extension_info_map) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have seen crashes where info is NULL: crbug.com/52374. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!info) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Allowing load of " << request->url().spec() 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "from unknown origin. Could not find user data for " 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "request."; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 333a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (is_incognito && !ExtensionCanLoadInIncognito( 334a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch info, request->url().host(), extension_info_map)) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The following checks are meant to replicate similar set of checks in the 339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // renderer process, performed by ResourceRequestPolicy::CanRequestResource. 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // These are not exactly equivalent, because we don't have the same bits of 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // information. The two checks need to be kept in sync as much as possible, as 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // an exploited renderer can bypass the checks in ResourceRequestPolicy. 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check if the extension for which this request is made is indeed loaded in 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the process sending the request. If not, we need to explicitly check if 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the resource is explicitly accessible or fits in a set of exception cases. 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Note: This allows a case where two extensions execute in the same renderer 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // process to request each other's resources. We can't do a more precise 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // check, since the renderer can lie about which extension has made the 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // request. 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (extension_info_map->process_map().Contains( 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) request->url().host(), info->GetChildID())) { 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 356a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Allow the extension module embedder to grant permission for loads. 357a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (ExtensionsBrowserClient::Get()->AllowCrossRendererResourceLoad( 358a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch request, is_incognito, extension, extension_info_map)) { 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 362a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // No special exceptions for cross-process loading. Block the load. 363a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return false; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the given URL references an icon in the given extension. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLIsForExtensionIcon(const GURL& url, const Extension* extension) { 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(url.SchemeIs(extensions::kExtensionScheme)); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string path = url.path(); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(url.host(), extension->id()); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(path.length() > 0 && path[0] == '/'); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path = path.substr(1); 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return extensions::IconsInfo::GetIcons(extension).ContainsPath(path); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionProtocolHandler 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public net::URLRequestJobFactory::ProtocolHandler { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 383a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ExtensionProtocolHandler(bool is_incognito, 384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::InfoMap* extension_info_map) 385a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : is_incognito_(is_incognito), extension_info_map_(extension_info_map) {} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ExtensionProtocolHandler() {} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual net::URLRequestJob* MaybeCreateJob( 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequest* request, 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::NetworkDelegate* network_delegate) const OVERRIDE; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 394a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const bool is_incognito_; 395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::InfoMap* const extension_info_map_; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ExtensionProtocolHandler); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates URLRequestJobs for extension:// URLs. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::URLRequestJob* 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionProtocolHandler::MaybeCreateJob( 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequest* request, net::NetworkDelegate* network_delegate) const { 403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // chrome-extension://extension-id/resource/path.js 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string extension_id = request->url().host(); 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Extension* extension = 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_info_map_->extensions().GetByID(extension_id); 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mpcomplete): better error code. 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AllowExtensionResourceLoad( 410a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch request, is_incognito_, extension, extension_info_map_)) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new net::URLRequestErrorJob( 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request, network_delegate, net::ERR_ADDRESS_UNREACHABLE); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // If this is a disabled extension only allow the icon to load. 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath directory_path; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directory_path = extension->path(); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (directory_path.value().empty()) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* disabled_extension = 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_info_map_->disabled_extensions().GetByID(extension_id); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (URLIsForExtensionIcon(request->url(), disabled_extension)) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directory_path = disabled_extension->path(); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (directory_path.value().empty()) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 430a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Set up content security policy. 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string content_security_policy; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool send_cors_header = false; 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool follow_symlinks_anywhere = false; 4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension) { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string resource_path = request->url().path(); 4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Use default CSP for <webview>. 4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!url_request_util::IsWebViewRequest(request)) { 4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch content_security_policy = 4410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch extensions::CSPInfo::GetResourceContentSecurityPolicy(extension, 4420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch resource_path); 4430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((extension->manifest_version() >= 2 || 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::WebAccessibleResourcesInfo::HasWebAccessibleResources( 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension)) && 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::WebAccessibleResourcesInfo::IsResourceWebAccessible( 4490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch extension, resource_path)) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) send_cors_header = true; 4510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) follow_symlinks_anywhere = 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (extension->creation_flags() & Extension::FOLLOW_SYMLINKS_ANYWHERE) 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) != 0; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 458a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Create a job for a generated background page. 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string path = request->url().path(); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path.size() > 1 && 461a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch path.substr(1) == extensions::kGeneratedBackgroundPageFilename) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new GeneratedBackgroundPageJob( 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request, network_delegate, extension, content_security_policy); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 466a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Component extension resources may be part of the embedder's resource files, 467a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // for example component_extension_resources.pak in Chrome. 468a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch net::URLRequestJob* resource_bundle_job = 469a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch extensions::ExtensionsBrowserClient::Get() 470a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ->MaybeCreateResourceBundleRequestJob(request, 471a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch network_delegate, 472a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch directory_path, 473a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch content_security_policy, 474a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch send_cors_header); 475a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (resource_bundle_job) 476a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return resource_bundle_job; 477a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 478a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::FilePath relative_path = 479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::file_util::ExtensionURLToRelativeFilePath(request->url()); 480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 481a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Handle shared resources (extension A loading resources out of extension B). 482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (SharedModuleInfo::IsImportedPath(path)) { 483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string new_extension_id; 484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string new_relative_path; 485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SharedModuleInfo::ParseImportedPath(path, &new_extension_id, 486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &new_relative_path); 487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Extension* new_extension = 488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_info_map_->extensions().GetByID(new_extension_id); 489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool first_party_in_import = false; 491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // NB: This first_party_for_cookies call is not for security, it is only 492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // used so an exported extension can limit the visible surface to the 493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // extension that imports it, more or less constituting its API. 494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& first_party_path = 495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) request->first_party_for_cookies().path(); 496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (SharedModuleInfo::IsImportedPath(first_party_path)) { 497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string first_party_id; 498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string dummy; 499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SharedModuleInfo::ParseImportedPath(first_party_path, &first_party_id, 500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &dummy); 501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (first_party_id == new_extension_id) { 502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) first_party_in_import = true; 503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (SharedModuleInfo::ImportsExtensionById(extension, new_extension_id) && 507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new_extension && 508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (first_party_in_import || 509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SharedModuleInfo::IsExportAllowed(new_extension, new_relative_path))) { 510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) directory_path = new_extension->path(); 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_id = new_extension_id; 512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) relative_path = base::FilePath::FromUTF8Unsafe(new_relative_path); 513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return NULL; 515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 517010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ContentVerifyJob* verify_job = NULL; 518010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ContentVerifier* verifier = extension_info_map_->content_verifier(); 519010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (verifier) { 520010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) verify_job = 521010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) verifier->CreateJobFor(extension_id, directory_path, relative_path); 522010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (verify_job) 523010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) verify_job->Start(); 524010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new URLRequestExtensionJob(request, 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_delegate, 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_id, 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directory_path, 530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) relative_path, 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_security_policy, 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) send_cors_header, 533010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) follow_symlinks_anywhere, 534010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) verify_job); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 539a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnet::HttpResponseHeaders* BuildHttpHeaders( 540a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::string& content_security_policy, 541a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool send_cors_header, 542a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const base::Time& last_modified_time) { 543a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string raw_headers; 544a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append("HTTP/1.1 200 OK"); 545a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!content_security_policy.empty()) { 546a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append(1, '\0'); 547a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append("Content-Security-Policy: "); 548a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append(content_security_policy); 549a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 550a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 551a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (send_cors_header) { 552a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append(1, '\0'); 553a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append("Access-Control-Allow-Origin: *"); 554a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 555a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 556a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!last_modified_time.is_null()) { 557a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Hash the time and make an etag to avoid exposing the exact 558a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // user installation time of the extension. 559a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string hash = 560a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::StringPrintf("%" PRId64, last_modified_time.ToInternalValue()); 561a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch hash = base::SHA1HashString(hash); 562a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::string etag; 563a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::Base64Encode(hash, &etag); 564a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append(1, '\0'); 565a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append("ETag: \""); 566a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append(etag); 567a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append("\""); 568a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Also force revalidation. 569a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append(1, '\0'); 570a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append("cache-control: no-cache"); 571a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 572a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 573a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch raw_headers.append(2, '\0'); 574a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return new net::HttpResponseHeaders(raw_headers); 575a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 576a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( 578a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool is_incognito, 579f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extensions::InfoMap* extension_info_map) { 580a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return new ExtensionProtocolHandler(is_incognito, extension_info_map); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 582a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 583a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} // namespace extensions 584