Don't preload rarely seen large images
[chromium-blink-merge.git] / components / html_viewer / html_document_application_delegate.cc
blobafb82505ffb22df7f32269dbdbbd9c5cdc3089e4
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 "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 {
19 namespace {
21 bool EnableOOPIFs() {
22 return base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kOOPIF);
25 } // namespace
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 {
32 public:
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());
45 private:
46 struct Request {
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)
71 : app_(this,
72 request.Pass(),
73 base::Bind(&HTMLDocumentApplicationDelegate::OnTerminate,
74 base::Unretained(this))),
75 parent_app_refcount_(parent_app_refcount.Pass()),
76 url_(response->url),
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)
87 doc->Destroy();
88 DCHECK(documents_.empty());
90 std::set<HTMLDocumentOOPIF*> documents2(documents2_);
91 for (HTMLDocumentOOPIF* doc : documents2)
92 doc->Destroy();
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() {
101 delete this;
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());
119 } else {
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());
129 request->url = url_;
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();
136 raw_loader->Start(
137 request.Pass(),
138 base::Bind(&HTMLDocumentApplicationDelegate::OnResponseReceived,
139 base::Unretained(this), base::Passed(&loader), connection,
140 base::Passed(&service_connector_queue)));
142 return true;
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);
170 } else {
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(&params);
176 documents_.insert(document);
179 if (connector_queue) {
180 connector_queue->PushRequestsTo(connection);
181 connection->SetServiceConnector(nullptr);
185 } // namespace html_viewer