Roll src/third_party/WebKit c63b89c:29324ab (svn 202546:202547)
[chromium-blink-merge.git] / components / html_viewer / html_document_application_delegate.cc
blobe57b857126da81a20c3cda62f8476c236be32a22
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/html_viewer/html_document_application_delegate.h"
7 #include "base/bind.h"
8 #include "components/html_viewer/global_state.h"
9 #include "components/html_viewer/html_document.h"
10 #include "mojo/application/public/cpp/application_connection.h"
11 #include "mojo/application/public/cpp/application_delegate.h"
12 #include "mojo/application/public/cpp/connect.h"
14 namespace html_viewer {
16 // ServiceConnectorQueue records all incoming service requests and processes
17 // them once PushRequestsTo() is called. This is useful if you need to delay
18 // processing incoming service requests.
19 class HTMLDocumentApplicationDelegate::ServiceConnectorQueue
20 : public mojo::ServiceConnector {
21 public:
22 ServiceConnectorQueue() {}
23 ~ServiceConnectorQueue() override {}
25 void PushRequestsTo(mojo::ApplicationConnection* connection) {
26 ScopedVector<Request> requests;
27 requests_.swap(requests);
28 for (Request* request : requests) {
29 connection->GetLocalServiceProvider()->ConnectToService(
30 request->interface_name, request->handle.Pass());
34 private:
35 struct Request {
36 std::string interface_name;
37 mojo::ScopedMessagePipeHandle handle;
40 // mojo::ServiceConnector:
41 void ConnectToService(mojo::ApplicationConnection* application_connection,
42 const std::string& interface_name,
43 mojo::ScopedMessagePipeHandle handle) override {
44 scoped_ptr<Request> request(new Request);
45 request->interface_name = interface_name;
46 request->handle = handle.Pass();
47 requests_.push_back(request.Pass());
50 ScopedVector<Request> requests_;
52 DISALLOW_COPY_AND_ASSIGN(ServiceConnectorQueue);
55 HTMLDocumentApplicationDelegate::HTMLDocumentApplicationDelegate(
56 mojo::InterfaceRequest<mojo::Application> request,
57 mojo::URLResponsePtr response,
58 GlobalState* global_state,
59 scoped_ptr<mojo::AppRefCount> parent_app_refcount)
60 : app_(this,
61 request.Pass(),
62 base::Bind(&HTMLDocumentApplicationDelegate::OnTerminate,
63 base::Unretained(this))),
64 parent_app_refcount_(parent_app_refcount.Pass()),
65 url_(response->url),
66 initial_response_(response.Pass()),
67 global_state_(global_state),
68 html_factory_(this),
69 weak_factory_(this) {}
71 HTMLDocumentApplicationDelegate::~HTMLDocumentApplicationDelegate() {
72 // Deleting the documents is going to trigger a callback to
73 // OnHTMLDocumentDeleted() and remove from |documents_|. Copy the set so we
74 // don't have to worry about the set being modified out from under us.
75 std::set<HTMLDocument*> documents2(documents2_);
76 for (HTMLDocument* doc : documents2)
77 doc->Destroy();
78 DCHECK(documents2_.empty());
81 // Callback from the quit closure. We key off this rather than
82 // ApplicationDelegate::Quit() as we don't want to shut down the messageloop
83 // when we quit (the messageloop is shared among multiple
84 // HTMLDocumentApplicationDelegates).
85 void HTMLDocumentApplicationDelegate::OnTerminate() {
86 delete this;
89 // ApplicationDelegate;
90 void HTMLDocumentApplicationDelegate::Initialize(mojo::ApplicationImpl* app) {
91 mojo::URLRequestPtr request(mojo::URLRequest::New());
92 request->url = mojo::String::From("mojo:network_service");
93 scoped_ptr<mojo::ApplicationConnection> connection =
94 app_.ConnectToApplication(request.Pass());
95 connection->ConnectToService(&url_loader_factory_);
98 bool HTMLDocumentApplicationDelegate::ConfigureIncomingConnection(
99 mojo::ApplicationConnection* connection) {
100 if (initial_response_) {
101 OnResponseReceived(nullptr, mojo::URLLoaderPtr(), connection, nullptr,
102 initial_response_.Pass());
103 } else if (url_ == "about:blank") {
104 // This is a little unfortunate. At the browser side, when starting a new
105 // app for "about:blank", the application manager uses
106 // mojo::runner::AboutFetcher to construct a response for "about:blank".
107 // However, when an app for "about:blank" already exists, it is reused and
108 // we end up here. We cannot fetch the URL using mojo::URLLoader because it
109 // is not an actual Web resource.
110 // TODO(yzshen): find out a better approach.
111 mojo::URLResponsePtr response(mojo::URLResponse::New());
112 response->url = url_;
113 response->status_code = 200;
114 response->mime_type = "text/html";
115 OnResponseReceived(nullptr, mojo::URLLoaderPtr(), connection, nullptr,
116 response.Pass());
117 } else {
118 // HTMLDocument provides services, but is created asynchronously. Queue up
119 // requests until the HTMLDocument is created.
120 scoped_ptr<ServiceConnectorQueue> service_connector_queue(
121 new ServiceConnectorQueue);
122 connection->SetServiceConnector(service_connector_queue.get());
124 mojo::URLLoaderPtr loader;
125 url_loader_factory_->CreateURLLoader(GetProxy(&loader));
126 mojo::URLRequestPtr request(mojo::URLRequest::New());
127 request->url = url_;
128 request->auto_follow_redirects = true;
130 // |loader| will be passed to the OnResponseReceived method through a
131 // callback. Because order of evaluation is undefined, a reference to the
132 // raw pointer is needed.
133 mojo::URLLoader* raw_loader = loader.get();
134 // The app needs to stay alive while waiting for the response to be
135 // available.
136 scoped_ptr<mojo::AppRefCount> app_retainer(
137 app_.app_lifetime_helper()->CreateAppRefCount());
138 raw_loader->Start(
139 request.Pass(),
140 base::Bind(&HTMLDocumentApplicationDelegate::OnResponseReceived,
141 weak_factory_.GetWeakPtr(), base::Passed(&app_retainer),
142 base::Passed(&loader), connection,
143 base::Passed(&service_connector_queue)));
145 return true;
148 void HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted2(
149 HTMLDocument* document) {
150 DCHECK(documents2_.count(document) > 0);
151 documents2_.erase(document);
154 void HTMLDocumentApplicationDelegate::OnResponseReceived(
155 scoped_ptr<mojo::AppRefCount> app_refcount,
156 mojo::URLLoaderPtr loader,
157 mojo::ApplicationConnection* connection,
158 scoped_ptr<ServiceConnectorQueue> connector_queue,
159 mojo::URLResponsePtr response) {
160 // HTMLDocument is destroyed when the hosting view is destroyed, or
161 // explicitly from our destructor.
162 HTMLDocument* document = new HTMLDocument(
163 &app_, connection, response.Pass(), global_state_,
164 base::Bind(&HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted2,
165 base::Unretained(this)),
166 html_factory_);
167 documents2_.insert(document);
169 if (connector_queue) {
170 connector_queue->PushRequestsTo(connection);
171 connection->SetServiceConnector(nullptr);
175 HTMLFrame* HTMLDocumentApplicationDelegate::CreateHTMLFrame(
176 HTMLFrame::CreateParams* params) {
177 return new HTMLFrame(params);
180 HTMLWidgetRootLocal* HTMLDocumentApplicationDelegate::CreateHTMLWidgetRootLocal(
181 HTMLWidgetRootLocal::CreateParams* params) {
182 return new HTMLWidgetRootLocal(params);
185 } // namespace html_viewer