summaryrefslogtreecommitdiffstats
path: root/mojo
diff options
context:
space:
mode:
authorben <ben@chromium.org>2016-02-01 17:59:11 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-02 02:01:52 +0000
commitaab3147b2e1f1d48113cb5c65b4224c497be3e4c (patch)
treefff37171d0de7f85670ff44bd6e7b1a36242b4de /mojo
parent58412186f7384edec6eb83f5e6c5f52dee9ab256 (diff)
downloadchromium_src-aab3147b2e1f1d48113cb5c65b4224c497be3e4c.zip
chromium_src-aab3147b2e1f1d48113cb5c65b4224c497be3e4c.tar.gz
chromium_src-aab3147b2e1f1d48113cb5c65b4224c497be3e4c.tar.bz2
Implement a skeleton of Mojo Application manifests.
In this first cut, when a local .mojo or .exe target is loaded, we look for a manifest json file nearby and consume it into a catalog maintained by the PackageManagerImpl. Default manifests are provided for several interesting Mojo apps in Chromium, with pretty names to make the Mash Task Viewer look a little nicer. Future CL improvements: - comprehensive testing. currently mojo_shell_apptests is broken due to the EDK change. - persisting the consumed catalog in a single store (e.g. Preferences) so that we don't need to read a bunch of files every startup. i.e. implement ApplicationCatalogStore. - block creating the ApplicationInstance on having read the manifest, so the base CapabilityFilter is understood. - implement base CapabilityFilter application. R=rockot@chromium.org http://crbug.com/575858 Review URL: https://codereview.chromium.org/1641043002 Cr-Commit-Position: refs/heads/master@{#372853}
Diffstat (limited to 'mojo')
-rw-r--r--mojo/public/mojo_application.gni14
-rw-r--r--mojo/services/tracing/BUILD.gn2
-rw-r--r--mojo/services/tracing/manifest.json5
-rw-r--r--mojo/shell/BUILD.gn11
-rw-r--r--mojo/shell/application_manager.cc4
-rw-r--r--mojo/shell/application_manager_apptest.cc10
-rw-r--r--mojo/shell/application_manager_apptest_driver_manifest.json5
-rw-r--r--mojo/shell/application_manager_apptest_manifest.json5
-rw-r--r--mojo/shell/fetcher/about_fetcher_unittest.cc2
-rw-r--r--mojo/shell/fetcher/url_resolver.cc13
-rw-r--r--mojo/shell/fetcher/url_resolver.h4
-rw-r--r--mojo/shell/fetcher/url_resolver_unittest.cc16
-rw-r--r--mojo/shell/package_manager.h7
-rw-r--r--mojo/shell/package_manager/BUILD.gn1
-rw-r--r--mojo/shell/package_manager/DEPS3
-rw-r--r--mojo/shell/package_manager/capability_filter_content_handler_unittest.cc2
-rw-r--r--mojo/shell/package_manager/content_handler_unittest.cc2
-rw-r--r--mojo/shell/package_manager/package_manager_impl.cc152
-rw-r--r--mojo/shell/package_manager/package_manager_impl.h50
-rw-r--r--mojo/shell/public/interfaces/application_manager.mojom1
-rw-r--r--mojo/shell/standalone/context.cc4
-rw-r--r--mojo/shell/test_package_manager.cc5
-rw-r--r--mojo/shell/test_package_manager.h2
23 files changed, 309 insertions, 11 deletions
diff --git a/mojo/public/mojo_application.gni b/mojo/public/mojo_application.gni
index 70fc5f1d..cd0e78e 100644
--- a/mojo/public/mojo_application.gni
+++ b/mojo/public/mojo_application.gni
@@ -39,6 +39,20 @@ template("mojo_native_application") {
}
mojo_deps += [ ":$copy_step_name" ]
}
+ if (defined(invoker.manifest)) {
+ copy_step_name = "${base_target_name}__copy_manifest"
+ copy(copy_step_name) {
+ sources = invoker.manifest
+ outputs = [
+ "${root_out_dir}/${base_target_name}/manifest.json",
+ ]
+ if (defined(invoker.testonly)) {
+ testonly = invoker.testonly
+ }
+ deps = mojo_deps
+ }
+ mojo_deps += [ ":$copy_step_name" ]
+ }
output = base_target_name + ".mojo"
library_target_name = base_target_name + "_library"
diff --git a/mojo/services/tracing/BUILD.gn b/mojo/services/tracing/BUILD.gn
index 14fed0f..2ffee2f 100644
--- a/mojo/services/tracing/BUILD.gn
+++ b/mojo/services/tracing/BUILD.gn
@@ -11,6 +11,8 @@ mojo_native_application("tracing") {
avoid_runner_cycle = true
+ manifest = [ "manifest.json" ]
+
deps = [
":lib",
"//mojo/public/cpp/system",
diff --git a/mojo/services/tracing/manifest.json b/mojo/services/tracing/manifest.json
new file mode 100644
index 0000000..ee4a0aa
--- /dev/null
+++ b/mojo/services/tracing/manifest.json
@@ -0,0 +1,5 @@
+{
+ "url": "mojo://tracing/",
+ "name": "Tracing Collector",
+ "capabilities": { }
+}
diff --git a/mojo/shell/BUILD.gn b/mojo/shell/BUILD.gn
index ad4273f..d5a3843 100644
--- a/mojo/shell/BUILD.gn
+++ b/mojo/shell/BUILD.gn
@@ -132,6 +132,7 @@ mojo_native_application("apptests") {
sources = [
"application_manager_apptest.cc",
]
+ manifest = [ "application_manager_apptest_manifest.json" ]
deps = [
":test_bindings",
@@ -158,6 +159,7 @@ executable("application_manager_apptest_driver") {
]
deps = [
+ ":copy_application_manager_apptest_driver_manifest",
":test_bindings",
"//base",
"//base:base_static",
@@ -173,6 +175,15 @@ executable("application_manager_apptest_driver") {
]
}
+copy("copy_application_manager_apptest_driver_manifest") {
+ sources = [
+ "application_manager_apptest_driver_manifest.json",
+ ]
+ outputs = [
+ "${root_out_dir}/{{source_file_part}}",
+ ]
+}
+
executable("application_manager_apptest_target") {
testonly = true
diff --git a/mojo/shell/application_manager.cc b/mojo/shell/application_manager.cc
index b1deb85..87a8706 100644
--- a/mojo/shell/application_manager.cc
+++ b/mojo/shell/application_manager.cc
@@ -114,6 +114,8 @@ bool ApplicationManager::ConnectToRunningApplication(
if (!instance)
return false;
+ // TODO(beng): CHECK() that the target URL is already in the application
+ // catalog.
instance->ConnectToClient(std::move(*params));
return true;
}
@@ -328,6 +330,8 @@ mojom::ApplicationInfoPtr ApplicationManager::CreateApplicationInfoForInstance(
info->id = instance->id();
info->url = instance->identity().url().spec();
info->qualifier = instance->identity().qualifier();
+ info->name =
+ package_manager_->GetApplicationName(instance->identity().url().spec());
if (instance->identity().url().spec() == "mojo://shell/")
info->pid = base::Process::Current().Pid();
else
diff --git a/mojo/shell/application_manager_apptest.cc b/mojo/shell/application_manager_apptest.cc
index 1e18c6b..d348c35 100644
--- a/mojo/shell/application_manager_apptest.cc
+++ b/mojo/shell/application_manager_apptest.cc
@@ -79,12 +79,15 @@ class ApplicationManagerAppTest : public mojo::test::ApplicationTestBase,
protected:
struct ApplicationInfo {
- ApplicationInfo(uint32_t id, const std::string& url)
- : id(id), url(url), pid(base::kNullProcessId) {}
+ ApplicationInfo(uint32_t id,
+ const std::string& url,
+ const std::string& name)
+ : id(id), url(url), pid(base::kNullProcessId), name(name) {}
uint32_t id;
std::string url;
base::ProcessId pid;
+ std::string name;
};
void AddListenerAndWaitForApplications() {
@@ -118,7 +121,8 @@ class ApplicationManagerAppTest : public mojo::test::ApplicationTestBase,
Array<mojom::ApplicationInfoPtr> applications) override {}
void ApplicationInstanceCreated(
mojom::ApplicationInfoPtr application) override {
- applications_.push_back(ApplicationInfo(application->id, application->url));
+ applications_.push_back(ApplicationInfo(application->id, application->url,
+ application->name));
}
void ApplicationInstanceDestroyed(uint32_t id) override {
for (auto it = applications_.begin(); it != applications_.end(); ++it) {
diff --git a/mojo/shell/application_manager_apptest_driver_manifest.json b/mojo/shell/application_manager_apptest_driver_manifest.json
new file mode 100644
index 0000000..d4b33a4
--- /dev/null
+++ b/mojo/shell/application_manager_apptest_driver_manifest.json
@@ -0,0 +1,5 @@
+{
+ "url": "exe://application_manager_apptest_driver/",
+ "name": "Application Manager Apptests: Driver",
+ "capabilities": { }
+}
diff --git a/mojo/shell/application_manager_apptest_manifest.json b/mojo/shell/application_manager_apptest_manifest.json
new file mode 100644
index 0000000..1c8fd8a
--- /dev/null
+++ b/mojo/shell/application_manager_apptest_manifest.json
@@ -0,0 +1,5 @@
+{
+ "url": "mojo://mojo_shell_apptests/",
+ "name": "Application Manager Apptests",
+ "capabilities": { }
+}
diff --git a/mojo/shell/fetcher/about_fetcher_unittest.cc b/mojo/shell/fetcher/about_fetcher_unittest.cc
index 93c27c4..121393f 100644
--- a/mojo/shell/fetcher/about_fetcher_unittest.cc
+++ b/mojo/shell/fetcher/about_fetcher_unittest.cc
@@ -131,7 +131,7 @@ class AboutFetcherTest : public testing::Test {
base::FilePath shell_dir;
PathService::Get(base::DIR_MODULE, &shell_dir);
scoped_ptr<PackageManagerImpl> package_manager(
- new PackageManagerImpl(shell_dir, nullptr));
+ new PackageManagerImpl(shell_dir, nullptr, nullptr));
package_manager->RegisterContentHandler(
"text/html", GURL("test:html_content_handler"));
application_manager_.reset(
diff --git a/mojo/shell/fetcher/url_resolver.cc b/mojo/shell/fetcher/url_resolver.cc
index 499d9fdb..0b2c182 100644
--- a/mojo/shell/fetcher/url_resolver.cc
+++ b/mojo/shell/fetcher/url_resolver.cc
@@ -47,5 +47,18 @@ GURL URLResolver::ResolveMojoURL(const GURL& mojo_url) const {
}
}
+GURL URLResolver::ResolveMojoManifest(const GURL& mojo_url) const {
+ // TODO(beng): think more about how this should be done for exe targets.
+ if (mojo_url.SchemeIs("mojo")) {
+ std::string host = GetBaseURLAndQuery(mojo_url, nullptr).host();
+ return mojo_base_url_.Resolve(host +
+ "/manifest.json");
+ } else if (mojo_url.SchemeIs("exe")) {
+ return mojo_base_url_.Resolve(GetBaseURLAndQuery(mojo_url, nullptr).host() +
+ "_manifest.json");
+ }
+ return GURL();
+}
+
} // namespace shell
} // namespace mojo
diff --git a/mojo/shell/fetcher/url_resolver.h b/mojo/shell/fetcher/url_resolver.h
index 2f1e0a0..c76e544 100644
--- a/mojo/shell/fetcher/url_resolver.h
+++ b/mojo/shell/fetcher/url_resolver.h
@@ -25,6 +25,10 @@ class URLResolver {
// Resolve the given "mojo:" URL to the URL that should be used to fetch the
// code for the corresponding Mojo App.
GURL ResolveMojoURL(const GURL& mojo_url) const;
+ // Resolve the given "mojo:" URL to the URL that should be used to fetch the
+ // application manifest for the corresponding Mojo App. Returns an empty url
+ // if no manifest can be resolved (e.g. for non-Mojo application URLs).
+ GURL ResolveMojoManifest(const GURL& mojo_url) const;
private:
GURL mojo_base_url_;
diff --git a/mojo/shell/fetcher/url_resolver_unittest.cc b/mojo/shell/fetcher/url_resolver_unittest.cc
index 6f0b3aa..23a829e 100644
--- a/mojo/shell/fetcher/url_resolver_unittest.cc
+++ b/mojo/shell/fetcher/url_resolver_unittest.cc
@@ -29,6 +29,22 @@ TEST_F(URLResolverTest, TestQueryForBaseHttpURL) {
EXPECT_EQ("http://127.0.0.1:1234/foo/foo.mojo?a=b", mapped_url.spec());
}
+TEST_F(URLResolverTest, TestManifest) {
+ URLResolver resolver(GURL("file:///base"));
+ {
+ GURL mapped_url = resolver.ResolveMojoManifest(GURL("mojo:foo"));
+ EXPECT_EQ("file:///base/foo/manifest.json", mapped_url.spec());
+ }
+ {
+ GURL mapped_url = resolver.ResolveMojoManifest(GURL("exe:foo"));
+ EXPECT_EQ("file:///base/foo_manifest.json", mapped_url.spec());
+ }
+ {
+ GURL mapped_url = resolver.ResolveMojoManifest(GURL("http://localhost/"));
+ EXPECT_TRUE(mapped_url.is_empty());
+ }
+}
+
} // namespace
} // namespace test
} // namespace shell
diff --git a/mojo/shell/package_manager.h b/mojo/shell/package_manager.h
index 147c25d..922c56f 100644
--- a/mojo/shell/package_manager.h
+++ b/mojo/shell/package_manager.h
@@ -53,6 +53,13 @@ class PackageManager {
const GURL& target_url,
const CapabilityFilter& target_filter,
InterfaceRequest<Application>* application_request) = 0;
+
+ // Returns true if a manifest for |url| exists within the PackageManager's
+ // application catalog.
+ virtual bool IsURLInCatalog(const std::string& url) const = 0;
+
+ // Returns the name for the application at |url| from its manifest.
+ virtual std::string GetApplicationName(const std::string& url) const = 0;
};
} // namespace shell
diff --git a/mojo/shell/package_manager/BUILD.gn b/mojo/shell/package_manager/BUILD.gn
index 3d6b72c..f49cd8c 100644
--- a/mojo/shell/package_manager/BUILD.gn
+++ b/mojo/shell/package_manager/BUILD.gn
@@ -16,6 +16,7 @@ source_set("package_manager") {
"//mojo/shell",
"//mojo/shell/fetcher",
"//mojo/util:filename_util",
+ "//net",
]
}
diff --git a/mojo/shell/package_manager/DEPS b/mojo/shell/package_manager/DEPS
index e69de29..6a2f02e 100644
--- a/mojo/shell/package_manager/DEPS
+++ b/mojo/shell/package_manager/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+net/base",
+]
diff --git a/mojo/shell/package_manager/capability_filter_content_handler_unittest.cc b/mojo/shell/package_manager/capability_filter_content_handler_unittest.cc
index 82e6262..3a32a0f 100644
--- a/mojo/shell/package_manager/capability_filter_content_handler_unittest.cc
+++ b/mojo/shell/package_manager/capability_filter_content_handler_unittest.cc
@@ -63,7 +63,7 @@ class TestFetcher : public Fetcher {
class TestPackageManager : public PackageManagerImpl {
public:
TestPackageManager(const base::FilePath& package_path)
- : PackageManagerImpl(package_path, nullptr) {}
+ : PackageManagerImpl(package_path, nullptr, nullptr) {}
~TestPackageManager() override {}
private:
diff --git a/mojo/shell/package_manager/content_handler_unittest.cc b/mojo/shell/package_manager/content_handler_unittest.cc
index 64cfa74..657404a 100644
--- a/mojo/shell/package_manager/content_handler_unittest.cc
+++ b/mojo/shell/package_manager/content_handler_unittest.cc
@@ -134,7 +134,7 @@ class TestApplicationLoader : public ApplicationLoader,
class TestPackageManagerImpl : public PackageManagerImpl {
public:
explicit TestPackageManagerImpl(const base::FilePath& package_path)
- : PackageManagerImpl(package_path, nullptr),
+ : PackageManagerImpl(package_path, nullptr, nullptr),
mime_type_(kTestMimeType) {}
~TestPackageManagerImpl() override {}
diff --git a/mojo/shell/package_manager/package_manager_impl.cc b/mojo/shell/package_manager/package_manager_impl.cc
index 90c8674..0d47150 100644
--- a/mojo/shell/package_manager/package_manager_impl.cc
+++ b/mojo/shell/package_manager/package_manager_impl.cc
@@ -9,6 +9,11 @@
#include <utility>
#include "base/bind.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner_util.h"
+#include "base/values.h"
#include "mojo/shell/application_manager.h"
#include "mojo/shell/connect_util.h"
#include "mojo/shell/fetcher/about_fetcher.h"
@@ -21,25 +26,80 @@
#include "mojo/shell/query_util.h"
#include "mojo/shell/switches.h"
#include "mojo/util/filename_util.h"
+#include "net/base/filename_util.h"
#include "url/gurl.h"
namespace mojo {
namespace shell {
+namespace {
+
+CapabilityFilter BuildCapabilityFilterFromDictionary(
+ const base::DictionaryValue& value) {
+ CapabilityFilter filter;
+ base::DictionaryValue::Iterator it(value);
+ for (; !it.IsAtEnd(); it.Advance()) {
+ const base::ListValue* values = nullptr;
+ CHECK(it.value().GetAsList(&values));
+ AllowedInterfaces interfaces;
+ for (auto i = values->begin(); i != values->end(); ++i) {
+ std::string iface_name;
+ const base::Value* v = *i;
+ CHECK(v->GetAsString(&iface_name));
+ interfaces.insert(iface_name);
+ }
+ filter[it.key()] = interfaces;
+ }
+ return filter;
+}
+
+ApplicationInfo BuildApplicationInfoFromDictionary(
+ const base::DictionaryValue& value) {
+ ApplicationInfo info;
+ CHECK(value.GetString("url", &info.url));
+ CHECK(value.GetString("name", &info.name));
+ const base::DictionaryValue* capabilities = nullptr;
+ CHECK(value.GetDictionary("capabilities", &capabilities));
+ info.base_filter = BuildCapabilityFilterFromDictionary(*capabilities);
+ return info;
+}
+
+void SerializeEntry(const ApplicationInfo& entry,
+ base::DictionaryValue** value) {
+ *value = new base::DictionaryValue;
+ (*value)->SetString("url", entry.url);
+ (*value)->SetString("name", entry.name);
+ base::DictionaryValue* capabilities = new base::DictionaryValue;
+ for (const auto& pair : entry.base_filter) {
+ scoped_ptr<base::ListValue> interfaces(new base::ListValue);
+ for (const auto& iface_name : pair.second)
+ interfaces->AppendString(iface_name);
+ capabilities->Set(pair.first, std::move(interfaces));
+ }
+ (*value)->Set("capabilities", make_scoped_ptr(capabilities));
+}
+
+}
+
+ApplicationInfo::ApplicationInfo() {}
+ApplicationInfo::~ApplicationInfo() {}
PackageManagerImpl::PackageManagerImpl(
const base::FilePath& shell_file_root,
- base::TaskRunner* task_runner)
+ base::TaskRunner* task_runner,
+ ApplicationCatalogStore* catalog_store)
: application_manager_(nullptr),
disable_cache_(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableCache)),
content_handler_id_counter_(0u),
task_runner_(task_runner),
- shell_file_root_(shell_file_root) {
+ shell_file_root_(shell_file_root),
+ catalog_store_(catalog_store) {
if (!shell_file_root.empty()) {
GURL mojo_root_file_url =
util::FilePathToFileURL(shell_file_root).Resolve(std::string());
url_resolver_.reset(new URLResolver(mojo_root_file_url));
}
+ DeserializeCatalog();
}
PackageManagerImpl::~PackageManagerImpl() {
@@ -96,6 +156,10 @@ void PackageManagerImpl::FetchRequest(
new LocalFetcher(network_service_.get(), resolved_url,
GetBaseURLAndQuery(resolved_url, nullptr),
shell_file_root_, loader_callback);
+
+ // TODO(beng): Determine if this is in the right place, and block
+ // establishing the connection on receiving a complete manifest.
+ EnsureURLInCatalog(url);
return;
}
@@ -132,6 +196,16 @@ uint32_t PackageManagerImpl::HandleWithContentHandler(
return Shell::kInvalidApplicationID;
}
+bool PackageManagerImpl::IsURLInCatalog(const std::string& url) const {
+ return catalog_.find(url) != catalog_.end();
+}
+
+std::string PackageManagerImpl::GetApplicationName(
+ const std::string& url) const {
+ auto it = catalog_.find(url);
+ return it != catalog_.end() ? it->second.name : url;
+}
+
GURL PackageManagerImpl::ResolveURL(const GURL& url) {
return url_resolver_.get() ? url_resolver_->ResolveMojoURL(url) : url;
}
@@ -223,5 +297,79 @@ void PackageManagerImpl::OnContentHandlerConnectionClosed(
identity_to_content_handler_.erase(it);
}
+void PackageManagerImpl::EnsureURLInCatalog(const GURL& url) {
+ if (IsURLInCatalog(url.spec()))
+ return;
+
+ GURL manifest_url = url_resolver_->ResolveMojoManifest(url);
+ if (manifest_url.is_empty())
+ return;
+ base::FilePath manifest_path;
+ CHECK(net::FileURLToFilePath(manifest_url, &manifest_path));
+ base::PostTaskAndReplyWithResult(
+ task_runner_, FROM_HERE,
+ base::Bind(&PackageManagerImpl::ReadManifest, base::Unretained(this),
+ manifest_path),
+ base::Bind(&PackageManagerImpl::OnReadManifest,
+ base::Unretained(this)));
+}
+
+void PackageManagerImpl::DeserializeCatalog() {
+ ApplicationInfo info;
+ info.url = "mojo://shell/";
+ info.name = "Mojo Shell";
+ catalog_[info.url] = info;
+
+ if (!catalog_store_)
+ return;
+ base::ListValue* catalog = nullptr;
+ catalog_store_->GetStore(&catalog);
+ CHECK(catalog);
+ for (auto it = catalog->begin(); it != catalog->end(); ++it) {
+ const base::DictionaryValue* dictionary = nullptr;
+ const base::Value* v = *it;
+ CHECK(v->GetAsDictionary(&dictionary));
+ DeserializeApplication(dictionary);
+ }
+}
+
+void PackageManagerImpl::SerializeCatalog() {
+ scoped_ptr<base::ListValue> catalog(new base::ListValue);
+ for (const auto& info : catalog_) {
+ base::DictionaryValue* dictionary = nullptr;
+ SerializeEntry(info.second, &dictionary);
+ catalog->Append(make_scoped_ptr(dictionary));
+ }
+ if (catalog_store_)
+ catalog_store_->UpdateStore(std::move(catalog));
+}
+
+void PackageManagerImpl::DeserializeApplication(
+ const base::DictionaryValue* dictionary) {
+ ApplicationInfo info = BuildApplicationInfoFromDictionary(*dictionary);
+ CHECK(catalog_.find(info.url) == catalog_.end());
+ catalog_[info.url] = info;
+}
+
+scoped_ptr<base::Value> PackageManagerImpl::ReadManifest(
+ const base::FilePath& manifest_path) {
+ JSONFileValueDeserializer deserializer(manifest_path);
+ int error = 0;
+ std::string message;
+ // TODO(beng): probably want to do more detailed error checking. This should
+ // be done when figuring out if to unblock connection completion.
+ return deserializer.Deserialize(&error, &message);
+}
+
+void PackageManagerImpl::OnReadManifest(scoped_ptr<base::Value> manifest) {
+ if (!manifest)
+ return;
+
+ base::DictionaryValue* dictionary = nullptr;
+ CHECK(manifest->GetAsDictionary(&dictionary));
+ DeserializeApplication(dictionary);
+ SerializeCatalog();
+}
+
} // namespace shell
} // namespace mojo
diff --git a/mojo/shell/package_manager/package_manager_impl.h b/mojo/shell/package_manager/package_manager_impl.h
index e550fdd..9aee042 100644
--- a/mojo/shell/package_manager/package_manager_impl.h
+++ b/mojo/shell/package_manager/package_manager_impl.h
@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
+#include "base/values.h"
#include "mojo/services/network/public/interfaces/network_service.mojom.h"
#include "mojo/services/network/public/interfaces/url_loader_factory.mojom.h"
#include "mojo/shell/fetcher/url_resolver.h"
@@ -25,6 +26,32 @@ class ContentHandlerConnection;
class Fetcher;
class Identity;
+// Static information about an application package known to the PackageManager.
+struct ApplicationInfo {
+ ApplicationInfo();
+ ~ApplicationInfo();
+
+ std::string url;
+ std::string name;
+ CapabilityFilter base_filter;
+};
+
+// Implemented by an object that provides storage for the application catalog
+// (e.g. in Chrome, preferences). The PackageManagerImpl is the canonical owner
+// of the contents of the store, so no one else must modify its contents.
+class ApplicationCatalogStore {
+ public:
+ // Called during initialization to construct the PackageManagerImpl's catalog.
+ virtual void GetStore(base::ListValue** store) = 0;
+
+ // Write the catalog to the store. Called when the PackageManagerImpl learns
+ // of a newly encountered application.
+ virtual void UpdateStore(scoped_ptr<base::ListValue> store) = 0;
+
+ protected:
+ virtual ~ApplicationCatalogStore();
+};
+
// This is the default implementation of PackageManager. It loads http/s urls
// off the network as well as providing special handling for mojo: and about:
// urls.
@@ -36,7 +63,8 @@ class PackageManagerImpl : public PackageManager {
// load. This can be null only in tests where application loading is handled
// by custom ApplicationLoader implementations.
PackageManagerImpl(const base::FilePath& shell_file_root,
- base::TaskRunner* task_runner);
+ base::TaskRunner* task_runner,
+ ApplicationCatalogStore* catalog_store);
~PackageManagerImpl() override;
// Register a content handler to handle content of |mime_type|.
@@ -71,6 +99,8 @@ class PackageManagerImpl : public PackageManager {
const GURL& target_url,
const CapabilityFilter& target_filter,
InterfaceRequest<Application>* application_request) override;
+ bool IsURLInCatalog(const std::string& url) const override;
+ std::string GetApplicationName(const std::string& url) const override;
GURL ResolveURL(const GURL& url);
bool ShouldHandleWithContentHandler(
@@ -89,6 +119,21 @@ class PackageManagerImpl : public PackageManager {
void OnContentHandlerConnectionClosed(
ContentHandlerConnection* content_handler);
+ // If |url| is not in the catalog, attempts to load a manifest for it.
+ void EnsureURLInCatalog(const GURL& url);
+
+ // Populate/serialize the catalog from/to the supplied store.
+ void DeserializeCatalog();
+ void SerializeCatalog();
+
+ // Construct a catalog entry from |dictionary|.
+ void DeserializeApplication(const base::DictionaryValue* dictionary);
+
+ // Reads a manifest in the blocking pool and returns a base::Value with its
+ // contents via OnReadManifest().
+ scoped_ptr<base::Value> ReadManifest(const base::FilePath& manifest_path);
+ void OnReadManifest(scoped_ptr<base::Value> manifest);
+
ApplicationManager* application_manager_;
scoped_ptr<URLResolver> url_resolver_;
const bool disable_cache_;
@@ -102,6 +147,9 @@ class PackageManagerImpl : public PackageManager {
base::TaskRunner* task_runner_;
base::FilePath shell_file_root_;
+ ApplicationCatalogStore* catalog_store_;
+ std::map<std::string, ApplicationInfo> catalog_;
+
DISALLOW_COPY_AND_ASSIGN(PackageManagerImpl);
};
diff --git a/mojo/shell/public/interfaces/application_manager.mojom b/mojo/shell/public/interfaces/application_manager.mojom
index f4bf384..dc409e6 100644
--- a/mojo/shell/public/interfaces/application_manager.mojom
+++ b/mojo/shell/public/interfaces/application_manager.mojom
@@ -11,6 +11,7 @@ struct ApplicationInfo {
string url;
string qualifier;
uint32 pid;
+ string name;
};
// Implemented by an application that wishes to be informed when the list of
diff --git a/mojo/shell/standalone/context.cc b/mojo/shell/standalone/context.cc
index 22e9414..f03cb61 100644
--- a/mojo/shell/standalone/context.cc
+++ b/mojo/shell/standalone/context.cc
@@ -215,8 +215,8 @@ bool Context::Init(const base::FilePath& shell_file_root) {
task_runners_->io_runner(),
embedder::ScopedPlatformHandle());
- package_manager_ =
- new PackageManagerImpl(shell_file_root, task_runners_->blocking_pool());
+ package_manager_ = new PackageManagerImpl(
+ shell_file_root, task_runners_->blocking_pool(), nullptr);
InitContentHandlers(package_manager_, command_line);
RegisterLocalAliases(package_manager_);
diff --git a/mojo/shell/test_package_manager.cc b/mojo/shell/test_package_manager.cc
index db9194d..889dd8d 100644
--- a/mojo/shell/test_package_manager.cc
+++ b/mojo/shell/test_package_manager.cc
@@ -25,6 +25,11 @@ uint32_t TestPackageManager::HandleWithContentHandler(
InterfaceRequest<Application>* application_request) {
return 0;
}
+bool TestPackageManager::IsURLInCatalog(const std::string& url) const {
+ return true;
+}
+std::string TestPackageManager::GetApplicationName(
+ const std::string& url) const { return url; }
} // namespace test
} // namespace shell
diff --git a/mojo/shell/test_package_manager.h b/mojo/shell/test_package_manager.h
index f48cd73..f4a35df 100644
--- a/mojo/shell/test_package_manager.h
+++ b/mojo/shell/test_package_manager.h
@@ -31,6 +31,8 @@ class TestPackageManager : public PackageManager {
const GURL& target_url,
const CapabilityFilter& target_filter,
InterfaceRequest<Application>* application_request) override;
+ bool IsURLInCatalog(const std::string& url) const override;
+ std::string GetApplicationName(const std::string& url) const override;
DISALLOW_COPY_AND_ASSIGN(TestPackageManager);
};