Index: mojo/services/launcher/launcher.cc |
diff --git a/mojo/services/launcher/launcher.cc b/mojo/services/launcher/launcher.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..58e00d894dabaa288e3e6824a8f37b3a3d861db5 |
--- /dev/null |
+++ b/mojo/services/launcher/launcher.cc |
@@ -0,0 +1,160 @@ |
+// Copyright 2014 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 "base/compiler_specific.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/strings/string_tokenizer.h" |
+#include "mojo/public/cpp/application/application.h" |
+#include "mojo/services/public/interfaces/launcher/launcher.mojom.h" |
+#include "mojo/services/public/interfaces/network/network_service.mojom.h" |
+#include "mojo/services/public/interfaces/network/url_loader.mojom.h" |
+ |
+namespace mojo { |
+namespace launcher { |
+ |
+class LauncherApp; |
+ |
+class LauncherConnection : public InterfaceImpl<Launcher> { |
+ public: |
+ explicit LauncherConnection(LauncherApp* app) : app_(app) {} |
+ virtual ~LauncherConnection() {} |
+ |
+ private: |
+ // Overridden from Launcher: |
+ virtual void Launch(const String& url) OVERRIDE; |
+ |
+ LauncherApp* app_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(LauncherConnection); |
+}; |
+ |
+class Launch : public URLLoaderClient { |
+ public: |
+ Launch(LauncherApp* app, const String& url); |
+ virtual ~Launch() {} |
+ |
+ private: |
+ // Overridden from URLLoaderClient: |
+ virtual void OnReceivedRedirect(URLResponsePtr response, |
+ const String& new_url, |
+ const String& new_method) OVERRIDE { |
+ } |
+ virtual void OnReceivedResponse(URLResponsePtr response) OVERRIDE; |
+ virtual void OnReceivedError(NetworkErrorPtr error) OVERRIDE { |
+ ScheduleDestroy(); |
+ } |
+ virtual void OnReceivedEndOfResponseBody() OVERRIDE { |
+ ScheduleDestroy(); |
+ } |
+ |
+ std::string GetContentType(const Array<String>& headers) { |
+ for (size_t i = 0; i < headers.size(); ++i) { |
+ base::StringTokenizer t(headers[i], ": ;="); |
+ while (t.GetNext()) { |
+ if (!t.token_is_delim() && t.token() == "Content-Type") { |
+ while (t.GetNext()) { |
+ if (!t.token_is_delim()) |
+ return t.token(); |
+ } |
+ } |
+ } |
+ } |
+ return ""; |
+ } |
+ |
+ void ScheduleDestroy() { |
+ if (destroy_scheduled_) |
+ return; |
+ destroy_scheduled_ = true; |
+ base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
+ } |
+ |
+ LauncherApp* app_; |
+ bool destroy_scheduled_; |
+ URLLoaderPtr url_loader_; |
+ ScopedDataPipeConsumerHandle response_body_stream_; |
+ LaunchablePtr launchable_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Launch); |
+}; |
+ |
+class LauncherApp : public Application { |
+ public: |
+ LauncherApp() { |
+ handler_map_["text/html"] = "mojo:mojo_html_viewer"; |
+ handler_map_["image/png"] = "mojo:mojo_image_viewer"; |
+ } |
+ virtual ~LauncherApp() {} |
+ |
+ void LaunchURL(const String& url) { |
+ new Launch(this, url); |
+ } |
+ |
+ URLLoaderPtr CreateURLLoader() { |
+ URLLoaderPtr loader; |
+ network_service_->CreateURLLoader(Get(&loader)); |
+ return loader.Pass(); |
+ } |
+ |
+ std::string GetHandlerForContentType(const std::string& content_type) { |
+ HandlerMap::const_iterator it = handler_map_.find(content_type); |
+ return it != handler_map_.end() ? it->second : ""; |
+ } |
+ |
+ private: |
+ typedef std::map<std::string, std::string> HandlerMap; |
+ |
+ // Overridden from Application: |
+ virtual void Initialize() OVERRIDE { |
+ AddService<LauncherConnection>(this); |
+ ConnectTo("mojo:mojo_network_service", &network_service_); |
+ } |
+ |
+ HandlerMap handler_map_; |
+ |
+ NetworkServicePtr network_service_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(LauncherApp); |
+}; |
+ |
+void LauncherConnection::Launch(const String& url) { |
+ app_->LaunchURL(url); |
+} |
+ |
+Launch::Launch(LauncherApp* app, const String& url) |
+ : app_(app), |
+ destroy_scheduled_(false) { |
+ url_loader_ = app_->CreateURLLoader(); |
+ url_loader_.set_client(this); |
+ |
+ URLRequestPtr request(URLRequest::New()); |
+ request->url = url; |
+ request->method = "GET"; |
+ request->auto_follow_redirects = true; |
+ |
+ DataPipe data_pipe; |
+ response_body_stream_ = data_pipe.consumer_handle.Pass(); |
+ |
+ url_loader_->Start(request.Pass(), data_pipe.producer_handle.Pass()); |
+} |
+ |
+void Launch::OnReceivedResponse(URLResponsePtr response) { |
+ std::string content_type = GetContentType(response->headers); |
+ printf("content_type: %s\n", content_type.c_str()); |
+ std::string handler_url = app_->GetHandlerForContentType(content_type); |
+ if (!handler_url.empty()) { |
+ app_->ConnectTo(handler_url, &launchable_); |
+ launchable_->OnLaunch(response.Pass(), response_body_stream_.Pass()); |
+ } |
+ ScheduleDestroy(); |
+} |
+ |
+} // namespace launcher |
+ |
+// static |
+Application* Application::Create() { |
+ return new launcher::LauncherApp; |
+} |
+ |
+} // namespace mojo |