| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "sky/tools/sky_snapshot/loader.h" |
| |
| #include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/logging.h" |
| #include "base/strings/string_util.h" |
| #include "sky/tools/sky_snapshot/logging.h" |
| #include "sky/tools/sky_snapshot/scope.h" |
| #include "sky/tools/sky_snapshot/switches.h" |
| |
| namespace { |
| |
| std::string Fetch(const std::string& url) { |
| base::FilePath path(url); |
| std::string source; |
| CHECK(base::ReadFileToString(path, &source)) << url; |
| return source; |
| } |
| |
| base::FilePath SimplifyPath(const base::FilePath& path) { |
| std::vector<base::FilePath::StringType> components; |
| path.GetComponents(&components); |
| auto it = components.begin(); |
| base::FilePath result(*it++); |
| for (; it != components.end(); it++) { |
| auto& component = *it; |
| if (component == base::FilePath::kCurrentDirectory) |
| continue; |
| if (component == base::FilePath::kParentDirectory) |
| result = result.DirName(); |
| else |
| result = result.Append(component); |
| } |
| return result; |
| } |
| |
| class Loader { |
| public: |
| Loader(const base::FilePath& package_root); |
| |
| std::string CanonicalizePackageURL(std::string url); |
| Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url); |
| Dart_Handle Import(Dart_Handle url); |
| Dart_Handle Source(Dart_Handle library, Dart_Handle url); |
| |
| private: |
| base::FilePath package_root_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Loader); |
| }; |
| |
| Loader::Loader(const base::FilePath& package_root) |
| : package_root_(package_root) { |
| } |
| |
| std::string Loader::CanonicalizePackageURL(std::string url) { |
| DCHECK(base::StartsWithASCII(url, "package:", true)); |
| base::ReplaceFirstSubstringAfterOffset(&url, 0, "package:", ""); |
| return package_root_.Append(url).AsUTF8Unsafe(); |
| } |
| |
| Dart_Handle Loader::CanonicalizeURL(Dart_Handle library, Dart_Handle url) { |
| std::string string = StringFromDart(url); |
| if (base::StartsWithASCII(string, "dart:", true)) |
| return url; |
| if (base::StartsWithASCII(string, "package:", true)) |
| return StringToDart(CanonicalizePackageURL(string)); |
| base::FilePath base_path(StringFromDart(Dart_LibraryUrl(library))); |
| base::FilePath resolved_path = base_path.DirName().Append(string); |
| base::FilePath normalized_path = SimplifyPath(resolved_path); |
| return StringToDart(normalized_path.AsUTF8Unsafe()); |
| } |
| |
| Dart_Handle Loader::Import(Dart_Handle url) { |
| Dart_Handle source = StringToDart(Fetch(StringFromDart(url))); |
| Dart_Handle result = Dart_LoadLibrary(url, source, 0, 0); |
| LogIfError(result); |
| return result; |
| } |
| |
| Dart_Handle Loader::Source(Dart_Handle library, Dart_Handle url) { |
| Dart_Handle source = StringToDart(Fetch(StringFromDart(url))); |
| Dart_Handle result = Dart_LoadSource(library, url, source, 0, 0); |
| LogIfError(result); |
| return result; |
| } |
| |
| Loader* g_loader = nullptr; |
| |
| Loader& GetLoader() { |
| if (!g_loader) { |
| base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); |
| CHECK(command_line.HasSwitch(switches::kPackageRoot)) |
| << "Need --package-root"; |
| g_loader = |
| new Loader(command_line.GetSwitchValuePath(switches::kPackageRoot)); |
| } |
| return *g_loader; |
| } |
| |
| } // namespace |
| |
| Dart_Handle HandleLibraryTag(Dart_LibraryTag tag, |
| Dart_Handle library, |
| Dart_Handle url) { |
| CHECK(Dart_IsLibrary(library)); |
| CHECK(Dart_IsString(url)); |
| |
| if (tag == Dart_kCanonicalizeUrl) |
| return GetLoader().CanonicalizeURL(library, url); |
| |
| if (tag == Dart_kImportTag) |
| return GetLoader().Import(url); |
| |
| if (tag == Dart_kSourceTag) |
| return GetLoader().Source(library, url); |
| |
| return Dart_NewApiError("Unknown library tag."); |
| } |
| |
| void LoadScript(const std::string& url) { |
| LogIfError( |
| Dart_LoadScript(StringToDart(url), StringToDart(Fetch(url)), 0, 0)); |
| } |