diff options
author | Andras Becsi <andras.becsi@digia.com> | 2014-03-18 13:16:26 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-03-20 15:55:39 +0100 |
commit | 3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch) | |
tree | 92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/content/browser/browser_plugin | |
parent | e90d7c4b152c56919d963987e2503f9909a666d2 (diff) |
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies
needed on Windows.
Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42
Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu>
Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/content/browser/browser_plugin')
13 files changed, 849 insertions, 538 deletions
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc index 1f673ba520f..18bfc25c3b4 100644 --- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc +++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc @@ -8,6 +8,7 @@ #include "content/browser/browser_plugin/browser_plugin_guest.h" #include "content/browser/browser_plugin/browser_plugin_guest_manager.h" #include "content/browser/browser_plugin/browser_plugin_host_factory.h" +#include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/browser_plugin/browser_plugin_constants.h" #include "content/common/browser_plugin/browser_plugin_messages.h" @@ -16,11 +17,13 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/native_web_keyboard_event.h" +#include "content/public/browser/render_view_host.h" #include "content/public/browser/user_metrics.h" #include "content/public/common/content_switches.h" #include "content/public/common/result_codes.h" #include "content/public/common/url_constants.h" #include "net/base/escape.h" +#include "ui/events/keycodes/keyboard_codes.h" namespace content { @@ -78,15 +81,58 @@ void BrowserPluginEmbedder::GetRenderViewHostAtPosition( ++next_get_render_view_request_id_; } +bool BrowserPluginEmbedder::DidSendScreenRectsCallback( + BrowserPluginGuest* guest) { + static_cast<RenderViewHostImpl*>( + guest->GetWebContents()->GetRenderViewHost())->SendScreenRects(); + // Not handled => Iterate over all guests. + return false; +} + void BrowserPluginEmbedder::DidSendScreenRects() { - GetBrowserPluginGuestManager()->DidSendScreenRects( - static_cast<WebContentsImpl*>(web_contents())); + WebContentsImpl* embedder = + static_cast<WebContentsImpl*>(web_contents()); + GetBrowserPluginGuestManager()->ForEachGuest(embedder, base::Bind( + &BrowserPluginEmbedder::DidSendScreenRectsCallback, + base::Unretained(this))); +} + +bool BrowserPluginEmbedder::UnlockMouseIfNecessaryCallback( + const NativeWebKeyboardEvent& event, + BrowserPluginGuest* guest) { + return guest->UnlockMouseIfNecessary(event); } bool BrowserPluginEmbedder::HandleKeyboardEvent( const NativeWebKeyboardEvent& event) { - return GetBrowserPluginGuestManager()->UnlockMouseIfNecessary( - static_cast<WebContentsImpl*>(web_contents()), event); + if ((event.type != blink::WebInputEvent::RawKeyDown) || + (event.windowsKeyCode != ui::VKEY_ESCAPE) || + (event.modifiers & blink::WebInputEvent::InputModifiers)) { + return false; + } + + WebContentsImpl* embedder = + static_cast<WebContentsImpl*>(web_contents()); + return GetBrowserPluginGuestManager()->ForEachGuest(embedder, base::Bind( + &BrowserPluginEmbedder::UnlockMouseIfNecessaryCallback, + base::Unretained(this), + event)); +} + +bool BrowserPluginEmbedder::SetZoomLevelCallback( + double level, BrowserPluginGuest* guest) { + guest->GetWebContents()->SetZoomLevel(level); + // Not handled => Iterate over all guests. + return false; +} + +void BrowserPluginEmbedder::SetZoomLevel(double level) { + WebContentsImpl* embedder = + static_cast<WebContentsImpl*>(web_contents()); + GetBrowserPluginGuestManager()->ForEachGuest(embedder, base::Bind( + &BrowserPluginEmbedder::SetZoomLevelCallback, + base::Unretained(this), + level)); } void BrowserPluginEmbedder::RenderProcessGone(base::TerminationStatus status) { @@ -109,7 +155,7 @@ bool BrowserPluginEmbedder::OnMessageReceived(const IPC::Message& message) { } void BrowserPluginEmbedder::DragSourceEndedAt(int client_x, int client_y, - int screen_x, int screen_y, WebKit::WebDragOperation operation) { + int screen_x, int screen_y, blink::WebDragOperation operation) { if (guest_started_drag_.get()) { gfx::Point guest_offset = guest_started_drag_->GetScreenCoordinates(gfx::Point()); @@ -177,7 +223,6 @@ void BrowserPluginEmbedder::OnAttach( GetBrowserPluginGuestManager()->GetGuestByInstanceID( instance_id, web_contents()->GetRenderProcessHost()->GetID()); - if (guest) { // There is an implicit order expectation here: // 1. The content embedder is made aware of the attachment. @@ -203,7 +248,7 @@ void BrowserPluginEmbedder::OnAttach( guest->GetWebContents(), web_contents(), extra_params); - guest->Initialize(static_cast<WebContentsImpl*>(web_contents()), params); + guest->Initialize(params, static_cast<WebContentsImpl*>(web_contents())); } } diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.h b/chromium/content/browser/browser_plugin/browser_plugin_embedder.h index 52610632f59..107fa618686 100644 --- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.h +++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.h @@ -67,12 +67,15 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver { factory_ = factory; } + // Sets the zoom level for all guests within this embedder. + void SetZoomLevel(double level); + // WebContentsObserver implementation. virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; void DragSourceEndedAt(int client_x, int client_y, int screen_x, - int screen_y, WebKit::WebDragOperation operation); + int screen_y, blink::WebDragOperation operation); void DragSourceMovedTo(int client_x, int client_y, int screen_x, int screen_y); @@ -98,6 +101,13 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver { BrowserPluginGuestManager* GetBrowserPluginGuestManager(); + bool DidSendScreenRectsCallback(BrowserPluginGuest* guest); + + bool SetZoomLevelCallback(double level, BrowserPluginGuest* guest); + + bool UnlockMouseIfNecessaryCallback(const NativeWebKeyboardEvent& event, + BrowserPluginGuest* guest); + // Message handlers. void OnAllocateInstanceID(int request_id); diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc index 19e7eba3d44..9668d227c51 100644 --- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc @@ -10,7 +10,6 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/browser_plugin/browser_plugin_embedder.h" -#include "content/browser/browser_plugin/browser_plugin_guest_helper.h" #include "content/browser/browser_plugin/browser_plugin_guest_manager.h" #include "content/browser/browser_plugin/browser_plugin_host_factory.h" #include "content/browser/browser_thread_impl.h" @@ -28,15 +27,16 @@ #include "content/common/input_messages.h" #include "content/common/view_messages.h" #include "content/port/browser/render_view_host_delegate_view.h" +#include "content/port/browser/render_widget_host_view_port.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/geolocation_permission_context.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_types.h" +#include "content/public/browser/navigation_controller.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/resource_request_details.h" #include "content/public/browser/user_metrics.h" +#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_view.h" #include "content/public/common/drop_data.h" #include "content/public/common/media_stream_request.h" @@ -44,7 +44,7 @@ #include "content/public/common/url_constants.h" #include "content/public/common/url_utils.h" #include "net/url_request/url_request.h" -#include "third_party/WebKit/public/web/WebCursorInfo.h" +#include "third_party/WebKit/public/platform/WebCursorInfo.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/surface/transport_dib.h" #include "webkit/common/resource_type.h" @@ -64,6 +64,9 @@ class BrowserPluginGuest::PermissionRequest : public base::RefCounted<BrowserPluginGuest::PermissionRequest> { public: virtual void Respond(bool should_allow, const std::string& user_input) = 0; + virtual bool AllowedByDefault() const { + return false; + } protected: PermissionRequest() { RecordAction(UserMetricsAction("BrowserPlugin.Guest.PermissionRequest")); @@ -193,7 +196,7 @@ class BrowserPluginGuest::NewWindowRequest : public PermissionRequest { guest_->GetWebContents()->GetBrowserPluginGuestManager()-> GetGuestByInstanceID(instance_id_, embedder_render_process_id); if (!guest) { - LOG(INFO) << "Guest not found. Instance ID: " << instance_id_; + VLOG(0) << "Guest not found. Instance ID: " << instance_id_; return; } @@ -213,8 +216,7 @@ class BrowserPluginGuest::JavaScriptDialogRequest : public PermissionRequest { JavaScriptDialogRequest(const DialogClosedCallback& callback) : callback_(callback) { RecordAction( - UserMetricsAction( - "BrowserPlugin.Guest.PermissionRequest.JavaScriptDialog")); + UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.JSDialog")); } virtual void Respond(bool should_allow, @@ -247,8 +249,6 @@ class BrowserPluginGuest::PointerLockRequest : public PermissionRequest { }; namespace { -const size_t kNumMaxOutstandingPermissionRequests = 1024; - std::string WindowOpenDispositionToString( WindowOpenDisposition window_open_disposition) { switch (window_open_disposition) { @@ -298,40 +298,46 @@ static std::string RetrieveDownloadURLFromRequestId( ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id); if (url_request) return url_request->url().possibly_invalid_spec(); - return std::string(); + return ""; } } // namespace -class BrowserPluginGuest::EmbedderRenderViewHostObserver - : public RenderViewHostObserver { +class BrowserPluginGuest::EmbedderWebContentsObserver + : public WebContentsObserver { public: - explicit EmbedderRenderViewHostObserver(BrowserPluginGuest* guest) - : RenderViewHostObserver( - guest->embedder_web_contents()->GetRenderViewHost()), + explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest) + : WebContentsObserver(guest->embedder_web_contents()), browser_plugin_guest_(guest) { } - virtual ~EmbedderRenderViewHostObserver() { + virtual ~EmbedderWebContentsObserver() { } - // RenderViewHostObserver: - virtual void RenderViewHostDestroyed( - RenderViewHost* render_view_host) OVERRIDE { + // WebContentsObserver: + virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE { browser_plugin_guest_->EmbedderDestroyed(); } + virtual void WasShown() OVERRIDE { + browser_plugin_guest_->EmbedderVisibilityChanged(true); + } + + virtual void WasHidden() OVERRIDE { + browser_plugin_guest_->EmbedderVisibilityChanged(false); + } + private: BrowserPluginGuest* browser_plugin_guest_; - DISALLOW_COPY_AND_ASSIGN(EmbedderRenderViewHostObserver); + DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver); }; BrowserPluginGuest::BrowserPluginGuest( int instance_id, + bool has_render_view, WebContentsImpl* web_contents, - BrowserPluginGuest* opener, - bool has_render_view) + BrowserPluginGuest* opener) : WebContentsObserver(web_contents), weak_ptr_factory_(this), embedder_web_contents_(NULL), @@ -346,6 +352,7 @@ BrowserPluginGuest::BrowserPluginGuest( mouse_locked_(false), pending_lock_request_(false), embedder_visible_(true), + copy_request_id_(0), next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID), has_render_view_(has_render_view), last_seen_auto_size_enabled_(false), @@ -360,9 +367,9 @@ BrowserPluginGuest::BrowserPluginGuest( bool BrowserPluginGuest::AddMessageToConsole(WebContents* source, int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) { + const base::string16& source_id) { if (!delegate_) return false; @@ -382,7 +389,22 @@ void BrowserPluginGuest::DestroyUnattachedWindows() { } // All pending windows should be removed from the set after Destroy() is // called on all of them. - DCHECK_EQ(0ul, pending_new_windows_.size()); + DCHECK(pending_new_windows_.empty()); +} + +void BrowserPluginGuest::LoadURLWithParams(const GURL& url, + const Referrer& referrer, + PageTransition transition_type, + WebContents* web_contents) { + NavigationController::LoadURLParams load_url_params(url); + load_url_params.referrer = referrer; + load_url_params.transition_type = transition_type; + load_url_params.extra_headers = std::string(); + if (delegate_ && delegate_->IsOverridingUserAgent()) { + load_url_params.override_user_agent = + NavigationController::UA_OVERRIDE_TRUE; + } + web_contents->GetController().LoadURLWithParams(load_url_params); } void BrowserPluginGuest::RespondToPermissionRequest( @@ -391,7 +413,7 @@ void BrowserPluginGuest::RespondToPermissionRequest( const std::string& user_input) { RequestMap::iterator request_itr = permission_request_map_.find(request_id); if (request_itr == permission_request_map_.end()) { - LOG(INFO) << "Not a valid request ID."; + VLOG(0) << "Not a valid request ID."; return; } request_itr->second->Respond(should_allow, user_input); @@ -415,9 +437,12 @@ int BrowserPluginGuest::RequestPermission( AsWeakPtr(), request_id); // If BrowserPluginGuestDelegate hasn't handled the permission then we simply - // reject it immediately. - if (!delegate_->RequestPermission(permission_type, request_info, callback)) - callback.Run(false, ""); + // perform the default action (which is one of allow or reject) immediately. + if (!delegate_->RequestPermission( + permission_type, request_info, callback, request->AllowedByDefault())) { + callback.Run(request->AllowedByDefault(), ""); + return browser_plugin::kInvalidPermissionRequestID; + } return request_id; } @@ -454,11 +479,8 @@ BrowserPluginGuest* BrowserPluginGuest::CreateNewGuestWindow( std::make_pair(new_guest, NewWindowInfo(params.url, std::string()))); // Request permission to show the new window. - RequestNewWindowPermission( - new_guest->GetWebContents(), - params.disposition, - gfx::Rect(), - params.user_gesture); + RequestNewWindowPermission(params.disposition, gfx::Rect(), + params.user_gesture, new_guest->GetWebContents()); return new_guest; } @@ -487,21 +509,33 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder( OnSwapBuffersACK) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameACK, OnCompositorFrameACK) + IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck, + OnCopyFromCompositingSurfaceAck) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate, OnDragStatusUpdate) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand, OnExecuteEditCommand) + IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete, + OnExtendSelectionAndDelete) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent, OnHandleInputEvent) + IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition, + OnImeConfirmComposition) + IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition, + OnImeSetComposition) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_NavigateGuest, OnNavigateGuest) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed) + IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources, + OnReclaimCompositorResources) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetSize) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent, OnSetEditCommandsForNextKeyEvent) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetName, OnSetName) + IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque, + OnSetContentsOpaque) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry) @@ -512,10 +546,11 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder( } void BrowserPluginGuest::Initialize( - WebContentsImpl* embedder_web_contents, - const BrowserPluginHostMsg_Attach_Params& params) { + const BrowserPluginHostMsg_Attach_Params& params, + WebContentsImpl* embedder_web_contents) { focused_ = params.focused; guest_visible_ = params.visible; + guest_opaque_ = params.opaque; guest_window_rect_ = params.resize_guest_params.view_rect; if (!params.name.empty()) @@ -532,11 +567,9 @@ void BrowserPluginGuest::Initialize( static_cast<WebContentsViewGuest*>(GetWebContents()->GetView()); new_view->OnGuestInitialized(embedder_web_contents->GetView()); - // |render_view_host| manages the ownership of this BrowserPluginGuestHelper. - new BrowserPluginGuestHelper(this, GetWebContents()->GetRenderViewHost()); - RendererPreferences* renderer_prefs = GetWebContents()->GetMutableRendererPrefs(); + std::string guest_user_agent_override = renderer_prefs->user_agent_override; // Copy renderer preferences (and nothing else) from the embedder's // WebContents to the guest. // @@ -544,6 +577,7 @@ void BrowserPluginGuest::Initialize( // values for caret blinking interval, colors related to selection and // focus. *renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs(); + renderer_prefs->user_agent_override = guest_user_agent_override; // We would like the guest to report changes to frame names so that we can // update the BrowserPlugin's corresponding 'name' attribute. @@ -555,14 +589,7 @@ void BrowserPluginGuest::Initialize( // Disable "client blocked" error page for browser plugin. renderer_prefs->disable_client_blocked_error_page = true; - // Listen to embedder visibility changes so that the guest is in a 'shown' - // state if both the embedder is visible and the BrowserPlugin is marked as - // visible. - notification_registrar_.Add( - this, NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, - Source<WebContents>(embedder_web_contents_)); - - embedder_rvh_observer_.reset(new EmbedderRenderViewHostObserver(this)); + embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this)); OnSetSize(instance_id_, params.auto_size_params, params.resize_guest_params); @@ -575,8 +602,10 @@ void BrowserPluginGuest::Initialize( new BrowserPluginMsg_GuestContentWindowReady(instance_id_, guest_routing_id)); - if (!params.src.empty()) + if (!params.src.empty()) { + // params.src will be validated in BrowserPluginGuest::OnNavigateGuest. OnNavigateGuest(instance_id_, params.src); + } has_render_view_ = true; @@ -606,6 +635,9 @@ void BrowserPluginGuest::Initialize( ack_params.name = name_; SendMessageToEmbedder( new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params)); + + if (delegate_) + delegate_->DidAttach(); } BrowserPluginGuest::~BrowserPluginGuest() { @@ -618,6 +650,7 @@ BrowserPluginGuest::~BrowserPluginGuest() { // static BrowserPluginGuest* BrowserPluginGuest::Create( int instance_id, + SiteInstance* guest_site_instance, WebContentsImpl* web_contents, scoped_ptr<base::DictionaryValue> extra_params) { RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create")); @@ -625,13 +658,13 @@ BrowserPluginGuest* BrowserPluginGuest::Create( if (factory_) { guest = factory_->CreateBrowserPluginGuest(instance_id, web_contents); } else { - guest = new BrowserPluginGuest(instance_id, web_contents, NULL, false); + guest = new BrowserPluginGuest(instance_id, false, web_contents, NULL); } guest->extra_attach_params_.reset(extra_params->DeepCopy()); web_contents->SetBrowserPluginGuest(guest); BrowserPluginGuestDelegate* delegate = NULL; GetContentClient()->browser()->GuestWebContentsCreated( - web_contents, NULL, &delegate, extra_params.Pass()); + guest_site_instance, web_contents, NULL, &delegate, extra_params.Pass()); guest->SetDelegate(delegate); return guest; } @@ -639,15 +672,16 @@ BrowserPluginGuest* BrowserPluginGuest::Create( // static BrowserPluginGuest* BrowserPluginGuest::CreateWithOpener( int instance_id, + bool has_render_view, WebContentsImpl* web_contents, - BrowserPluginGuest* opener, - bool has_render_view) { + BrowserPluginGuest* opener) { BrowserPluginGuest* guest = new BrowserPluginGuest( - instance_id, web_contents, opener, has_render_view); + instance_id, has_render_view, web_contents, opener); web_contents->SetBrowserPluginGuest(guest); BrowserPluginGuestDelegate* delegate = NULL; GetContentClient()->browser()->GuestWebContentsCreated( + opener->GetWebContents()->GetSiteInstance(), web_contents, opener->GetWebContents(), &delegate, scoped_ptr<base::DictionaryValue>()); guest->SetDelegate(delegate); @@ -662,6 +696,16 @@ void BrowserPluginGuest::UpdateVisibility() { OnSetVisibility(instance_id_, visible()); } +void BrowserPluginGuest::CopyFromCompositingSurface( + gfx::Rect src_subrect, + gfx::Size dst_size, + const base::Callback<void(bool, const SkBitmap&)>& callback) { + copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback)); + SendMessageToEmbedder( + new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(), + copy_request_id_, src_subrect, dst_size)); +} + // screen. gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) { gfx::Rect guest_rect(bounds); @@ -669,20 +713,9 @@ gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) { return guest_rect; } -void BrowserPluginGuest::Observe(int type, - const NotificationSource& source, - const NotificationDetails& details) { - switch (type) { - case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: { - DCHECK_EQ(Source<WebContents>(source).ptr(), embedder_web_contents_); - embedder_visible_ = *Details<bool>(details).ptr(); - UpdateVisibility(); - break; - } - default: - NOTREACHED() << "Unexpected notification sent."; - break; - } +void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) { + embedder_visible_ = visible; + UpdateVisibility(); } void BrowserPluginGuest::AddNewContents(WebContents* source, @@ -693,8 +726,8 @@ void BrowserPluginGuest::AddNewContents(WebContents* source, bool* was_blocked) { if (was_blocked) *was_blocked = false; - RequestNewWindowPermission(static_cast<WebContentsImpl*>(new_contents), - disposition, initial_pos, user_gesture); + RequestNewWindowPermission(disposition, initial_pos, user_gesture, + static_cast<WebContentsImpl*>(new_contents)); } void BrowserPluginGuest::CanDownload( @@ -702,12 +735,6 @@ void BrowserPluginGuest::CanDownload( int request_id, const std::string& request_method, const base::Callback<void(bool)>& callback) { - if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) { - // Deny the download request. - callback.Run(false); - return; - } - BrowserThread::PostTaskAndReplyWithResult( BrowserThread::IO, FROM_HERE, base::Bind(&RetrieveDownloadURLFromRequestId, @@ -754,6 +781,9 @@ void BrowserPluginGuest::HandleKeyboardEvent( if (delegate_ && delegate_->HandleKeyboardEvent(event)) return; + if (!embedder_web_contents_->GetDelegate()) + return; + // Send the unhandled keyboard events back to the embedder to reprocess them. // TODO(fsamuel): This introduces the possibility of out-of-order keyboard // events because the guest may be arbitrarily delayed when responding to @@ -783,8 +813,7 @@ WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source, } if (params.disposition == CURRENT_TAB) { // This can happen for cross-site redirects. - source->GetController().LoadURL( - params.url, params.referrer, params.transition, std::string()); + LoadURLWithParams(params.url, params.referrer, params.transition, source); return source; } @@ -793,7 +822,7 @@ WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source, void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents, int64 source_frame_id, - const string16& frame_name, + const base::string16& frame_name, const GURL& target_url, WebContents* new_contents) { WebContentsImpl* new_contents_impl = @@ -825,6 +854,12 @@ void BrowserPluginGuest::RendererResponsive(WebContents* source) { void BrowserPluginGuest::RunFileChooser(WebContents* web_contents, const FileChooserParams& params) { + if (!attached()) + return; + + if (!embedder_web_contents_->GetDelegate()) + return; + embedder_web_contents_->GetDelegate()->RunFileChooser(web_contents, params); } @@ -886,10 +921,10 @@ bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const { } void BrowserPluginGuest::RequestNewWindowPermission( - WebContentsImpl* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_bounds, - bool user_gesture) { + bool user_gesture, + WebContentsImpl* new_contents) { BrowserPluginGuest* guest = new_contents->GetBrowserPluginGuest(); PendingWindowMap::iterator it = pending_new_windows_.find(guest); if (it == pending_new_windows_.end()) @@ -940,7 +975,7 @@ void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) { } void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y, - int screen_x, int screen_y, WebKit::WebDragOperation operation) { + int screen_x, int screen_y, blink::WebDragOperation operation) { web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y, screen_x, screen_y, operation); } @@ -956,9 +991,9 @@ void BrowserPluginGuest::EndSystemDrag() { GetWebContents()->GetRenderViewHost()); guest_rvh->DragSourceSystemDragEnded(); // Issue a MouseUp event to get out of a selection state. - WebKit::WebMouseEvent mouse_event; - mouse_event.type = WebKit::WebInputEvent::MouseUp; - mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; + blink::WebMouseEvent mouse_event; + mouse_event.type = blink::WebInputEvent::MouseUp; + mouse_event.button = blink::WebMouseEvent::ButtonLeft; guest_rvh->ForwardMouseEvent(mouse_event); } @@ -971,12 +1006,6 @@ void BrowserPluginGuest::AskEmbedderForGeolocationPermission( int bridge_id, const GURL& requesting_frame, const GeolocationCallback& callback) { - if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) { - // Deny the geolocation request. - callback.Run(false); - return; - } - base::DictionaryValue request_info; request_info.Set(browser_plugin::kURL, base::Value::CreateStringValue(requesting_frame.spec())); @@ -1031,6 +1060,7 @@ void BrowserPluginGuest::SendQueuedMessages() { void BrowserPluginGuest::DidCommitProvisionalLoadForFrame( int64 frame_id, + const base::string16& frame_unique_name, bool is_main_frame, const GURL& url, PageTransition transition_type, @@ -1047,23 +1077,26 @@ void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) { const char script[] = "window.addEventListener('dragstart', function() { " " window.event.preventDefault(); " "});"; - render_view_host->ExecuteJavascriptInWebFrame(string16(), + render_view_host->ExecuteJavascriptInWebFrame(base::string16(), ASCIIToUTF16(script)); } } void BrowserPluginGuest::RenderViewReady() { + RenderViewHost* rvh = GetWebContents()->GetRenderViewHost(); + // The guest RenderView should always live in a guest process. + CHECK(rvh->GetProcess()->IsGuest()); // TODO(fsamuel): Investigate whether it's possible to update state earlier // here (see http://crbug.com/158151). Send(new InputMsg_SetFocus(routing_id(), focused_)); UpdateVisibility(); - RenderViewHost* rvh = GetWebContents()->GetRenderViewHost(); if (auto_size_enabled_) rvh->EnableAutoResize(min_auto_size_, max_auto_size_); else rvh->DisableAutoResize(damage_view_size_); Send(new ViewMsg_SetName(routing_id(), name_)); + OnSetContentsOpaque(instance_id_, guest_opaque_); RenderWidgetHostImpl::From(rvh)-> set_hung_renderer_delay_ms(guest_hang_timeout_); @@ -1110,26 +1143,31 @@ bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest( switch (message.type()) { case BrowserPluginHostMsg_BuffersSwappedACK::ID: case BrowserPluginHostMsg_CompositorFrameACK::ID: + case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID: case BrowserPluginHostMsg_DragStatusUpdate::ID: case BrowserPluginHostMsg_ExecuteEditCommand::ID: + case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID: case BrowserPluginHostMsg_HandleInputEvent::ID: + case BrowserPluginHostMsg_ImeConfirmComposition::ID: + case BrowserPluginHostMsg_ImeSetComposition::ID: case BrowserPluginHostMsg_LockMouse_ACK::ID: case BrowserPluginHostMsg_NavigateGuest::ID: case BrowserPluginHostMsg_PluginDestroyed::ID: + case BrowserPluginHostMsg_ReclaimCompositorResources::ID: case BrowserPluginHostMsg_ResizeGuest::ID: case BrowserPluginHostMsg_SetAutoSize::ID: case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID: case BrowserPluginHostMsg_SetFocus::ID: case BrowserPluginHostMsg_SetName::ID: + case BrowserPluginHostMsg_SetContentsOpaque::ID: case BrowserPluginHostMsg_SetVisibility::ID: case BrowserPluginHostMsg_UnlockMouse_ACK::ID: case BrowserPluginHostMsg_UpdateGeometry::ID: case BrowserPluginHostMsg_UpdateRect_ACK::ID: return true; default: - break; + return false; } - return false; } bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) { @@ -1147,6 +1185,14 @@ bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) { #endif IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget) IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus) + IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged, + OnTextInputTypeChanged) + IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition, + OnImeCancelComposition) +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) + IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged, + OnImeCompositionRangeChanged) +#endif IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse) IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameName, OnUpdateFrameName) IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect) @@ -1170,7 +1216,7 @@ void BrowserPluginGuest::Attach( params.src.clear(); // If a RenderView has already been created for this new window, then we need - // to initialize the browser-side state now so that the RenderViewHostManager + // to initialize the browser-side state now so that the RenderFrameHostManager // does not create a new RenderView on navigation. if (has_render_view_) { static_cast<RenderViewHostImpl*>( @@ -1203,7 +1249,7 @@ void BrowserPluginGuest::Attach( if (!name_.empty()) params.name.clear(); - Initialize(embedder_web_contents, params); + Initialize(params, embedder_web_contents); SendQueuedMessages(); @@ -1223,29 +1269,29 @@ void BrowserPluginGuest::OnCompositorFrameACK( } void BrowserPluginGuest::OnDragStatusUpdate(int instance_id, - WebKit::WebDragStatus drag_status, + blink::WebDragStatus drag_status, const DropData& drop_data, - WebKit::WebDragOperationsMask mask, + blink::WebDragOperationsMask mask, const gfx::Point& location) { RenderViewHost* host = GetWebContents()->GetRenderViewHost(); switch (drag_status) { - case WebKit::WebDragStatusEnter: + case blink::WebDragStatusEnter: embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest( this); host->DragTargetDragEnter(drop_data, location, location, mask, 0); break; - case WebKit::WebDragStatusOver: + case blink::WebDragStatusOver: host->DragTargetDragOver(location, location, mask, 0); break; - case WebKit::WebDragStatusLeave: + case blink::WebDragStatusLeave: embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this); host->DragTargetDragLeave(); break; - case WebKit::WebDragStatusDrop: + case blink::WebDragStatusDrop: host->DragTargetDrop(location, location, 0); EndSystemDrag(); break; - case WebKit::WebDragStatusUnknown: + case blink::WebDragStatusUnknown: NOTREACHED(); } } @@ -1255,10 +1301,50 @@ void BrowserPluginGuest::OnExecuteEditCommand(int instance_id, Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string())); } +void BrowserPluginGuest::OnImeSetComposition( + int instance_id, + const std::string& text, + const std::vector<blink::WebCompositionUnderline>& underlines, + int selection_start, + int selection_end) { + Send(new ViewMsg_ImeSetComposition(routing_id(), + UTF8ToUTF16(text), underlines, + selection_start, selection_end)); +} + +void BrowserPluginGuest::OnImeConfirmComposition( + int instance_id, + const std::string& text, + bool keep_selection) { + Send(new ViewMsg_ImeConfirmComposition(routing_id(), + UTF8ToUTF16(text), + gfx::Range::InvalidRange(), + keep_selection)); +} + +void BrowserPluginGuest::OnExtendSelectionAndDelete( + int instance_id, + int before, + int after) { + Send(new ViewMsg_ExtendSelectionAndDelete(routing_id(), before, after)); +} + +void BrowserPluginGuest::OnReclaimCompositorResources( + int instance_id, + int route_id, + uint32 output_surface_id, + int renderer_host_id, + const cc::CompositorFrameAck& ack) { + RenderWidgetHostImpl::SendReclaimCompositorResources(route_id, + output_surface_id, + renderer_host_id, + ack); +} + void BrowserPluginGuest::OnHandleInputEvent( int instance_id, const gfx::Rect& guest_window_rect, - const WebKit::WebInputEvent* event) { + const blink::WebInputEvent* event) { guest_window_rect_ = guest_window_rect; // If the embedder's RWHV is destroyed then that means that the embedder's // window has been closed but the embedder's WebContents has not yet been @@ -1273,19 +1359,19 @@ void BrowserPluginGuest::OnHandleInputEvent( RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>( GetWebContents()->GetRenderViewHost()); - if (WebKit::WebInputEvent::isMouseEventType(event->type)) { + if (blink::WebInputEvent::isMouseEventType(event->type)) { guest_rvh->ForwardMouseEvent( - *static_cast<const WebKit::WebMouseEvent*>(event)); + *static_cast<const blink::WebMouseEvent*>(event)); return; } - if (event->type == WebKit::WebInputEvent::MouseWheel) { + if (event->type == blink::WebInputEvent::MouseWheel) { guest_rvh->ForwardWheelEvent( - *static_cast<const WebKit::WebMouseWheelEvent*>(event)); + *static_cast<const blink::WebMouseWheelEvent*>(event)); return; } - if (WebKit::WebInputEvent::isKeyboardEventType(event->type)) { + if (blink::WebInputEvent::isKeyboardEventType(event->type)) { RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>( embedder_web_contents_->GetRenderViewHost()); if (!embedder_rvh->GetLastKeyboardEvent()) @@ -1296,16 +1382,16 @@ void BrowserPluginGuest::OnHandleInputEvent( return; } - if (WebKit::WebInputEvent::isTouchEventType(event->type)) { + if (blink::WebInputEvent::isTouchEventType(event->type)) { guest_rvh->ForwardTouchEventWithLatencyInfo( - *static_cast<const WebKit::WebTouchEvent*>(event), + *static_cast<const blink::WebTouchEvent*>(event), ui::LatencyInfo()); return; } - if (WebKit::WebInputEvent::isGestureEventType(event->type)) { + if (blink::WebInputEvent::isGestureEventType(event->type)) { guest_rvh->ForwardGestureEvent( - *static_cast<const WebKit::WebGestureEvent*>(event)); + *static_cast<const blink::WebGestureEvent*>(event)); return; } } @@ -1313,9 +1399,7 @@ void BrowserPluginGuest::OnHandleInputEvent( void BrowserPluginGuest::OnLockMouse(bool user_gesture, bool last_unlocked_by_target, bool privileged) { - if (pending_lock_request_ || - (permission_request_map_.size() >= - kNumMaxOutstandingPermissionRequests)) { + if (pending_lock_request_) { // Immediately reject the lock because only one pointerLock may be active // at a time. Send(new ViewMsg_LockMouse_ACK(routing_id(), false)); @@ -1346,39 +1430,45 @@ void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) { void BrowserPluginGuest::OnNavigateGuest( int instance_id, const std::string& src) { - GURL url(src); + GURL url = delegate_ ? delegate_->ResolveURL(src) : GURL(src); // We do not load empty urls in web_contents. // If a guest sets empty src attribute after it has navigated to some // non-empty page, the action is considered no-op. This empty src navigation // should never be sent to BrowserPluginGuest (browser process). DCHECK(!src.empty()); - if (!src.empty()) { - // Do not allow navigating a guest to schemes other than known safe schemes. - // This will block the embedder trying to load unwanted schemes, e.g. - // chrome://settings. - bool scheme_is_blocked = - (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme( - url.scheme()) && - !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme( - url.scheme())) || - url.SchemeIs(kJavaScriptScheme); - if (scheme_is_blocked || !url.is_valid()) { - if (delegate_) { - std::string error_type; - RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::", &error_type); - delegate_->LoadAbort(true /* is_top_level */, url, error_type); - } - return; - } + if (src.empty()) + return; - // As guests do not swap processes on navigation, only navigations to - // normal web URLs are supported. No protocol handlers are installed for - // other schemes (e.g., WebUI or extensions), and no permissions or bindings - // can be granted to the guest process. - GetWebContents()->GetController().LoadURL(url, Referrer(), - PAGE_TRANSITION_AUTO_TOPLEVEL, - std::string()); + // Do not allow navigating a guest to schemes other than known safe schemes. + // This will block the embedder trying to load unwanted schemes, e.g. + // chrome://settings. + bool scheme_is_blocked = + (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme( + url.scheme()) && + !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme( + url.scheme())) || + url.SchemeIs(kJavaScriptScheme); + if (scheme_is_blocked || !url.is_valid()) { + if (delegate_) { + std::string error_type; + base::RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::", + &error_type); + delegate_->LoadAbort(true /* is_top_level */, url, error_type); + } + return; } + + GURL validated_url(url); + RenderViewHost::FilterURL( + GetWebContents()->GetRenderProcessHost(), + false, + &validated_url); + // As guests do not swap processes on navigation, only navigations to + // normal web URLs are supported. No protocol handlers are installed for + // other schemes (e.g., WebUI or extensions), and no permissions or bindings + // can be granted to the guest process. + LoadURLWithParams(validated_url, Referrer(), PAGE_TRANSITION_AUTO_TOPLEVEL, + GetWebContents()); } void BrowserPluginGuest::OnPluginDestroyed(int instance_id) { @@ -1413,15 +1503,10 @@ void BrowserPluginGuest::OnResizeGuest( } // Invalid damage buffer means we are in HW compositing mode, // so just resize the WebContents and repaint if needed. - if (!base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) { - if (!params.view_rect.size().IsEmpty()) - GetWebContents()->GetView()->SizeContents(params.view_rect.size()); - if (params.repaint) - Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size())); - return; - } - SetDamageBuffer(params); - GetWebContents()->GetView()->SizeContents(params.view_rect.size()); + if (base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) + SetDamageBuffer(params); + if (!params.view_rect.size().IsEmpty()) + GetWebContents()->GetView()->SizeContents(params.view_rect.size()); if (params.repaint) Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size())); } @@ -1480,6 +1565,18 @@ void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent( edit_commands)); } +void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) { + guest_opaque_ = opaque; + + SkBitmap background; + if (!guest_opaque_) { + background.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); + unsigned int color = 0; + background.setPixels(&color); + } + Send(new ViewMsg_SetBackground(routing_id(), background)); +} + void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) { guest_visible_ = visible; if (embedder_visible_ && guest_visible_) @@ -1529,6 +1626,18 @@ void BrowserPluginGuest::OnUpdateRectACK( OnSetSize(instance_id_, auto_size_params, resize_guest_params); } +void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck( + int instance_id, + int request_id, + const SkBitmap& bitmap) { + CHECK(copy_request_callbacks_.count(request_id)); + if (!copy_request_callbacks_.count(request_id)) + return; + const CopyRequestCallback& callback = copy_request_callbacks_[request_id]; + callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap); + copy_request_callbacks_.erase(request_id); +} + void BrowserPluginGuest::OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect) { // The plugin has moved within the embedder without resizing or the @@ -1591,12 +1700,6 @@ void BrowserPluginGuest::RequestMediaAccessPermission( WebContents* web_contents, const MediaStreamRequest& request, const MediaResponseCallback& callback) { - if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) { - // Deny the media request. - callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>()); - return; - } - base::DictionaryValue request_info; request_info.Set( browser_plugin::kURL, @@ -1612,15 +1715,10 @@ void BrowserPluginGuest::RunJavaScriptDialog( const GURL& origin_url, const std::string& accept_lang, JavaScriptMessageType javascript_message_type, - const string16& message_text, - const string16& default_prompt_text, + const base::string16& message_text, + const base::string16& default_prompt_text, const DialogClosedCallback& callback, bool* did_suppress_message) { - if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) { - // Cancel the dialog. - callback.Run(false, string16()); - return; - } base::DictionaryValue request_info; request_info.Set( browser_plugin::kDefaultPromptText, @@ -1643,18 +1741,18 @@ void BrowserPluginGuest::RunJavaScriptDialog( void BrowserPluginGuest::RunBeforeUnloadDialog( WebContents* web_contents, - const string16& message_text, + const base::string16& message_text, bool is_reload, const DialogClosedCallback& callback) { // This is called if the guest has a beforeunload event handler. // This callback allows navigation to proceed. - callback.Run(true, string16()); + callback.Run(true, base::string16()); } bool BrowserPluginGuest::HandleJavaScriptDialog( WebContents* web_contents, bool accept, - const string16* prompt_override) { + const base::string16* prompt_override) { return false; } @@ -1729,6 +1827,29 @@ void BrowserPluginGuest::OnUpdateRect( new BrowserPluginMsg_UpdateRect(instance_id(), relay_params)); } +void BrowserPluginGuest::OnTextInputTypeChanged(ui::TextInputType type, + ui::TextInputMode input_mode, + bool can_compose_inline) { + RenderWidgetHostViewPort::FromRWHV( + web_contents()->GetRenderWidgetHostView())->TextInputTypeChanged( + type, input_mode, can_compose_inline); +} + +void BrowserPluginGuest::OnImeCancelComposition() { + RenderWidgetHostViewPort::FromRWHV( + web_contents()->GetRenderWidgetHostView())->ImeCancelComposition(); +} + +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) +void BrowserPluginGuest::OnImeCompositionRangeChanged( + const gfx::Range& range, + const std::vector<gfx::Rect>& character_bounds) { + RenderWidgetHostViewPort::FromRWHV( + web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged( + range, character_bounds); +} +#endif + void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId( const std::string& request_method, const base::Callback<void(bool)>& callback, diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h index 0101ff7118d..46c95a40da8 100644 --- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h +++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h @@ -6,12 +6,9 @@ // renderer channel. A BrowserPlugin (a WebPlugin) is on the embedder // renderer side of browser <--> embedder renderer communication. // -// BrowserPluginGuest lives on the UI thread of the browser process. It has a -// helper, BrowserPluginGuestHelper, which is a RenderViewHostObserver. The -// helper object intercepts messages (ViewHostMsg_*) directed at the browser -// process and redirects them to this class. Any messages about the guest render -// process that the embedder might be interested in receiving should be listened -// for here. +// BrowserPluginGuest lives on the UI thread of the browser process. Any +// messages about the guest render process that the embedder might be interested +// in receiving should be listened for here. // // BrowserPluginGuest is a WebContentsDelegate and WebContentsObserver for the // guest WebContents. BrowserPluginGuest operates under the assumption that the @@ -33,15 +30,15 @@ #include "content/port/common/input_event_ack_state.h" #include "content/public/browser/browser_plugin_guest_delegate.h" #include "content/public/browser/javascript_dialog_manager.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "content/public/browser/render_view_host_observer.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/common/browser_plugin_permission_type.h" +#include "third_party/WebKit/public/web/WebCompositionUnderline.h" #include "third_party/WebKit/public/web/WebDragOperation.h" #include "third_party/WebKit/public/web/WebDragStatus.h" #include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/base/ime/text_input_mode.h" +#include "ui/base/ime/text_input_type.h" #include "ui/gfx/rect.h" #include "ui/surface/transport_dib.h" @@ -59,10 +56,14 @@ namespace cc { class CompositorFrameAck; } -namespace WebKit { +namespace blink { class WebInputEvent; } +namespace gfx { +class Range; +} + namespace content { class BrowserPluginHostFactory; @@ -70,6 +71,7 @@ class BrowserPluginEmbedder; class BrowserPluginGuestManager; class RenderProcessHost; class RenderWidgetHostView; +class SiteInstance; struct DropData; struct MediaStreamRequest; @@ -85,7 +87,6 @@ struct MediaStreamRequest; // which means it can share storage and can script this guest. class CONTENT_EXPORT BrowserPluginGuest : public JavaScriptDialogManager, - public NotificationObserver, public WebContentsDelegate, public WebContentsObserver, public base::SupportsWeakPtr<BrowserPluginGuest> { @@ -93,21 +94,32 @@ class CONTENT_EXPORT BrowserPluginGuest typedef base::Callback<void(bool)> GeolocationCallback; virtual ~BrowserPluginGuest(); + // The WebContents passed into the factory method here has not been + // initialized yet and so it does not yet hold a SiteInstance. + // BrowserPluginGuest must be constructed and installed into a WebContents + // prior to its initialization because WebContents needs to determine what + // type of WebContentsView to construct on initialization. The content + // embedder needs to be aware of |guest_site_instance| on the guest's + // construction and so we pass it in here. static BrowserPluginGuest* Create( int instance_id, + SiteInstance* guest_site_instance, WebContentsImpl* web_contents, scoped_ptr<base::DictionaryValue> extra_params); static BrowserPluginGuest* CreateWithOpener( int instance_id, + bool has_render_view, WebContentsImpl* web_contents, - BrowserPluginGuest* opener, - bool has_render_view); + BrowserPluginGuest* opener); - // Called when the embedder RenderViewHost is destroyed to give the + // Called when the embedder WebContents is destroyed to give the // BrowserPluginGuest an opportunity to clean up after itself. void EmbedderDestroyed(); + // Called when the embedder WebContents changes visibility. + void EmbedderVisibilityChanged(bool visible); + // Destroys the guest WebContents and all its associated state, including // this BrowserPluginGuest, and its new unattached windows. void Destroy(); @@ -116,20 +128,10 @@ class CONTENT_EXPORT BrowserPluginGuest // within an embedder. int instance_id() const { return instance_id_; } - // Overrides factory for testing. Default (NULL) value indicates regular - // (non-test) environment. - static void set_factory_for_testing(BrowserPluginHostFactory* factory) { - BrowserPluginGuest::factory_ = factory; - } - bool OnMessageReceivedFromEmbedder(const IPC::Message& message); - void Initialize(WebContentsImpl* embedder_web_contents, - const BrowserPluginHostMsg_Attach_Params& params); - - void set_guest_hang_timeout_for_testing(const base::TimeDelta& timeout) { - guest_hang_timeout_ = timeout; - } + void Initialize(const BrowserPluginHostMsg_Attach_Params& params, + WebContentsImpl* embedder_web_contents); WebContentsImpl* embedder_web_contents() const { return embedder_web_contents_; @@ -149,14 +151,15 @@ class CONTENT_EXPORT BrowserPluginGuest void UpdateVisibility(); - // NotificationObserver implementation. - virtual void Observe(int type, - const NotificationSource& source, - const NotificationDetails& details) OVERRIDE; + void CopyFromCompositingSurface( + gfx::Rect src_subrect, + gfx::Size dst_size, + const base::Callback<void(bool, const SkBitmap&)>& callback); // WebContentsObserver implementation. virtual void DidCommitProvisionalLoadForFrame( int64 frame_id, + const base::string16& frame_unique_name, bool is_main_frame, const GURL& url, PageTransition transition_type, @@ -170,9 +173,9 @@ class CONTENT_EXPORT BrowserPluginGuest // WebContentsDelegate implementation. virtual bool AddMessageToConsole(WebContents* source, int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) OVERRIDE; + const base::string16& source_id) OVERRIDE; // If a new window is created with target="_blank" and rel="noreferrer", then // this method is called, indicating that the new WebContents is ready to be // attached. @@ -198,7 +201,7 @@ class CONTENT_EXPORT BrowserPluginGuest const OpenURLParams& params) OVERRIDE; virtual void WebContentsCreated(WebContents* source_contents, int64 source_frame_id, - const string16& frame_name, + const base::string16& frame_name, const GURL& target_url, WebContents* new_contents) OVERRIDE; virtual void RendererUnresponsive(WebContents* source) OVERRIDE; @@ -217,18 +220,19 @@ class CONTENT_EXPORT BrowserPluginGuest const GURL& origin_url, const std::string& accept_lang, JavaScriptMessageType javascript_message_type, - const string16& message_text, - const string16& default_prompt_text, + const base::string16& message_text, + const base::string16& default_prompt_text, const DialogClosedCallback& callback, bool* did_suppress_message) OVERRIDE; virtual void RunBeforeUnloadDialog( WebContents* web_contents, - const string16& message_text, + const base::string16& message_text, bool is_reload, const DialogClosedCallback& callback) OVERRIDE; - virtual bool HandleJavaScriptDialog(WebContents* web_contents, - bool accept, - const string16* prompt_override) OVERRIDE; + virtual bool HandleJavaScriptDialog( + WebContents* web_contents, + bool accept, + const base::string16* prompt_override) OVERRIDE; virtual void CancelActiveAndPendingDialogs( WebContents* web_contents) OVERRIDE; virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE; @@ -249,7 +253,7 @@ class CONTENT_EXPORT BrowserPluginGuest virtual void SendMessageToEmbedder(IPC::Message* msg); // Returns whether the guest is attached to an embedder. - bool attached() const { return !!embedder_web_contents_; } + bool attached() const { return embedder_web_contents_ != NULL; } // Attaches this BrowserPluginGuest to the provided |embedder_web_contents| // and initializes the guest with the provided |params|. Attaching a guest @@ -281,7 +285,7 @@ class CONTENT_EXPORT BrowserPluginGuest gfx::Rect ToGuestRect(const gfx::Rect& rect); void DragSourceEndedAt(int client_x, int client_y, int screen_x, - int screen_y, WebKit::WebDragOperation operation); + int screen_y, blink::WebDragOperation operation); void DragSourceMovedTo(int client_x, int client_y, int screen_x, int screen_y); @@ -296,8 +300,14 @@ class CONTENT_EXPORT BrowserPluginGuest bool should_allow, const std::string& user_input); + // Overrides factory for testing. Default (NULL) value indicates regular + // (non-test) environment. + static void set_factory_for_testing(BrowserPluginHostFactory* factory) { + BrowserPluginGuest::factory_ = factory; + } + private: - class EmbedderRenderViewHostObserver; + class EmbedderWebContentsObserver; friend class TestBrowserPluginGuest; class DownloadRequest; @@ -309,15 +319,36 @@ class CONTENT_EXPORT BrowserPluginGuest class PermissionRequest; class PointerLockRequest; + // Tracks the name, and target URL of the new window and whether or not it has + // changed since the WebContents has been created and before the new window + // has been attached to a BrowserPlugin. Once the first navigation commits, we + // no longer track this information. + struct NewWindowInfo { + bool changed; + GURL url; + std::string name; + NewWindowInfo(const GURL& url, const std::string& name) : + changed(false), + url(url), + name(name) {} + }; + + // BrowserPluginGuest is a WebContentsObserver of |web_contents| and + // |web_contents| has to stay valid for the lifetime of BrowserPluginGuest. BrowserPluginGuest(int instance_id, + bool has_render_view, WebContentsImpl* web_contents, - BrowserPluginGuest* opener, - bool has_render_view); + BrowserPluginGuest* opener); // Destroy unattached new windows that have been opened by this // BrowserPluginGuest. void DestroyUnattachedWindows(); + void LoadURLWithParams(const GURL& url, + const Referrer& referrer, + PageTransition transition_type, + WebContents* web_contents); + // Bridge IDs correspond to a geolocation request. This method will remove // the bookkeeping for a particular geolocation request associated with the // provided |bridge_id|. It returns the request ID of the geolocation request. @@ -344,10 +375,10 @@ class CONTENT_EXPORT BrowserPluginGuest bool InAutoSizeBounds(const gfx::Size& size) const; - void RequestNewWindowPermission(WebContentsImpl* new_contents, - WindowOpenDisposition disposition, + void RequestNewWindowPermission(WindowOpenDisposition disposition, const gfx::Rect& initial_bounds, - bool user_gesture); + bool user_gesture, + WebContentsImpl* new_contents); // Message handlers for messages from embedder. @@ -356,24 +387,34 @@ class CONTENT_EXPORT BrowserPluginGuest uint32 output_surface_id, int renderer_host_id, const cc::CompositorFrameAck& ack); - + void OnCopyFromCompositingSurfaceAck(int instance_id, + int request_id, + const SkBitmap& bitmap); // Handles drag events from the embedder. // When dragging, the drag events go to the embedder first, and if the drag // happens on the browser plugin, then the plugin sends a corresponding // drag-message to the guest. This routes the drag-message to the guest // renderer. void OnDragStatusUpdate(int instance_id, - WebKit::WebDragStatus drag_status, + blink::WebDragStatus drag_status, const DropData& drop_data, - WebKit::WebDragOperationsMask drag_mask, + blink::WebDragOperationsMask drag_mask, const gfx::Point& location); // Instructs the guest to execute an edit command decoded in the embedder. void OnExecuteEditCommand(int instance_id, const std::string& command); + + // Returns compositor resources reclaimed in the embedder to the guest. + void OnReclaimCompositorResources(int instance_id, + int route_id, + uint32 output_surface_id, + int renderer_host_id, + const cc::CompositorFrameAck& ack); + // Overriden in tests. virtual void OnHandleInputEvent(int instance_id, const gfx::Rect& guest_window_rect, - const WebKit::WebInputEvent* event); + const blink::WebInputEvent* event); void OnLockMouse(bool user_gesture, bool last_unlocked_by_target, bool privileged); @@ -397,6 +438,7 @@ class CONTENT_EXPORT BrowserPluginGuest void OnSetEditCommandsForNextKeyEvent( int instance_id, const std::vector<EditCommand>& edit_commands); + void OnSetContentsOpaque(int instance_id, bool opaque); // The guest WebContents is visible if both its embedder is visible and // the browser plugin element is visible. If either one is not then the // WebContents is marked as hidden. A hidden WebContents will consume @@ -428,12 +470,33 @@ class CONTENT_EXPORT BrowserPluginGuest const BrowserPluginHostMsg_AutoSize_Params& auto_size_params, const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params); + void OnTextInputTypeChanged(ui::TextInputType type, + ui::TextInputMode input_mode, + bool can_compose_inline); + void OnImeSetComposition( + int instance_id, + const std::string& text, + const std::vector<blink::WebCompositionUnderline>& underlines, + int selection_start, + int selection_end); + void OnImeConfirmComposition( + int instance_id, + const std::string& text, + bool keep_selection); + void OnExtendSelectionAndDelete(int instance_id, int before, int after); + // Overridden in tests. + virtual void OnImeCancelComposition(); +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) + void OnImeCompositionRangeChanged( + const gfx::Range& range, + const std::vector<gfx::Rect>& character_bounds); +#endif // Message handlers for messages from guest. void OnDragStopped(); void OnHandleInputEventAck( - WebKit::WebInputEvent::Type event_type, + blink::WebInputEvent::Type event_type, InputEventAckState ack_result); void OnHasTouchEventHandlers(bool accept); void OnSetCursor(const WebCursor& cursor); @@ -471,8 +534,7 @@ class CONTENT_EXPORT BrowserPluginGuest // Static factory instance (always NULL for non-test). static BrowserPluginHostFactory* factory_; - NotificationRegistrar notification_registrar_; - scoped_ptr<EmbedderRenderViewHostObserver> embedder_rvh_observer_; + scoped_ptr<EmbedderWebContentsObserver> embedder_web_contents_observer_; WebContentsImpl* embedder_web_contents_; std::map<int, int> bridge_id_to_request_id_map_; @@ -494,25 +556,20 @@ class CONTENT_EXPORT BrowserPluginGuest bool mouse_locked_; bool pending_lock_request_; bool guest_visible_; + bool guest_opaque_; bool embedder_visible_; std::string name_; bool auto_size_enabled_; gfx::Size max_auto_size_; gfx::Size min_auto_size_; - // Tracks the name, and target URL of the new window and whether or not it has - // changed since the WebContents has been created and before the new window - // has been attached to a BrowserPlugin. Once the first navigation commits, we - // no longer track this information. - struct NewWindowInfo { - bool changed; - GURL url; - std::string name; - NewWindowInfo(const GURL& url, const std::string& name) : - changed(false), - url(url), - name(name) {} - }; + // Each copy-request is identified by a unique number. The unique number is + // used to keep track of the right callback. + int copy_request_id_; + typedef base::Callback<void(bool, const SkBitmap&)> CopyRequestCallback; + typedef std::map<int, const CopyRequestCallback> CopyRequestMap; + CopyRequestMap copy_request_callbacks_; + typedef std::map<BrowserPluginGuest*, NewWindowInfo> PendingWindowMap; PendingWindowMap pending_new_windows_; base::WeakPtr<BrowserPluginGuest> opener_; diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.cc deleted file mode 100644 index ee18b6e92e3..00000000000 --- a/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2012 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 "content/browser/browser_plugin/browser_plugin_guest_helper.h" - -#include "content/browser/browser_plugin/browser_plugin_guest.h" -#include "content/common/drag_messages.h" -#include "content/common/view_messages.h" -#include "content/public/browser/render_view_host.h" - -namespace content { - -BrowserPluginGuestHelper::BrowserPluginGuestHelper( - BrowserPluginGuest* guest, - RenderViewHost* render_view_host) - : RenderViewHostObserver(render_view_host), - guest_(guest) { -} - -BrowserPluginGuestHelper::~BrowserPluginGuestHelper() { -} - -bool BrowserPluginGuestHelper::OnMessageReceived( - const IPC::Message& message) { - if (ShouldForwardToBrowserPluginGuest(message)) - return guest_->OnMessageReceived(message); - return false; -} - -// static -bool BrowserPluginGuestHelper::ShouldForwardToBrowserPluginGuest( - const IPC::Message& message) { - switch (message.type()) { - case DragHostMsg_StartDragging::ID: - case DragHostMsg_TargetDrop_ACK::ID: - case ViewHostMsg_HasTouchEventHandlers::ID: - case ViewHostMsg_SetCursor::ID: - #if defined(OS_MACOSX) - case ViewHostMsg_ShowPopup::ID: - #endif - case ViewHostMsg_ShowWidget::ID: - case ViewHostMsg_TakeFocus::ID: - case ViewHostMsg_UpdateFrameName::ID: - case ViewHostMsg_UpdateRect::ID: - case ViewHostMsg_LockMouse::ID: - case ViewHostMsg_UnlockMouse::ID: - return true; - default: - break; - } - return false; -} - -} // namespace content diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.h b/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.h deleted file mode 100644 index dfe2e321691..00000000000 --- a/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_HELPER_H_ -#define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_HELPER_H_ - -#include "content/port/common/input_event_ack_state.h" -#include "content/public/browser/render_view_host_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "third_party/WebKit/public/web/WebDragOperation.h" -#include "third_party/WebKit/public/web/WebInputEvent.h" - -class WebCursor; -#if defined(OS_MACOSX) -struct ViewHostMsg_ShowPopup_Params; -#endif -struct ViewHostMsg_UpdateRect_Params; - -namespace gfx { -class Size; -} - -namespace content { -class BrowserPluginGuest; -class RenderViewHost; - -// Helper for BrowserPluginGuest. -// -// The purpose of this class is to intercept messages from the guest RenderView -// before they are handled by the standard message handlers in the browser -// process. This permits overriding standard behavior with BrowserPlugin- -// specific behavior. -// -// The lifetime of this class is managed by the associated RenderViewHost. A -// BrowserPluginGuestHelper is created whenever a BrowserPluginGuest is created. -class BrowserPluginGuestHelper : public RenderViewHostObserver { - public: - BrowserPluginGuestHelper(BrowserPluginGuest* guest, - RenderViewHost* render_view_host); - virtual ~BrowserPluginGuestHelper(); - - protected: - // RenderViewHostObserver implementation. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - private: - // Returns whether a message should be forward to the helper's associated - // BrowserPluginGuest. - static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message); - - BrowserPluginGuest* guest_; - - DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuestHelper); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_HELPER_H_ diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc index 6c86331b0fe..ed91c1f51ad 100644 --- a/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc +++ b/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc @@ -4,7 +4,6 @@ #include "content/browser/browser_plugin/browser_plugin_guest_manager.h" -#include "base/command_line.h" #include "content/browser/browser_plugin/browser_plugin_guest.h" #include "content/browser/browser_plugin/browser_plugin_host_factory.h" #include "content/browser/renderer_host/render_view_host_impl.h" @@ -13,11 +12,10 @@ #include "content/common/browser_plugin/browser_plugin_messages.h" #include "content/common/content_export.h" #include "content/public/browser/user_metrics.h" -#include "content/public/common/content_switches.h" #include "content/public/common/result_codes.h" #include "content/public/common/url_constants.h" +#include "content/public/common/url_utils.h" #include "net/base/escape.h" -#include "ui/events/keycodes/keyboard_codes.h" namespace content { @@ -43,7 +41,8 @@ BrowserPluginGuest* BrowserPluginGuestManager::CreateGuest( int instance_id, const BrowserPluginHostMsg_Attach_Params& params, scoped_ptr<base::DictionaryValue> extra_params) { - SiteInstance* guest_site_instance = NULL; + RenderProcessHost* embedder_process_host = + embedder_site_instance->GetProcess(); // Validate that the partition id coming from the renderer is valid UTF-8, // since we depend on this in other parts of the code, such as FilePath // creation. If the validation fails, treat it as a bad message and kill the @@ -51,50 +50,44 @@ BrowserPluginGuest* BrowserPluginGuestManager::CreateGuest( if (!IsStringUTF8(params.storage_partition_id)) { content::RecordAction(UserMetricsAction("BadMessageTerminate_BPGM")); base::KillProcess( - embedder_site_instance->GetProcess()->GetHandle(), + embedder_process_host->GetHandle(), content::RESULT_CODE_KILLED_BAD_MESSAGE, false); return NULL; } - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kSitePerProcess)) { - // When --site-per-process is specified, the behavior of BrowserPlugin - // as <webview> is broken and we use it for rendering out-of-process - // iframes instead. We use the src URL sent by the renderer to find the - // right process in which to place this instance. - // Note: Since BrowserPlugin doesn't support cross-process navigation, - // the instance will stay in the initially assigned process, regardless - // of the site it is navigated to. - // TODO(nasko): Fix this, and such that cross-process navigations are - // supported. - guest_site_instance = - embedder_site_instance->GetRelatedSiteInstance(GURL(params.src)); - } else { - const std::string& host = embedder_site_instance->GetSiteURL().host(); - - std::string url_encoded_partition = net::EscapeQueryParamValue( - params.storage_partition_id, false); - // The SiteInstance of a given webview tag is based on the fact that it's - // a guest process in addition to which platform application the tag - // belongs to and what storage partition is in use, rather than the URL - // that the tag is being navigated to. - GURL guest_site( - base::StringPrintf("%s://%s/%s?%s", chrome::kGuestScheme, - host.c_str(), - params.persist_storage ? "persist" : "", - url_encoded_partition.c_str())); - - // If we already have a webview tag in the same app using the same storage - // partition, we should use the same SiteInstance so the existing tag and - // the new tag can script each other. - guest_site_instance = GetGuestSiteInstance(guest_site); - if (!guest_site_instance) { - // Create the SiteInstance in a new BrowsingInstance, which will ensure - // that webview tags are also not allowed to send messages across - // different partitions. - guest_site_instance = SiteInstance::CreateForURL( - embedder_site_instance->GetBrowserContext(), guest_site); - } + // We usually require BrowserPlugins to be hosted by a storage isolated + // extension. We treat WebUI pages as a special case if they host the + // BrowserPlugin in a component extension iframe. In that case, we use the + // iframe's URL to determine the extension. + const GURL& embedder_site_url = embedder_site_instance->GetSiteURL(); + GURL validated_frame_url(params.embedder_frame_url); + RenderViewHost::FilterURL( + embedder_process_host, false, &validated_frame_url); + const std::string& host = content::HasWebUIScheme(embedder_site_url) ? + validated_frame_url.host() : embedder_site_url.host(); + + std::string url_encoded_partition = net::EscapeQueryParamValue( + params.storage_partition_id, false); + // The SiteInstance of a given webview tag is based on the fact that it's + // a guest process in addition to which platform application the tag + // belongs to and what storage partition is in use, rather than the URL + // that the tag is being navigated to. + GURL guest_site(base::StringPrintf("%s://%s/%s?%s", + kGuestScheme, + host.c_str(), + params.persist_storage ? "persist" : "", + url_encoded_partition.c_str())); + + // If we already have a webview tag in the same app using the same storage + // partition, we should use the same SiteInstance so the existing tag and + // the new tag can script each other. + SiteInstance* guest_site_instance = GetGuestSiteInstance(guest_site); + if (!guest_site_instance) { + // Create the SiteInstance in a new BrowsingInstance, which will ensure + // that webview tags are also not allowed to send messages across + // different partitions. + guest_site_instance = SiteInstance::CreateForURL( + embedder_site_instance->GetBrowserContext(), guest_site); } return WebContentsImpl::CreateGuest( @@ -233,40 +226,17 @@ void BrowserPluginGuestManager::OnUnhandledSwapBuffersACK( sync_point); } -void BrowserPluginGuestManager::DidSendScreenRects( - WebContentsImpl* embedder_web_contents) { - // TODO(lazyboy): Generalize iterating over guest instances and performing - // actions on the guests. +bool BrowserPluginGuestManager::ForEachGuest( + WebContentsImpl* embedder_web_contents, const GuestCallback& callback) { for (GuestInstanceMap::iterator it = guest_web_contents_by_instance_id_.begin(); - it != guest_web_contents_by_instance_id_.end(); ++it) { + it != guest_web_contents_by_instance_id_.end(); ++it) { BrowserPluginGuest* guest = it->second->GetBrowserPluginGuest(); - if (embedder_web_contents == guest->embedder_web_contents()) { - static_cast<RenderViewHostImpl*>( - guest->GetWebContents()->GetRenderViewHost())->SendScreenRects(); - } - } -} + if (embedder_web_contents != guest->embedder_web_contents()) + continue; -bool BrowserPluginGuestManager::UnlockMouseIfNecessary( - WebContentsImpl* embedder_web_contents, - const NativeWebKeyboardEvent& event) { - if ((event.type != WebKit::WebInputEvent::RawKeyDown) || - (event.windowsKeyCode != ui::VKEY_ESCAPE) || - (event.modifiers & WebKit::WebInputEvent::InputModifiers)) { - return false; - } - - // TODO(lazyboy): Generalize iterating over guest instances and performing - // actions on the guests. - for (GuestInstanceMap::iterator it = - guest_web_contents_by_instance_id_.begin(); - it != guest_web_contents_by_instance_id_.end(); ++it) { - BrowserPluginGuest* guest = it->second->GetBrowserPluginGuest(); - if (embedder_web_contents == guest->embedder_web_contents()) { - if (guest->UnlockMouseIfNecessary(event)) - return true; - } + if (callback.Run(guest)) + return true; } return false; } diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.h b/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.h index a657bfa7a67..5f3b3b9c686 100644 --- a/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.h +++ b/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.h @@ -36,8 +36,10 @@ class RenderWidgetHostImpl; class SiteInstance; class WebContents; class WebContentsImpl; -struct NativeWebKeyboardEvent; +// WARNING: All APIs should be guarded with a process ID check like +// CanEmbedderAccessInstanceIDMaybeKill, to prevent abuse by normal renderer +// processes. class CONTENT_EXPORT BrowserPluginGuestManager : public base::SupportsUserData::Data { public: @@ -83,10 +85,9 @@ class CONTENT_EXPORT BrowserPluginGuestManager : bool CanEmbedderAccessInstanceIDMaybeKill(int embedder_render_process_id, int instance_id) const; - void DidSendScreenRects(WebContentsImpl* embedder_web_contents); - - bool UnlockMouseIfNecessary(WebContentsImpl* embedder_web_contents_, - const NativeWebKeyboardEvent& event); + typedef base::Callback<bool(BrowserPluginGuest*)> GuestCallback; + bool ForEachGuest(WebContentsImpl* embedder_web_contents, + const GuestCallback& callback); void OnMessageReceived(const IPC::Message& message, int render_process_id); diff --git a/chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc b/chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc index d49f169f05f..9e48a49647d 100644 --- a/chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc +++ b/chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc @@ -18,11 +18,12 @@ #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/browser_plugin/browser_plugin_messages.h" #include "content/common/view_messages.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" -#include "content/public/browser/render_view_host_observer.h" #include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents_observer.h" #include "content/public/common/content_switches.h" #include "content/public/common/drop_data.h" #include "content/public/common/url_constants.h" @@ -38,31 +39,16 @@ #include "net/test/spawned_test_server/spawned_test_server.h" #include "third_party/WebKit/public/web/WebInputEvent.h" -using WebKit::WebInputEvent; -using WebKit::WebMouseEvent; +using blink::WebInputEvent; +using blink::WebMouseEvent; using content::BrowserPluginEmbedder; using content::BrowserPluginGuest; using content::BrowserPluginHostFactory; using content::WebContentsImpl; -namespace { - const char kHTMLForGuest[] = "data:text/html,<html><body>hello world</body></html>"; -const char kHTMLForGuestBusyLoop[] = - "data:text/html,<html><head><script type=\"text/javascript\">" - "function PauseMs(timems) {" - " document.title = \"start\";" - " var date = new Date();" - " var currDate = null;" - " do {" - " currDate = new Date();" - " } while (currDate - date < timems)" - "}" - "function StartPauseMs(timems) {" - " setTimeout(function() { PauseMs(timems); }, 0);" - "}" - "</script></head><body></body></html>"; + const char kHTMLForGuestTouchHandler[] = "data:text/html,<html><body><div id=\"touch\">With touch</div></body>" "<script type=\"text/javascript\">" @@ -76,11 +62,7 @@ const char kHTMLForGuestTouchHandler[] = " handler);" "}" "</script></html>"; -const char kHTMLForGuestWithTitle[] = - "data:text/html," - "<html><head><title>%s</title></head>" - "<body>hello world</body>" - "</html>"; + const char kHTMLForGuestAcceptDrag[] = "data:text/html,<html><body>" "<script>" @@ -92,6 +74,7 @@ const char kHTMLForGuestAcceptDrag[] = " ondrop=\"dropped();\">" "</textarea>" "</body></html>"; + const char kHTMLForGuestWithSize[] = "data:text/html," "<html>" @@ -100,12 +83,6 @@ const char kHTMLForGuestWithSize[] = "</body>" "</html>"; -std::string GetHTMLForGuestWithTitle(const std::string& title) { - return base::StringPrintf(kHTMLForGuestWithTitle, title.c_str()); -} - -} // namespace - namespace content { // Test factory for creating test instances of BrowserPluginEmbedder and @@ -169,9 +146,9 @@ class TestShortHangTimeoutGuestFactory : public TestBrowserPluginHostFactory { public: virtual BrowserPluginGuest* CreateBrowserPluginGuest( int instance_id, WebContentsImpl* web_contents) OVERRIDE { - BrowserPluginGuest* guest = + TestBrowserPluginGuest* guest = new TestBrowserPluginGuest(instance_id, web_contents); - guest->set_guest_hang_timeout_for_testing(TestTimeouts::tiny_timeout()); + guest->set_guest_hang_timeout(TestTimeouts::tiny_timeout()); return guest; } @@ -193,16 +170,15 @@ class TestShortHangTimeoutGuestFactory : public TestBrowserPluginHostFactory { // A transparent observer that can be used to verify that a RenderViewHost // received a specific message. -class RenderViewHostMessageObserver : public RenderViewHostObserver { +class MessageObserver : public WebContentsObserver { public: - RenderViewHostMessageObserver(RenderViewHost* host, - uint32 message_id) - : RenderViewHostObserver(host), + MessageObserver(WebContents* web_contents, uint32 message_id) + : WebContentsObserver(web_contents), message_id_(message_id), message_received_(false) { } - virtual ~RenderViewHostMessageObserver() {} + virtual ~MessageObserver() {} void WaitUntilMessageReceived() { if (message_received_) @@ -230,7 +206,7 @@ class RenderViewHostMessageObserver : public RenderViewHostObserver { uint32 message_id_; bool message_received_; - DISALLOW_COPY_AND_ASSIGN(RenderViewHostMessageObserver); + DISALLOW_COPY_AND_ASSIGN(MessageObserver); }; class BrowserPluginHostTest : public ContentBrowserTest { @@ -411,7 +387,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AdvanceFocus) { StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, std::string()); SimulateMouseClick(test_embedder()->web_contents(), 0, - WebKit::WebMouseEvent::ButtonLeft); + blink::WebMouseEvent::ButtonLeft); BrowserPluginHostTest::SimulateTabKeyPress(test_embedder()->web_contents()); // Wait until we focus into the guest. test_guest()->WaitForFocus(); @@ -445,7 +421,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderChangedAfterSwap) { GURL test_https_url(https_server.GetURL( "files/browser_plugin_title_change.html")); content::WindowedNotificationObserver swap_observer( - content::NOTIFICATION_WEB_CONTENTS_SWAPPED, + content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, content::Source<WebContents>(test_embedder()->web_contents())); NavigateToURL(shell(), test_https_url); swap_observer.Wait(); @@ -463,7 +439,13 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderChangedAfterSwap) { // This test opens two pages in http and there is no RenderViewHost swap, // therefore the embedder created on first page navigation stays the same in // web_contents. -IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderSameAfterNav) { +// Failing flakily on Windows: crbug.com/308405 +#if defined(OS_WIN) +#define MAYBE_EmbedderSameAfterNav DISABLED_EmbedderSameAfterNav +#else +#define MAYBE_EmbedderSameAfterNav EmbedderSameAfterNav +#endif +IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, MAYBE_EmbedderSameAfterNav) { const char kEmbedderURL[] = "/browser_plugin_embedder.html"; StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string()); WebContentsImpl* embedder_web_contents = test_embedder()->web_contents(); @@ -472,13 +454,13 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderSameAfterNav) { // does not happen and existing embedder doesn't change in web_contents. GURL test_url_new(embedded_test_server()->GetURL( "/browser_plugin_title_change.html")); - const string16 expected_title = ASCIIToUTF16("done"); + const base::string16 expected_title = ASCIIToUTF16("done"); content::TitleWatcher title_watcher(shell()->web_contents(), expected_title); NavigateToURL(shell(), test_url_new); - LOG(INFO) << "Start waiting for title"; - string16 actual_title = title_watcher.WaitAndGetTitle(); + VLOG(0) << "Start waiting for title"; + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); - LOG(INFO) << "Done navigating to second page"; + VLOG(0) << "Done navigating to second page"; TestBrowserPluginEmbedder* test_embedder_after_nav = static_cast<TestBrowserPluginEmbedder*>( @@ -527,8 +509,8 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AcceptTouchEvents) { // Install the touch handler in the guest. This should cause the embedder to // start listening for touch events too. - RenderViewHostMessageObserver observer(rvh, - ViewHostMsg_HasTouchEventHandlers::ID); + MessageObserver observer(test_embedder()->web_contents(), + ViewHostMsg_HasTouchEventHandlers::ID); ExecuteSyncJSFunction(test_guest()->web_contents()->GetRenderViewHost(), "InstallTouchHandler();"); observer.WaitUntilMessageReceived(); @@ -555,26 +537,26 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ReloadEmbedder) { // the page has successfully reloaded when it goes back to 'embedder' // in the next step. { - const string16 expected_title = ASCIIToUTF16("modified"); + const base::string16 expected_title = ASCIIToUTF16("modified"); content::TitleWatcher title_watcher(test_embedder()->web_contents(), expected_title); ExecuteSyncJSFunction(rvh, base::StringPrintf("SetTitle('%s');", "modified")); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); } // Reload the embedder page, and verify that the reload was successful. // Then navigate the guest to verify that the browser process does not crash. { - const string16 expected_title = ASCIIToUTF16("embedder"); + const base::string16 expected_title = ASCIIToUTF16("embedder"); content::TitleWatcher title_watcher(test_embedder()->web_contents(), expected_title); test_embedder()->web_contents()->GetController().Reload(false); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); ExecuteSyncJSFunction( @@ -596,8 +578,9 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ReloadEmbedder) { } } -// Always failing in the win7_aura try bot. See http://crbug.com/181107. -#if defined(OS_WIN) && defined(USE_AURA) +// Always failing in the win7_aura try bot. See http://crbug.com/181107. +// Times out on the Mac. See http://crbug.com/297576. +#if (defined(OS_WIN) && defined(USE_AURA)) || defined(OS_MACOSX) #define MAYBE_AcceptDragEvents DISABLED_AcceptDragEvents #else #define MAYBE_AcceptDragEvents AcceptDragEvents @@ -636,17 +619,17 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, MAYBE_AcceptDragEvents) { // This should trigger appropriate messages from the embedder to the guest, // and end with a drop on the guest. The guest changes title when a drop // happens. - const string16 expected_title = ASCIIToUTF16("DROPPED"); + const base::string16 expected_title = ASCIIToUTF16("DROPPED"); content::TitleWatcher title_watcher(test_guest()->web_contents(), expected_title); rvh->DragTargetDragEnter(drop_data, gfx::Point(start_x, start_y), - gfx::Point(start_x, start_y), WebKit::WebDragOperationEvery, 0); + gfx::Point(start_x, start_y), blink::WebDragOperationEvery, 0); rvh->DragTargetDragOver(gfx::Point(end_x, end_y), gfx::Point(end_x, end_y), - WebKit::WebDragOperationEvery, 0); + blink::WebDragOperationEvery, 0); rvh->DragTargetDrop(gfx::Point(end_x, end_y), gfx::Point(end_x, end_y), 0); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); } @@ -668,7 +651,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, PostMessage) { RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( test_embedder()->web_contents()->GetRenderViewHost()); { - const string16 expected_title = ASCIIToUTF16("main guest"); + const base::string16 expected_title = ASCIIToUTF16("main guest"); content::TitleWatcher title_watcher(test_embedder()->web_contents(), expected_title); @@ -679,7 +662,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, PostMessage) { // The title will be updated to "main guest" at the last stage of the // process described above. - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); } } @@ -696,7 +679,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_PostMessageToIFrame) { RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( test_embedder()->web_contents()->GetRenderViewHost()); { - const string16 expected_title = ASCIIToUTF16("main guest"); + const base::string16 expected_title = ASCIIToUTF16("main guest"); content::TitleWatcher title_watcher(test_embedder()->web_contents(), expected_title); @@ -705,7 +688,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_PostMessageToIFrame) { // The title will be updated to "main guest" at the last stage of the // process described above. - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); } { @@ -721,7 +704,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_PostMessageToIFrame) { base::StringPrintf( "CreateChildFrame('%s');", test_url.spec().c_str())); - string16 actual_title = ready_watcher.WaitAndGetTitle(); + base::string16 actual_title = ready_watcher.WaitAndGetTitle(); EXPECT_EQ(ASCIIToUTF16("ready"), actual_title); content::TitleWatcher iframe_watcher(test_embedder()->web_contents(), @@ -823,10 +806,234 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DoNotCrashOnInvalidNavigation) { // should be blocked because the scheme isn't web-safe or a pseudo-scheme. ExecuteSyncJSFunction( test_embedder()->web_contents()->GetRenderViewHost(), - base::StringPrintf("SetSrc('%s://abc123');", - chrome::kGuestScheme)); + base::StringPrintf("SetSrc('%s://abc123');", kGuestScheme)); EXPECT_TRUE(delegate->load_aborted()); EXPECT_TRUE(delegate->load_aborted_url().is_valid()); } +// Tests involving the threaded compositor. +class BrowserPluginThreadedCompositorTest : public BrowserPluginHostTest { + public: + BrowserPluginThreadedCompositorTest() {} + virtual ~BrowserPluginThreadedCompositorTest() {} + + protected: + virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE { + BrowserPluginHostTest::SetUpCommandLine(cmd); + cmd->AppendSwitch(switches::kEnableThreadedCompositing); + + // http://crbug.com/327035 + cmd->AppendSwitch(switches::kDisableDelegatedRenderer); + } +}; + +static void CompareSkBitmaps(const SkBitmap& expected_bitmap, + const SkBitmap& bitmap) { + EXPECT_EQ(expected_bitmap.width(), bitmap.width()); + if (expected_bitmap.width() != bitmap.width()) + return; + EXPECT_EQ(expected_bitmap.height(), bitmap.height()); + if (expected_bitmap.height() != bitmap.height()) + return; + EXPECT_EQ(expected_bitmap.config(), bitmap.config()); + if (expected_bitmap.config() != bitmap.config()) + return; + + SkAutoLockPixels expected_bitmap_lock(expected_bitmap); + SkAutoLockPixels bitmap_lock(bitmap); + int fails = 0; + const int kAllowableError = 2; + for (int i = 0; i < bitmap.width() && fails < 10; ++i) { + for (int j = 0; j < bitmap.height() && fails < 10; ++j) { + SkColor expected_color = expected_bitmap.getColor(i, j); + SkColor color = bitmap.getColor(i, j); + int expected_alpha = SkColorGetA(expected_color); + int alpha = SkColorGetA(color); + int expected_red = SkColorGetR(expected_color); + int red = SkColorGetR(color); + int expected_green = SkColorGetG(expected_color); + int green = SkColorGetG(color); + int expected_blue = SkColorGetB(expected_color); + int blue = SkColorGetB(color); + EXPECT_NEAR(expected_alpha, alpha, kAllowableError) + << "expected_color: " << std::hex << expected_color + << " color: " << color + << " Failed at " << std::dec << i << ", " << j + << " Failure " << ++fails; + EXPECT_NEAR(expected_red, red, kAllowableError) + << "expected_color: " << std::hex << expected_color + << " color: " << color + << " Failed at " << std::dec << i << ", " << j + << " Failure " << ++fails; + EXPECT_NEAR(expected_green, green, kAllowableError) + << "expected_color: " << std::hex << expected_color + << " color: " << color + << " Failed at " << std::dec << i << ", " << j + << " Failure " << ++fails; + EXPECT_NEAR(expected_blue, blue, kAllowableError) + << "expected_color: " << std::hex << expected_color + << " color: " << color + << " Failed at " << std::dec << i << ", " << j + << " Failure " << ++fails; + } + } + EXPECT_LT(fails, 10); +} + +static void CompareSkBitmapAndRun(const base::Closure& callback, + const SkBitmap& expected_bitmap, + bool *result, + bool succeed, + const SkBitmap& bitmap) { + *result = succeed; + if (succeed) + CompareSkBitmaps(expected_bitmap, bitmap); + callback.Run(); +} + +// http://crbug.com/171744 +#if defined(OS_MACOSX) +#define MAYBE_GetBackingStore DISABLED_GetBackingStore +#else +#define MAYBE_GetBackingStore GetBackingStore +#endif +IN_PROC_BROWSER_TEST_F(BrowserPluginThreadedCompositorTest, + MAYBE_GetBackingStore) { + const char kEmbedderURL[] = "/browser_plugin_embedder.html"; + const char kHTMLForGuest[] = + "data:text/html,<html><style>body { background-color: red; }</style>" + "<body></body></html>"; + StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, + std::string("SetSize(50, 60);")); + + WebContentsImpl* guest_contents = test_guest()->web_contents(); + RenderWidgetHostImpl* guest_widget_host = + RenderWidgetHostImpl::From(guest_contents->GetRenderViewHost()); + + SkBitmap expected_bitmap; + expected_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 50, 60); + expected_bitmap.allocPixels(); + expected_bitmap.eraseARGB(255, 255, 0, 0); // #f00 + bool result = false; + while (!result) { + base::RunLoop loop; + guest_widget_host->CopyFromBackingStore(gfx::Rect(), + guest_widget_host->GetView()->GetViewBounds().size(), + base::Bind(&CompareSkBitmapAndRun, loop.QuitClosure(), expected_bitmap, + &result)); + loop.Run(); + } +} + +// Tests input method. +IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, InputMethod) { + const char kEmbedderURL[] = "/browser_plugin_embedder.html"; + const char kGuestHTML[] = "data:text/html," + "<html><body><input id=\"input1\">" + "<input id=\"input2\"></body>" + "<script>" + "var i = document.getElementById(\"input1\");" + "i.oninput = function() {" + " document.title = i.value;" + "}" + "</script>" + "</html>"; + StartBrowserPluginTest(kEmbedderURL, kGuestHTML, true, + "document.getElementById(\"plugin\").focus();"); + + RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>( + test_embedder()->web_contents()->GetRenderViewHost()); + RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>( + test_guest()->web_contents()->GetRenderViewHost()); + + std::vector<blink::WebCompositionUnderline> underlines; + + // An input field in browser plugin guest gets focus and given some user + // input via IME. + { + ExecuteSyncJSFunction(guest_rvh, + "document.getElementById('input1').focus();"); + string16 expected_title = UTF8ToUTF16("InputTest123"); + content::TitleWatcher title_watcher(test_guest()->web_contents(), + expected_title); + embedder_rvh->Send( + new ViewMsg_ImeSetComposition( + test_embedder()->web_contents()->GetRoutingID(), + expected_title, + underlines, + 12, 12)); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); + EXPECT_EQ(expected_title, actual_title); + } + // A composition is committed via IME. + { + string16 expected_title = UTF8ToUTF16("InputTest456"); + content::TitleWatcher title_watcher(test_guest()->web_contents(), + expected_title); + embedder_rvh->Send( + new ViewMsg_ImeConfirmComposition( + test_embedder()->web_contents()->GetRoutingID(), + expected_title, + gfx::Range(), + true)); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); + EXPECT_EQ(expected_title, actual_title); + } + // IME composition starts, but focus moves out, then the composition will + // be committed and get cancel msg. + { + ExecuteSyncJSFunction(guest_rvh, + "document.getElementById('input1').value = '';"); + string16 composition = UTF8ToUTF16("InputTest789"); + content::TitleWatcher title_watcher(test_guest()->web_contents(), + composition); + embedder_rvh->Send( + new ViewMsg_ImeSetComposition( + test_embedder()->web_contents()->GetRoutingID(), + composition, + underlines, + 12, 12)); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); + EXPECT_EQ(composition, actual_title); + // Moving focus causes IME cancel, and the composition will be committed + // in input1, not in input2. + ExecuteSyncJSFunction(guest_rvh, + "document.getElementById('input2').focus();"); + test_guest()->WaitForImeCancel(); + scoped_ptr<base::Value> value = + content::ExecuteScriptAndGetValue( + guest_rvh, "document.getElementById('input1').value"); + std::string result; + ASSERT_TRUE(value->GetAsString(&result)); + EXPECT_EQ(UTF16ToUTF8(composition), result); + } + // Tests ExtendSelectionAndDelete message works in browser_plugin. + { + // Set 'InputTestABC' in input1 and put caret at 6 (after 'T'). + ExecuteSyncJSFunction(guest_rvh, + "var i = document.getElementById('input1');" + "i.focus();" + "i.value = 'InputTestABC';" + "i.selectionStart=6;" + "i.selectionEnd=6;"); + string16 expected_value = UTF8ToUTF16("InputABC"); + content::TitleWatcher title_watcher(test_guest()->web_contents(), + expected_value); + // Delete 'Test' in 'InputTestABC', as the caret is after 'T': + // delete before 1 character ('T') and after 3 characters ('est'). + embedder_rvh->Send( + new ViewMsg_ExtendSelectionAndDelete( + test_embedder()->web_contents()->GetRoutingID(), + 1, 3)); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); + EXPECT_EQ(expected_value, actual_title); + scoped_ptr<base::Value> value = + content::ExecuteScriptAndGetValue( + guest_rvh, "document.getElementById('input1').value"); + std::string actual_value; + ASSERT_TRUE(value->GetAsString(&actual_value)); + EXPECT_EQ(UTF16ToUTF8(expected_value), actual_value); + } +} + } // namespace content diff --git a/chromium/content/browser/browser_plugin/test_browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/test_browser_plugin_guest.cc index a6e62a3ba55..91ba2909d21 100644 --- a/chromium/content/browser/browser_plugin/test_browser_plugin_guest.cc +++ b/chromium/content/browser/browser_plugin/test_browser_plugin_guest.cc @@ -8,7 +8,6 @@ #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/browser_plugin/browser_plugin_messages.h" -#include "content/public/browser/notification_types.h" namespace content { @@ -17,7 +16,7 @@ class BrowserPluginGuest; TestBrowserPluginGuest::TestBrowserPluginGuest( int instance_id, WebContentsImpl* web_contents) - : BrowserPluginGuest(instance_id, web_contents, NULL, false), + : BrowserPluginGuest(instance_id, false, web_contents, NULL), update_rect_count_(0), damage_buffer_call_count_(0), exit_observed_(false), @@ -28,12 +27,9 @@ TestBrowserPluginGuest::TestBrowserPluginGuest( set_damage_buffer_observed_(false), input_observed_(false), load_stop_observed_(false), + ime_cancel_observed_(false), waiting_for_damage_buffer_with_size_(false), last_damage_buffer_size_(gfx::Size()) { - // Listen to visibility changes so that a test can wait for these changes. - notification_registrar_.Add(this, - NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, - Source<WebContents>(web_contents)); } TestBrowserPluginGuest::~TestBrowserPluginGuest() { @@ -43,24 +39,6 @@ WebContentsImpl* TestBrowserPluginGuest::web_contents() const { return static_cast<WebContentsImpl*>(BrowserPluginGuest::web_contents()); } -void TestBrowserPluginGuest::Observe(int type, - const NotificationSource& source, - const NotificationDetails& details) { - switch (type) { - case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: { - bool visible = *Details<bool>(details).ptr(); - if (!visible) { - was_hidden_observed_ = true; - if (was_hidden_message_loop_runner_.get()) - was_hidden_message_loop_runner_->Quit(); - } - return; - } - } - - BrowserPluginGuest::Observe(type, source, details); -} - void TestBrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) { if (msg->type() == BrowserPluginMsg_UpdateRect::ID) { update_rect_count_++; @@ -106,7 +84,7 @@ void TestBrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) { exit_observed_ = true; if (status != base::TERMINATION_STATUS_NORMAL_TERMINATION && status != base::TERMINATION_STATUS_STILL_RUNNING) - LOG(INFO) << "Guest crashed status: " << status; + VLOG(0) << "Guest crashed status: " << status; if (crash_message_loop_runner_.get()) crash_message_loop_runner_->Quit(); BrowserPluginGuest::RenderProcessGone(status); @@ -115,7 +93,7 @@ void TestBrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) { void TestBrowserPluginGuest::OnHandleInputEvent( int instance_id, const gfx::Rect& guest_window_rect, - const WebKit::WebInputEvent* event) { + const blink::WebInputEvent* event) { BrowserPluginGuest::OnHandleInputEvent(instance_id, guest_window_rect, event); @@ -204,6 +182,17 @@ void TestBrowserPluginGuest::WaitForViewSize(const gfx::Size& view_size) { last_view_size_observed_ = gfx::Size(); } +void TestBrowserPluginGuest::WaitForImeCancel() { + if (ime_cancel_observed_) { + ime_cancel_observed_ = false; + return; + } + + ime_cancel_message_loop_runner_ = new MessageLoopRunner(); + ime_cancel_message_loop_runner_->Run(); + ime_cancel_observed_ = false; +} + void TestBrowserPluginGuest::OnSetFocus(int instance_id, bool focused) { if (focused) { focus_observed_ = true; @@ -247,4 +236,19 @@ void TestBrowserPluginGuest::DidStopLoading( load_stop_message_loop_runner_->Quit(); } +void TestBrowserPluginGuest::OnImeCancelComposition() { + if (!ime_cancel_observed_) { + ime_cancel_observed_ = true; + if (ime_cancel_message_loop_runner_.get()) + ime_cancel_message_loop_runner_->Quit(); + } + BrowserPluginGuest::OnImeCancelComposition(); +} + +void TestBrowserPluginGuest::WasHidden() { + was_hidden_observed_ = true; + if (was_hidden_message_loop_runner_.get()) + was_hidden_message_loop_runner_->Quit(); +} + } // namespace content diff --git a/chromium/content/browser/browser_plugin/test_browser_plugin_guest.h b/chromium/content/browser/browser_plugin/test_browser_plugin_guest.h index 7fccb002388..1ef7f0dbecf 100644 --- a/chromium/content/browser/browser_plugin/test_browser_plugin_guest.h +++ b/chromium/content/browser/browser_plugin/test_browser_plugin_guest.h @@ -27,21 +27,20 @@ class TestBrowserPluginGuest : public BrowserPluginGuest { WebContentsImpl* web_contents() const; - // NotificationObserver method override. - virtual void Observe(int type, - const NotificationSource& source, - const NotificationDetails& details) OVERRIDE; - // Overridden methods from BrowserPluginGuest to intercept in test objects. virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; virtual void OnHandleInputEvent(int instance_id, const gfx::Rect& guest_window_rect, - const WebKit::WebInputEvent* event) OVERRIDE; + const blink::WebInputEvent* event) OVERRIDE; virtual void OnSetFocus(int instance_id, bool focused) OVERRIDE; virtual void OnTakeFocus(bool reverse) OVERRIDE; virtual void SetDamageBuffer( const BrowserPluginHostMsg_ResizeGuest_Params& params) OVERRIDE; virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE; + virtual void OnImeCancelComposition() OVERRIDE; + + // Overridden from WebContentsObserver. + virtual void WasHidden() OVERRIDE; // Test utilities to wait for a event we are interested in. // Waits until UpdateRect message is sent from the guest, meaning it is @@ -66,6 +65,12 @@ class TestBrowserPluginGuest : public BrowserPluginGuest { void WaitForLoadStop(); // Waits until UpdateRect with a particular |view_size| is observed. void WaitForViewSize(const gfx::Size& view_size); + // Waits until IME cancellation is observed. + void WaitForImeCancel(); + + void set_guest_hang_timeout(const base::TimeDelta& timeout) { + guest_hang_timeout_ = timeout; + } private: // Overridden methods from BrowserPluginGuest to intercept in test objects. @@ -81,6 +86,7 @@ class TestBrowserPluginGuest : public BrowserPluginGuest { bool set_damage_buffer_observed_; bool input_observed_; bool load_stop_observed_; + bool ime_cancel_observed_; gfx::Size last_view_size_observed_; gfx::Size expected_auto_view_size_; @@ -99,6 +105,7 @@ class TestBrowserPluginGuest : public BrowserPluginGuest { scoped_refptr<MessageLoopRunner> input_message_loop_runner_; scoped_refptr<MessageLoopRunner> load_stop_message_loop_runner_; scoped_refptr<MessageLoopRunner> auto_view_size_message_loop_runner_; + scoped_refptr<MessageLoopRunner> ime_cancel_message_loop_runner_; DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginGuest); }; diff --git a/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc b/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc index 28c27b7578e..59ae63555d9 100644 --- a/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc +++ b/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc @@ -20,9 +20,9 @@ void TestBrowserPluginGuestDelegate::ResetStates() { void TestBrowserPluginGuestDelegate::AddMessageToConsole( int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) { + const base::string16& source_id) { } void TestBrowserPluginGuestDelegate::Close() { @@ -53,10 +53,12 @@ void TestBrowserPluginGuestDelegate::RendererUnresponsive() { bool TestBrowserPluginGuestDelegate::RequestPermission( BrowserPluginPermissionType permission_type, const base::DictionaryValue& request_info, - const PermissionResponseCallback& callback) { + const PermissionResponseCallback& callback, + bool allowed_by_default) { return BrowserPluginGuestDelegate::RequestPermission(permission_type, request_info, - callback); + callback, + allowed_by_default); } void TestBrowserPluginGuestDelegate::SizeChanged(const gfx::Size& old_size, diff --git a/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h b/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h index b6e7e9079f3..4bfae4c622f 100644 --- a/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h +++ b/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h @@ -22,9 +22,9 @@ class TestBrowserPluginGuestDelegate : public BrowserPluginGuestDelegate { private: // Overridden from BrowserPluginGuestDelegate: virtual void AddMessageToConsole(int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) OVERRIDE; + const base::string16& source_id) OVERRIDE; virtual void Close() OVERRIDE; virtual void GuestProcessGone(base::TerminationStatus status) OVERRIDE; virtual bool HandleKeyboardEvent( @@ -37,7 +37,8 @@ class TestBrowserPluginGuestDelegate : public BrowserPluginGuestDelegate { virtual bool RequestPermission( BrowserPluginPermissionType permission_type, const base::DictionaryValue& request_info, - const PermissionResponseCallback& callback) OVERRIDE; + const PermissionResponseCallback& callback, + bool allowed_by_default) OVERRIDE; virtual void SizeChanged(const gfx::Size& old_size, const gfx::Size& new_size) OVERRIDE; |