blob: 3905f868cbffb364e8ab470912d6ad40143d212b [file] [log] [blame]
// Copyright 2015 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 "components/html_viewer/document_resource_waiter.h"
#include "components/html_viewer/global_state.h"
#include "components/html_viewer/html_document.h"
#include "components/html_viewer/html_frame_tree_manager.h"
#include "components/mus/public/cpp/view.h"
using web_view::mojom::ViewConnectType;
namespace html_viewer {
DocumentResourceWaiter::DocumentResourceWaiter(GlobalState* global_state,
mojo::URLResponsePtr response,
HTMLDocument* document)
: global_state_(global_state),
document_(document),
response_(response.Pass()),
root_(nullptr),
change_id_(0u),
view_id_(0u),
view_connect_type_(web_view::mojom::VIEW_CONNECT_TYPE_USE_NEW),
frame_client_binding_(this),
is_ready_(false),
waiting_for_change_id_(false),
target_frame_tree_(nullptr) {}
DocumentResourceWaiter::~DocumentResourceWaiter() {
if (root_)
root_->RemoveObserver(this);
if (target_frame_tree_)
target_frame_tree_->RemoveObserver(this);
}
void DocumentResourceWaiter::Release(
mojo::InterfaceRequest<web_view::mojom::FrameClient>* frame_client_request,
web_view::mojom::FramePtr* frame,
mojo::Array<web_view::mojom::FrameDataPtr>* frame_data,
uint32_t* change_id,
uint32_t* view_id,
ViewConnectType* view_connect_type,
OnConnectCallback* on_connect_callback) {
DCHECK(is_ready_);
*frame_client_request = frame_client_request_.Pass();
*frame = frame_.Pass();
*frame_data = frame_data_.Pass();
*change_id = change_id_;
*view_id = view_id_;
*view_connect_type = view_connect_type_;
*on_connect_callback = on_connect_callback_;
}
mojo::URLResponsePtr DocumentResourceWaiter::ReleaseURLResponse() {
return response_.Pass();
}
void DocumentResourceWaiter::SetRoot(mus::View* root) {
DCHECK(!root_);
root_ = root;
root_->AddObserver(this);
UpdateIsReady();
}
void DocumentResourceWaiter::Bind(
mojo::InterfaceRequest<web_view::mojom::FrameClient> request) {
if (frame_client_binding_.is_bound() || !frame_data_.is_null()) {
DVLOG(1) << "Request for FrameClient after already supplied one";
return;
}
frame_client_binding_.Bind(request.Pass());
}
void DocumentResourceWaiter::UpdateIsReady() {
if (is_ready_)
return;
// See description of |waiting_for_change_id_| for details.
if (waiting_for_change_id_) {
if (target_frame_tree_->change_id() == change_id_) {
is_ready_ = true;
waiting_for_change_id_ = false;
document_->Load();
}
return;
}
// The first portion of ready is when we have received OnConnect()
// (|frame_data_| is valid) and we have a view with valid metrics. The view
// is not necessary is ViewConnectType is USE_EXISTING, which means the
// application is not asked for a ViewTreeClient. The metrics are necessary
// to initialize ResourceBundle. If USE_EXISTING is true, it means a View has
// already been provided to another HTMLDocument and there is no need to wait
// for metrics.
bool is_ready =
(!frame_data_.is_null() &&
((view_connect_type_ ==
web_view::mojom::VIEW_CONNECT_TYPE_USE_EXISTING) ||
(root_ && root_->viewport_metrics().device_pixel_ratio != 0.0f)));
if (is_ready) {
HTMLFrameTreeManager* frame_tree =
HTMLFrameTreeManager::FindFrameTreeWithRoot(frame_data_[0]->frame_id);
// Once we've received OnConnect() and the view (if necessary), we determine
// which HTMLFrameTreeManager the new frame ends up in. If there is an
// existing HTMLFrameTreeManager then we must wait for the change_id
// supplied to OnConnect() to be <= that of the HTMLFrameTreeManager's
// change_id. If we did not wait for the change id to be <= then the
// structure of the tree is not in the expected state and it's possible the
// frame communicated in OnConnect() does not exist yet.
if (frame_tree && change_id_ > frame_tree->change_id()) {
waiting_for_change_id_ = true;
target_frame_tree_ = frame_tree;
target_frame_tree_->AddObserver(this);
} else {
is_ready_ = true;
document_->Load();
}
}
}
void DocumentResourceWaiter::OnConnect(
web_view::mojom::FramePtr frame,
uint32_t change_id,
uint32_t view_id,
ViewConnectType view_connect_type,
mojo::Array<web_view::mojom::FrameDataPtr> frame_data,
const OnConnectCallback& callback) {
DCHECK(frame_data_.is_null());
change_id_ = change_id;
view_id_ = view_id;
view_connect_type_ = view_connect_type;
frame_ = frame.Pass();
frame_data_ = frame_data.Pass();
on_connect_callback_ = callback;
CHECK(frame_data_.size() > 0u);
frame_client_request_ = frame_client_binding_.Unbind();
UpdateIsReady();
}
void DocumentResourceWaiter::OnFrameAdded(
uint32_t change_id,
web_view::mojom::FrameDataPtr frame_data) {
// It is assumed we receive OnConnect() (which unbinds) before anything else.
NOTREACHED();
}
void DocumentResourceWaiter::OnFrameRemoved(uint32_t change_id,
uint32_t frame_id) {
// It is assumed we receive OnConnect() (which unbinds) before anything else.
NOTREACHED();
}
void DocumentResourceWaiter::OnFrameClientPropertyChanged(
uint32_t frame_id,
const mojo::String& name,
mojo::Array<uint8_t> new_value) {
// It is assumed we receive OnConnect() (which unbinds) before anything else.
NOTREACHED();
}
void DocumentResourceWaiter::OnPostMessageEvent(
uint32_t source_frame_id,
uint32_t target_frame_id,
web_view::mojom::HTMLMessageEventPtr event) {
// It is assumed we receive OnConnect() (which unbinds) before anything else.
NOTREACHED();
}
void DocumentResourceWaiter::OnWillNavigate(
const mojo::String& origin,
const OnWillNavigateCallback& callback) {
// It is assumed we receive OnConnect() (which unbinds) before anything else.
NOTREACHED();
}
void DocumentResourceWaiter::OnFrameLoadingStateChanged(uint32_t frame_id,
bool loading) {
// It is assumed we receive OnConnect() (which unbinds) before anything else.
NOTREACHED();
}
void DocumentResourceWaiter::OnDispatchFrameLoadEvent(uint32_t frame_id) {
// It is assumed we receive OnConnect() (which unbinds) before anything else.
NOTREACHED();
}
void DocumentResourceWaiter::OnViewViewportMetricsChanged(
mus::View* view,
const mojo::ViewportMetrics& old_metrics,
const mojo::ViewportMetrics& new_metrics) {
UpdateIsReady();
}
void DocumentResourceWaiter::OnViewDestroyed(mus::View* view) {
root_->RemoveObserver(this);
root_ = nullptr;
}
void DocumentResourceWaiter::OnHTMLFrameTreeManagerChangeIdAdvanced() {
UpdateIsReady();
}
void DocumentResourceWaiter::OnHTMLFrameTreeManagerDestroyed() {
document_->Destroy(); // This destroys us.
}
} // namespace html_viewer