blob: 895902350dcc244a3438d8d417faa6f5cd83685c [file] [log] [blame]
// Copyright 2016 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 "blimp/engine/session/tab.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "blimp/common/create_blimp_message.h"
#include "blimp/common/proto/blimp_message.pb.h"
#include "blimp/common/proto/render_widget.pb.h"
#include "blimp/common/proto/tab_control.pb.h"
#include "blimp/engine/common/blimp_user_agent.h"
#include "blimp/engine/feature/engine_render_widget_feature.h"
#include "blimp/net/blimp_message_processor.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/renderer_preferences.h"
#include "ui/aura/window.h"
#include "ui/gfx/geometry/size.h"
namespace blimp {
namespace engine {
Tab::Tab(std::unique_ptr<content::WebContents> web_contents,
const int tab_id,
EngineRenderWidgetFeature* render_widget_feature,
BlimpMessageProcessor* navigation_message_sender)
: web_contents_(std::move(web_contents)),
tab_id_(tab_id),
render_widget_feature_(render_widget_feature),
navigation_message_sender_(navigation_message_sender),
page_load_tracker_(web_contents_.get(), this) {
DCHECK(render_widget_feature_);
DCHECK(navigation_message_sender_);
// A Tab is created upon client's request, thus an updated
// user agent info (containing client OS info) is available, and we will use
// that to override user agent string from BlimpContentRendererClient.
web_contents_->SetUserAgentOverride(GetBlimpEngineUserAgent());
render_widget_feature_->SetDelegate(tab_id_, this);
Observe(web_contents_.get());
}
Tab::~Tab() {
render_widget_feature_->RemoveDelegate(tab_id_);
}
void Tab::Resize(float device_pixel_ratio, const gfx::Size& size_in_dips) {
DVLOG(1) << "Resize to " << size_in_dips.ToString() << ", "
<< device_pixel_ratio;
web_contents_->GetNativeView()->SetBounds(gfx::Rect(size_in_dips));
if (web_contents_->GetRenderViewHost() &&
web_contents_->GetRenderViewHost()->GetWidget()) {
web_contents_->GetRenderViewHost()->GetWidget()->WasResized();
}
}
void Tab::LoadUrl(const GURL& url) {
TRACE_EVENT1("blimp", "Tab::LoadUrl", "URL", url.spec());
DVLOG(1) << "Load URL " << url << " in tab " << tab_id_;
if (!url.is_valid()) {
VLOG(1) << "Dropping invalid URL " << url;
return;
}
content::NavigationController::LoadURLParams params(url);
params.transition_type = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
web_contents_->GetController().LoadURLWithParams(params);
web_contents_->Focus();
}
void Tab::GoBack() {
if (!web_contents_->GetController().CanGoBack()) {
DLOG(ERROR) << "Ignoring back in tab " << tab_id_;
return;
}
DVLOG(1) << "Back in tab " << tab_id_;
web_contents_->GetController().GoBack();
}
void Tab::GoForward() {
if (!web_contents_->GetController().CanGoForward()) {
DLOG(ERROR) << "Ignoring forward in tab " << tab_id_;
return;
}
DVLOG(1) << "Forward in tab " << tab_id_;
web_contents_->GetController().GoForward();
}
void Tab::Reload() {
DVLOG(1) << "Reload in tab " << tab_id_;
web_contents_->GetController().Reload(true);
}
void Tab::RenderViewCreated(content::RenderViewHost* render_view_host) {
DCHECK(render_view_host);
web_contents_->GetMutableRendererPrefs()->caret_blink_interval = 0;
render_view_host->SyncRendererPrefs();
render_widget_feature_->OnRenderWidgetCreated(tab_id_,
render_view_host->GetWidget());
}
void Tab::RenderViewHostChanged(content::RenderViewHost* old_host,
content::RenderViewHost* new_host) {
render_widget_feature_->OnRenderWidgetInitialized(tab_id_,
new_host->GetWidget());
}
void Tab::RenderViewDeleted(content::RenderViewHost* render_view_host) {
render_widget_feature_->OnRenderWidgetDeleted(tab_id_,
render_view_host->GetWidget());
}
void Tab::NavigationStateChanged(content::InvalidateTypes changed_flags) {
DCHECK(changed_flags);
NavigationMessage* navigation_message;
std::unique_ptr<BlimpMessage> message =
CreateBlimpMessage(&navigation_message, tab_id_);
navigation_message->set_type(NavigationMessage::NAVIGATION_STATE_CHANGED);
NavigationStateChangeMessage* details =
navigation_message->mutable_navigation_state_changed();
if (changed_flags & content::InvalidateTypes::INVALIDATE_TYPE_URL)
details->set_url(web_contents_->GetURL().spec());
if (changed_flags & content::InvalidateTypes::INVALIDATE_TYPE_TAB) {
// TODO(dtrainor): Serialize the favicon? crbug.com/597094.
DVLOG(3) << "Tab favicon changed";
}
if (changed_flags & content::InvalidateTypes::INVALIDATE_TYPE_TITLE)
details->set_title(base::UTF16ToUTF8(web_contents_->GetTitle()));
if (changed_flags & content::InvalidateTypes::INVALIDATE_TYPE_LOAD)
details->set_loading(web_contents_->IsLoading());
navigation_message_sender_->ProcessMessage(std::move(message),
net::CompletionCallback());
}
void Tab::SendPageLoadStatusUpdate(PageLoadStatus load_status) {
NavigationMessage* navigation_message = nullptr;
std::unique_ptr<BlimpMessage> message =
CreateBlimpMessage(&navigation_message, tab_id_);
navigation_message->set_type(NavigationMessage::NAVIGATION_STATE_CHANGED);
navigation_message->mutable_navigation_state_changed()
->set_page_load_completed(load_status == PageLoadStatus::LOADED);
navigation_message_sender_->ProcessMessage(std::move(message),
net::CompletionCallback());
}
void Tab::OnWebGestureEvent(content::RenderWidgetHost* render_widget_host,
std::unique_ptr<blink::WebGestureEvent> event) {
TRACE_EVENT1("blimp", "Tab::OnWebGestureEvent", "type", event->type);
render_widget_host->ForwardGestureEvent(*event);
}
void Tab::OnCompositorMessageReceived(
content::RenderWidgetHost* render_widget_host,
const std::vector<uint8_t>& message) {
TRACE_EVENT0("blimp", "Tab::OnCompositorMessageReceived");
render_widget_host->HandleCompositorProto(message);
}
} // namespace engine
} // namespace blimp