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.h"
11 #include "components/html_viewer/html_document_oopif.h"
12 #include "components/html_viewer/html_viewer_switches.h"
13 #include "mojo/application/public/cpp/application_connection.h"
14 #include "mojo/application/public/cpp/application_delegate.h"
15 #include "mojo/application/public/cpp/connect.h"
17 namespace html_viewer
{
22 return base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kOOPIF
);
27 // ServiceConnectorQueue records all incoming service requests and processes
28 // them once PushRequestsTo() is called. This is useful if you need to delay
29 // processing incoming service requests.
30 class HTMLDocumentApplicationDelegate::ServiceConnectorQueue
31 : public mojo::ServiceConnector
{
33 ServiceConnectorQueue() {}
34 ~ServiceConnectorQueue() override
{}
36 void PushRequestsTo(mojo::ApplicationConnection
* connection
) {
37 ScopedVector
<Request
> requests
;
38 requests_
.swap(requests
);
39 for (Request
* request
: requests
) {
40 connection
->GetLocalServiceProvider()->ConnectToService(
41 request
->interface_name
, request
->handle
.Pass());
47 std::string interface_name
;
48 mojo::ScopedMessagePipeHandle handle
;
51 // mojo::ServiceConnector:
52 void ConnectToService(mojo::ApplicationConnection
* application_connection
,
53 const std::string
& interface_name
,
54 mojo::ScopedMessagePipeHandle handle
) override
{
55 scoped_ptr
<Request
> request(new Request
);
56 request
->interface_name
= interface_name
;
57 request
->handle
= handle
.Pass();
58 requests_
.push_back(request
.Pass());
61 ScopedVector
<Request
> requests_
;
63 DISALLOW_COPY_AND_ASSIGN(ServiceConnectorQueue
);
66 HTMLDocumentApplicationDelegate::HTMLDocumentApplicationDelegate(
67 mojo::InterfaceRequest
<mojo::Application
> request
,
68 mojo::URLResponsePtr response
,
69 GlobalState
* global_state
,
70 scoped_ptr
<mojo::AppRefCount
> parent_app_refcount
)
73 base::Bind(&HTMLDocumentApplicationDelegate::OnTerminate
,
74 base::Unretained(this))),
75 parent_app_refcount_(parent_app_refcount
.Pass()),
77 initial_response_(response
.Pass()),
78 global_state_(global_state
) {
81 HTMLDocumentApplicationDelegate::~HTMLDocumentApplicationDelegate() {
82 // Deleting the documents is going to trigger a callback to
83 // OnHTMLDocumentDeleted() and remove from |documents_|. Copy the set so we
84 // don't have to worry about the set being modified out from under us.
85 std::set
<HTMLDocument
*> documents(documents_
);
86 for (HTMLDocument
* doc
: documents
)
88 DCHECK(documents_
.empty());
90 std::set
<HTMLDocumentOOPIF
*> documents2(documents2_
);
91 for (HTMLDocumentOOPIF
* doc
: documents2
)
93 DCHECK(documents2_
.empty());
96 // Callback from the quit closure. We key off this rather than
97 // ApplicationDelegate::Quit() as we don't want to shut down the messageloop
98 // when we quit (the messageloop is shared among multiple
99 // HTMLDocumentApplicationDelegates).
100 void HTMLDocumentApplicationDelegate::OnTerminate() {
104 // ApplicationDelegate;
105 void HTMLDocumentApplicationDelegate::Initialize(mojo::ApplicationImpl
* app
) {
106 mojo::URLRequestPtr
request(mojo::URLRequest::New());
107 request
->url
= mojo::String::From("mojo:network_service");
108 mojo::ApplicationConnection
* connection
=
109 app_
.ConnectToApplication(request
.Pass());
110 connection
->ConnectToService(&network_service_
);
111 connection
->ConnectToService(&url_loader_factory_
);
114 bool HTMLDocumentApplicationDelegate::ConfigureIncomingConnection(
115 mojo::ApplicationConnection
* connection
) {
116 if (initial_response_
) {
117 OnResponseReceived(mojo::URLLoaderPtr(), connection
, nullptr,
118 initial_response_
.Pass());
120 // HTMLDocument provides services, but is created asynchronously. Queue up
121 // requests until the HTMLDocument is created.
122 scoped_ptr
<ServiceConnectorQueue
> service_connector_queue(
123 new ServiceConnectorQueue
);
124 connection
->SetServiceConnector(service_connector_queue
.get());
126 mojo::URLLoaderPtr loader
;
127 url_loader_factory_
->CreateURLLoader(GetProxy(&loader
));
128 mojo::URLRequestPtr
request(mojo::URLRequest::New());
130 request
->auto_follow_redirects
= true;
132 // |loader| will be passed to the OnResponseReceived method through a
133 // callback. Because order of evaluation is undefined, a reference to the
134 // raw pointer is needed.
135 mojo::URLLoader
* raw_loader
= loader
.get();
138 base::Bind(&HTMLDocumentApplicationDelegate::OnResponseReceived
,
139 base::Unretained(this), base::Passed(&loader
), connection
,
140 base::Passed(&service_connector_queue
)));
145 void HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted(
146 HTMLDocument
* document
) {
147 DCHECK(documents_
.count(document
) > 0);
148 documents_
.erase(document
);
151 void HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted2(
152 HTMLDocumentOOPIF
* document
) {
153 DCHECK(documents2_
.count(document
) > 0);
154 documents2_
.erase(document
);
157 void HTMLDocumentApplicationDelegate::OnResponseReceived(
158 mojo::URLLoaderPtr loader
,
159 mojo::ApplicationConnection
* connection
,
160 scoped_ptr
<ServiceConnectorQueue
> connector_queue
,
161 mojo::URLResponsePtr response
) {
162 // HTMLDocument is destroyed when the hosting view is destroyed, or
163 // explicitly from our destructor.
164 if (EnableOOPIFs()) {
165 HTMLDocumentOOPIF
* document
= new HTMLDocumentOOPIF(
166 &app_
, connection
, response
.Pass(), global_state_
,
167 base::Bind(&HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted2
,
168 base::Unretained(this)));
169 documents2_
.insert(document
);
171 HTMLDocument::CreateParams
params(
172 &app_
, connection
, response
.Pass(), global_state_
,
173 base::Bind(&HTMLDocumentApplicationDelegate::OnHTMLDocumentDeleted
,
174 base::Unretained(this)));
175 HTMLDocument
* document
= new HTMLDocument(¶ms
);
176 documents_
.insert(document
);
179 if (connector_queue
) {
180 connector_queue
->PushRequestsTo(connection
);
181 connection
->SetServiceConnector(nullptr);
185 } // namespace html_viewer