| Index: chrome/browser/extensions/extension_protocols.cc | 
| diff --git a/chrome/browser/extensions/extension_protocols.cc b/chrome/browser/extensions/extension_protocols.cc | 
| index b0da9b0321838ef93d5fb5c7c1345af550ca7917..42da06b300b8d74b3d3ec412ddccc6a011a9f214 100644 | 
| --- a/chrome/browser/extensions/extension_protocols.cc | 
| +++ b/chrome/browser/extensions/extension_protocols.cc | 
| @@ -205,14 +205,13 @@ class URLRequestExtensionJob : public net::URLRequestFileJob { | 
| net::NetworkDelegate* network_delegate, | 
| const std::string& extension_id, | 
| const base::FilePath& directory_path, | 
| +                         const base::FilePath& relative_path, | 
| const std::string& content_security_policy, | 
| bool send_cors_header) | 
| : net::URLRequestFileJob(request, network_delegate, base::FilePath()), | 
| // TODO(tc): Move all of these files into resources.pak so we don't break | 
| // when updating on Linux. | 
| -      resource_(extension_id, directory_path, | 
| -                extension_file_util::ExtensionURLToRelativeFilePath( | 
| -                    request->url())), | 
| +      resource_(extension_id, directory_path, relative_path), | 
| weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 
| response_info_.headers = BuildHttpHeaders(content_security_policy, | 
| send_cors_header); | 
| @@ -388,7 +387,7 @@ net::URLRequestJob* | 
| ExtensionProtocolHandler::MaybeCreateJob( | 
| net::URLRequest* request, net::NetworkDelegate* network_delegate) const { | 
| // chrome-extension://extension-id/resource/path.js | 
| -  const std::string& extension_id = request->url().host(); | 
| +  std::string extension_id = request->url().host(); | 
| const Extension* extension = | 
| extension_info_map_->extensions().GetByID(extension_id); | 
|  | 
| @@ -462,10 +461,48 @@ ExtensionProtocolHandler::MaybeCreateJob( | 
| } | 
| } | 
|  | 
| +  relative_path = | 
| +      extension_file_util::ExtensionURLToRelativeFilePath(request->url()); | 
| + | 
| +  if (Extension::IsImportedPath(path)) { | 
| +    std::string new_extension_id; | 
| +    std::string new_relative_path; | 
| +    Extension::ParseImportedPath(path, &new_extension_id, &new_relative_path); | 
| +    const Extension* new_extension = | 
| +        extension_info_map_->extensions().GetByID(new_extension_id); | 
| + | 
| +    bool first_party_in_import = false; | 
| +    // NB: This first_party_for_cookies call is not for security, it is only | 
| +    // used so an exported extension can limit the visible surface to the | 
| +    // extension that imports it, more or less constituting its API. | 
| +    const std::string& first_party_path = | 
| +        request->first_party_for_cookies().path(); | 
| +    if (Extension::IsImportedPath(first_party_path)) { | 
| +      std::string first_party_id; | 
| +      std::string dummy; | 
| +      Extension::ParseImportedPath(first_party_path, &first_party_id, &dummy); | 
| +      if (first_party_id == new_extension_id) { | 
| +        first_party_in_import = true; | 
| +      } | 
| +    } | 
| + | 
| +    if (extension->Imports(new_extension_id) && | 
| +        new_extension && | 
| +        (first_party_in_import || | 
| +         new_extension->IsExportAllowed(new_relative_path))) { | 
| +      directory_path = new_extension->path(); | 
| +      extension_id = new_extension_id; | 
| +      relative_path = base::FilePath(new_relative_path); | 
| +    } else { | 
| +      return NULL; | 
| +    } | 
| +  } | 
| + | 
| return new URLRequestExtensionJob(request, | 
| network_delegate, | 
| extension_id, | 
| directory_path, | 
| +                                    relative_path, | 
| content_security_policy, | 
| send_cors_header); | 
| } | 
|  |