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"
8 #include "base/command_line.h"
9 #include "components/html_viewer/global_state.h"
10 #include "components/html_viewer/html_document_oopif.h"
11 #include "components/html_viewer/html_viewer_switches.h"
12 #include "mojo/application/public/cpp/application_connection.h"
13 #include "mojo/application/public/cpp/application_delegate.h"
14 #include "mojo/application/public/cpp/connect.h"
16 namespace html_viewer
{
21 return base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kOOPIF
);
24 HTMLDocument
* CreateHTMLDocument(HTMLDocument::CreateParams
* params
) {
25 return new HTMLDocument(params
);
30 // ServiceConnectorQueue records all incoming service requests and processes
31 // them once PushRequestsTo() is called. This is useful if you need to delay
32 // processing incoming service requests.
33 class HTMLDocumentApplicationDelegate::ServiceConnectorQueue
34 : public mojo::ServiceConnector
{
36 ServiceConnectorQueue() {}
37 ~ServiceConnectorQueue() override
{}
39 void PushRequestsTo(mojo::ApplicationConnection
* connection
) {
40 ScopedVector
<Request
> requests
;
41 requests_
.swap(requests
);
42 for (Request
* request
: requests
) {
43 connection
->GetLocalServiceProvider()->ConnectToService(
44 request
->interface_name
, request
->handle
.Pass());
50 std::string interface_name
;
51 mojo::ScopedMessagePipeHandle handle
;
54 // mojo::ServiceConnector:
55 void ConnectToService(mojo::ApplicationConnection
* application_connection
,
56 const std::string
& interface_name
,
57 mojo::ScopedMessagePipeHandle handle
) override
{
58 scoped_ptr
<Request
> request(new Request
);
59 request
->interface_name
= interface_name
;
60 request
->handle
= handle
.Pass();
61 requests_
.push_back(request
.Pass());
64 ScopedVector
<Request
> requests_
;
66 DISALLOW_COPY_AND_ASSIGN(ServiceConnectorQueue
);
69 HTMLDocumentApplicationDelegate::HTMLDocumentApplicationDelegate(
70 mojo::InterfaceRequest
<mojo::Application
> request
,
71 mojo::URLResponsePtr response
,
72 GlobalState
* global_state
,
73 scoped_ptr
<mojo::AppRefCount
> parent_app_refcount
)
76 base::Bind(&HTMLDocumentApplicationDelegate::OnTerminate
,
77 base::Unretained(this))),
78 parent_app_refcount_(parent_app_refcount
.Pass()),
80 initial_response_(response
.Pass()),
81 global_state_(global_state
),
82 html_document_creation_callback_(base::Bind(CreateHTMLDocument
)) {
85 HTMLDocumentApplicationDelegate::~HTMLDocumentApplicationDelegate() {
86 // Deleting the documents is going to trigger a callback to
87 // OnHTMLDocumentDeleted() and remove from |documents_|. Copy the set so we
88 // don't have to worry about the set being modified out from under us.
89 std::set
<HTMLDocument
*> documents(documents_
);
90 for (HTMLDocument
* doc
: documents
)
92 DCHECK(documents_
.empty());
94 std::set
<HTMLDocumentOOPIF
*> documents2(documents2_
);
95 for (HTMLDocumentOOPIF
* doc
: documents2
)
97 DCHECK(documents2_
.empty());
100 void HTMLDocumentApplicationDelegate::SetHTMLDocumentCreationCallback(
101 const HTMLDocumentCreationCallback
& callback
) {
102 html_document_creation_callback_
= callback
;
105 // Callback from the quit closure. We key off this rather than
106 // ApplicationDelegate::Quit() as we don't want to shut down the messageloop
107 // when we quit (the messageloop is shared among multiple
108 // HTMLDocumentApplicationDelegates).
109 void HTMLDocumentApplicationDelegate::OnTerminate() {
113 // ApplicationDelegate;
114 void HTMLDocumentApplicationDelegate::Initialize(mojo::ApplicationImpl
* app
) {
115 mojo::URLRequestPtr
request(mojo::URLRequest::New());
116 request
->url
= mojo::String::From("mojo:network_service");
117 mojo::ApplicationConnection
* connection
=
118 app_
.ConnectToApplication(request
.Pass());
119 connection
->ConnectToService(&network_service_
);
120 connection
->ConnectToService(&url_loader_factory_
);
123 bool HTMLDocumentApplicationDelegate::ConfigureIncomingConnection(
124 mojo::ApplicationConnection
* connection
) {
125 if (initial_response_
) {
126 OnResponseReceived(mojo::URLLoaderPtr(), connection
, nullptr,
127 initial_response_
.Pass());
129 // HTMLDocument provides services, but is created asynchronously. Queue up
130 // requests until the HTMLDocument is created.
131 scoped_ptr
<ServiceConnectorQueue
> service_connector_queue(
132 new ServiceConnectorQueue
);
133 connection
->SetServiceConnector(service_connector_queue
.get());
135 mojo::URLLoaderPtr loader
;
136 url_loader_factory_
->CreateURLLoader(GetProxy(&loader
));
137 mojo::URLRequestPtr
request(mojo::URLRequest::New());
139 request
->auto_follow_redirects
= true;
141 // |loader| will be passed to the OnResponseReceived method through a
142 // callback. Because order of evaluation is undefined, a reference to the
143 // raw pointer is needed.
144 mojo::URLLoader
* raw_loader
= loader
.get();
147 base::Bind(&HTMLDocumentApplicationDelegate::OnResponseReceived
,
148 base::Unretained(this), base::Passed(&loader
), connection
,
149 base::Passed(&service_connector_queue
)));
154 void HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted(
155 HTMLDocument
* document
) {
156 DCHECK(documents_
.count(document
) > 0);
157 documents_
.erase(document
);
160 void HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted2(
161 HTMLDocumentOOPIF
* document
) {
162 DCHECK(documents2_
.count(document
) > 0);
163 documents2_
.erase(document
);
166 void HTMLDocumentApplicationDelegate::OnResponseReceived(
167 mojo::URLLoaderPtr loader
,
168 mojo::ApplicationConnection
* connection
,
169 scoped_ptr
<ServiceConnectorQueue
> connector_queue
,
170 mojo::URLResponsePtr response
) {
171 // HTMLDocument is destroyed when the hosting view is destroyed, or
172 // explicitly from our destructor.
173 if (EnableOOPIFs()) {
174 HTMLDocumentOOPIF
* document
= new HTMLDocumentOOPIF(
175 &app_
, connection
, response
.Pass(), global_state_
,
176 base::Bind(&HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted2
,
177 base::Unretained(this)));
178 documents2_
.insert(document
);
180 HTMLDocument::CreateParams
params(
181 &app_
, connection
, response
.Pass(), global_state_
,
182 base::Bind(&HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted
,
183 base::Unretained(this)));
184 HTMLDocument
* document
= html_document_creation_callback_
.Run(¶ms
);
185 documents_
.insert(document
);
188 if (connector_queue
) {
189 connector_queue
->PushRequestsTo(connection
);
190 connection
->SetServiceConnector(nullptr);
194 } // namespace html_viewer