diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-23 23:06:56 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-23 23:06:56 +0000 |
commit | 581b87eb99683237b52cf727178c0492cf273eeb (patch) | |
tree | 516cf6d1b75dc380fa179d72f95579300d9fdfcb | |
parent | c72d7f9099a607ed546404a04a50402a9c3eeeb6 (diff) | |
download | chromium_src-581b87eb99683237b52cf727178c0492cf273eeb.zip chromium_src-581b87eb99683237b52cf727178c0492cf273eeb.tar.gz chromium_src-581b87eb99683237b52cf727178c0492cf273eeb.tar.bz2 |
Allow the browser to send actions back to the render for media element context menus.
Also renamed ContextNodeType per fishd's suggestion.
BUG=15686
TEST=none
Review URL: http://codereview.chromium.org/155954
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21466 0039d316-1c4b-4281-b951-d872f2087c98
20 files changed, 351 insertions, 104 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 75b07da..ff99693 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -1248,6 +1248,13 @@ void RenderViewHost::OnMsgShowModalHTMLDialog( delegate_->ShowModalHTMLDialog(url, width, height, json_arguments, reply_msg); } +void RenderViewHost::MediaPlayerActionAt(int x, + int y, + const MediaPlayerAction& action) { + // TODO(ajwong): Which thread should run this? Does it matter? + Send(new ViewMsg_MediaPlayerActionAt(routing_id(), x, y, action)); +} + void RenderViewHost::OnMsgPasswordFormsSeen( const std::vector<webkit_glue::PasswordForm>& forms) { delegate_->PasswordFormsSeen(forms); diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 6f68bb0..26612b0 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -25,6 +25,7 @@ class SiteInstance; class SkBitmap; class ViewMsg_Navigate; struct ContextMenuParams; +struct MediaPlayerAction; struct ViewHostMsg_DidPrintPage_Params; struct ViewMsg_Navigate_Params; struct WebDropData; @@ -297,6 +298,9 @@ class RenderViewHost : public RenderWidgetHost, void ModalHTMLDialogClosed(IPC::Message* reply_msg, const std::string& json_retval); + // Send an action to the media player element located at |x|, |y|. + void MediaPlayerActionAt(int x, int y, const MediaPlayerAction& action); + // Copies the image at the specified point. void CopyImageAt(int x, int y); diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc index e7099ac..1c4959f 100644 --- a/chrome/browser/tab_contents/render_view_context_menu.cc +++ b/chrome/browser/tab_contents/render_view_context_menu.cc @@ -51,44 +51,44 @@ RenderViewContextMenu::~RenderViewContextMenu() { // Menu construction functions ------------------------------------------------- void RenderViewContextMenu::Init() { - InitMenu(params_.node, params_.media_params); + InitMenu(params_.node_type, params_.media_params); DoInit(); } -void RenderViewContextMenu::InitMenu(ContextNode node, +void RenderViewContextMenu::InitMenu(ContextNodeType node_type, ContextMenuMediaParams media_params) { - if (node.type & ContextNode::PAGE) + if (node_type.type & ContextNodeType::PAGE) AppendPageItems(); - if (node.type & ContextNode::FRAME) + if (node_type.type & ContextNodeType::FRAME) AppendFrameItems(); - if (node.type & ContextNode::LINK) + if (node_type.type & ContextNodeType::LINK) AppendLinkItems(); - if (node.type & ContextNode::IMAGE) { - if (node.type & ContextNode::LINK) + if (node_type.type & ContextNodeType::IMAGE) { + if (node_type.type & ContextNodeType::LINK) AppendSeparator(); AppendImageItems(); } - if (node.type & ContextNode::VIDEO) { - if (node.type & ContextNode::LINK) + if (node_type.type & ContextNodeType::VIDEO) { + if (node_type.type & ContextNodeType::LINK) AppendSeparator(); AppendVideoItems(media_params); } - if (node.type & ContextNode::AUDIO) { - if (node.type & ContextNode::LINK) + if (node_type.type & ContextNodeType::AUDIO) { + if (node_type.type & ContextNodeType::LINK) AppendSeparator(); AppendAudioItems(media_params); } - if (node.type & ContextNode::EDITABLE) + if (node_type.type & ContextNodeType::EDITABLE) AppendEditableItems(); - else if (node.type & ContextNode::SELECTION || - node.type & ContextNode::LINK) + else if (node_type.type & ContextNodeType::SELECTION || + node_type.type & ContextNodeType::LINK) AppendCopyItem(); - if (node.type & ContextNode::SELECTION) + if (node_type.type & ContextNodeType::SELECTION) AppendSearchProvider(); AppendSeparator(); AppendDeveloperItems(); @@ -132,23 +132,21 @@ void RenderViewContextMenu::AppendAudioItems( void RenderViewContextMenu::AppendVideoItems( ContextMenuMediaParams media_params) { AppendMediaItems(media_params); - AppendMenuItem(IDS_CONTENT_CONTEXT_FULLSCREEN); AppendSeparator(); AppendMenuItem(IDS_CONTENT_CONTEXT_SAVEVIDEOAS); - AppendMenuItem(IDS_CONTENT_CONTEXT_SAVESCREENSHOTAS); AppendMenuItem(IDS_CONTENT_CONTEXT_COPYVIDEOLOCATION); AppendMenuItem(IDS_CONTENT_CONTEXT_OPENVIDEONEWTAB); } void RenderViewContextMenu::AppendMediaItems( ContextMenuMediaParams media_params) { - if (media_params.player_state & ContextMenuMediaParams::PLAYER_PAUSED) { + if (media_params.player_state & ContextMenuMediaParams::PAUSED) { AppendMenuItem(IDS_CONTENT_CONTEXT_PLAY); } else { AppendMenuItem(IDS_CONTENT_CONTEXT_PAUSE); } - if (media_params.player_state & ContextMenuMediaParams::PLAYER_MUTED) { + if (media_params.player_state & ContextMenuMediaParams::MUTED) { AppendMenuItem(IDS_CONTENT_CONTEXT_UNMUTE); } else { AppendMenuItem(IDS_CONTENT_CONTEXT_MUTE); @@ -350,7 +348,7 @@ bool RenderViewContextMenu::IsItemCommandEnabled(int id) const { case IDS_CONTENT_CONTEXT_PLAYBACKRATE_FASTER: case IDS_CONTENT_CONTEXT_PLAYBACKRATE_DOUBLETIME: return (params_.media_params.player_state & - ContextMenuMediaParams::PLAYER_ERROR) == 0; + ContextMenuMediaParams::IN_ERROR) == 0; case IDS_CONTENT_CONTEXT_SAVESCREENSHOTAS: // TODO(ajwong): Enable save screenshot after we actually implement @@ -365,7 +363,7 @@ bool RenderViewContextMenu::IsItemCommandEnabled(int id) const { case IDS_CONTENT_CONTEXT_SAVEAUDIOAS: case IDS_CONTENT_CONTEXT_SAVEVIDEOAS: return (params_.media_params.player_state & - ContextMenuMediaParams::PLAYER_CAN_SAVE) && + ContextMenuMediaParams::CAN_SAVE) && params_.src_url.is_valid() && URLRequest::IsHandledURL(params_.src_url); @@ -381,25 +379,25 @@ bool RenderViewContextMenu::IsItemCommandEnabled(int id) const { return params_.frame_url.is_valid(); case IDS_CONTENT_CONTEXT_UNDO: - return !!(params_.edit_flags & ContextNode::CAN_UNDO); + return !!(params_.edit_flags & ContextNodeType::CAN_UNDO); case IDS_CONTENT_CONTEXT_REDO: - return !!(params_.edit_flags & ContextNode::CAN_REDO); + return !!(params_.edit_flags & ContextNodeType::CAN_REDO); case IDS_CONTENT_CONTEXT_CUT: - return !!(params_.edit_flags & ContextNode::CAN_CUT); + return !!(params_.edit_flags & ContextNodeType::CAN_CUT); case IDS_CONTENT_CONTEXT_COPY: - return !!(params_.edit_flags & ContextNode::CAN_COPY); + return !!(params_.edit_flags & ContextNodeType::CAN_COPY); case IDS_CONTENT_CONTEXT_PASTE: - return !!(params_.edit_flags & ContextNode::CAN_PASTE); + return !!(params_.edit_flags & ContextNodeType::CAN_PASTE); case IDS_CONTENT_CONTEXT_DELETE: - return !!(params_.edit_flags & ContextNode::CAN_DELETE); + return !!(params_.edit_flags & ContextNodeType::CAN_DELETE); case IDS_CONTENT_CONTEXT_SELECTALL: - return !!(params_.edit_flags & ContextNode::CAN_SELECT_ALL); + return !!(params_.edit_flags & ContextNodeType::CAN_SELECT_ALL); case IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD: return !profile_->IsOffTheRecord() && params_.link_url.is_valid(); @@ -456,7 +454,7 @@ bool RenderViewContextMenu::ItemIsChecked(int id) const { // See if the video is set to looping. if (id == IDS_CONTENT_CONTEXT_LOOP) { return (params_.media_params.player_state & - ContextMenuMediaParams::PLAYER_LOOP) != 0; + ContextMenuMediaParams::LOOP) != 0; } // Check box for 'Check the Spelling of this field'. @@ -541,6 +539,82 @@ void RenderViewContextMenu::ExecuteItemCommand(int id) { OpenURL(params_.src_url, NEW_BACKGROUND_TAB, PageTransition::LINK); break; + case IDS_CONTENT_CONTEXT_PLAY: + MediaPlayerActionAt(params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::PLAY)); + break; + + case IDS_CONTENT_CONTEXT_PAUSE: + MediaPlayerActionAt(params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::PAUSE)); + break; + + case IDS_CONTENT_CONTEXT_MUTE: + MediaPlayerActionAt(params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::MUTE)); + break; + + case IDS_CONTENT_CONTEXT_UNMUTE: + MediaPlayerActionAt(params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::UNMUTE)); + break; + + case IDS_CONTENT_CONTEXT_LOOP: + if (ItemIsChecked(IDS_CONTENT_CONTEXT_LOOP)) { + MediaPlayerActionAt(params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::NO_LOOP)); + } else { + MediaPlayerActionAt(params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::LOOP)); + } + break; + + case IDS_CONTENT_CONTEXT_PLAYBACKRATE_SLOW: + MediaPlayerActionAt( + params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::SET_PLAYBACK_RATE, + kSlowPlaybackRate)); + break; + + case IDS_CONTENT_CONTEXT_PLAYBACKRATE_NORMAL: + MediaPlayerActionAt( + params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::SET_PLAYBACK_RATE, + kNormalPlaybackRate)); + break; + + case IDS_CONTENT_CONTEXT_PLAYBACKRATE_FAST: + MediaPlayerActionAt( + params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::SET_PLAYBACK_RATE, + kFastPlaybackRate)); + break; + + case IDS_CONTENT_CONTEXT_PLAYBACKRATE_FASTER: + MediaPlayerActionAt( + params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::SET_PLAYBACK_RATE, + kFasterPlaybackRate)); + break; + + case IDS_CONTENT_CONTEXT_PLAYBACKRATE_DOUBLETIME: + MediaPlayerActionAt( + params_.x, + params_.y, + MediaPlayerAction(MediaPlayerAction::SET_PLAYBACK_RATE, + kDoubleTimePlaybackRate)); + break; + case IDS_CONTENT_CONTEXT_BACK: source_tab_contents_->controller().GoBack(); break; @@ -779,3 +853,10 @@ void RenderViewContextMenu::WriteURLToClipboard(const GURL& url) { WriteTextToClipboard(UTF8ToUTF16(utf8_text)); DidWriteURLToClipboard(utf8_text); } + +void RenderViewContextMenu::MediaPlayerActionAt( + int x, + int y, + const MediaPlayerAction& action) { + source_tab_contents_->render_view_host()->MediaPlayerActionAt(x, y, action); +} diff --git a/chrome/browser/tab_contents/render_view_context_menu.h b/chrome/browser/tab_contents/render_view_context_menu.h index afa6861..93c554d 100644 --- a/chrome/browser/tab_contents/render_view_context_menu.h +++ b/chrome/browser/tab_contents/render_view_context_menu.h @@ -25,7 +25,7 @@ class RenderViewContextMenu { void Init(); protected: - void InitMenu(ContextNode node, ContextMenuMediaParams media_params); + void InitMenu(ContextNodeType node, ContextMenuMediaParams media_params); // Functions to be implemented by platform-specific subclasses --------------- @@ -101,6 +101,8 @@ class RenderViewContextMenu { void WriteTextToClipboard(const string16& text); void WriteURLToClipboard(const GURL& url); + void MediaPlayerActionAt(int x, int y, const MediaPlayerAction& action); + bool IsDevCommandEnabled(int id) const; DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenu); diff --git a/chrome/browser/views/tab_contents/render_view_context_menu_external_win.h b/chrome/browser/views/tab_contents/render_view_context_menu_external_win.h index 852adb4..15baa37 100644 --- a/chrome/browser/views/tab_contents/render_view_context_menu_external_win.h +++ b/chrome/browser/views/tab_contents/render_view_context_menu_external_win.h @@ -17,7 +17,7 @@ class RenderViewContextMenuExternalWin : public RenderViewContextMenuWin { const ContextMenuParams& params, const std::vector<int> disabled_menu_ids); - ~RenderViewContextMenuExternalWin() {} + virtual ~RenderViewContextMenuExternalWin() {} protected: // RenderViewContextMenuWin overrides -------------------------------------- diff --git a/chrome/browser/views/tab_contents/render_view_context_menu_win.h b/chrome/browser/views/tab_contents/render_view_context_menu_win.h index 4ff68b9..89560e3 100644 --- a/chrome/browser/views/tab_contents/render_view_context_menu_win.h +++ b/chrome/browser/views/tab_contents/render_view_context_menu_win.h @@ -17,7 +17,7 @@ class RenderViewContextMenuWin : public RenderViewContextMenu, RenderViewContextMenuWin(TabContents* tab_contents, const ContextMenuParams& params); - ~RenderViewContextMenuWin(); + virtual ~RenderViewContextMenuWin(); void RunMenuAt(int x, int y); diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index d3faea0..6835b49 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -484,8 +484,8 @@ struct ParamTraits<FilterPolicy::Type> { }; template <> -struct ParamTraits<ContextNode> { - typedef ContextNode param_type; +struct ParamTraits<ContextNodeType> { + typedef ContextNodeType param_type; static void Write(Message* m, const param_type& p) { m->WriteInt(p.type); } @@ -493,7 +493,7 @@ struct ParamTraits<ContextNode> { int type; if (!m->ReadInt(iter, &type)) return false; - *p = ContextNode(type); + *p = ContextNodeType(type); return true; } static void Log(const param_type& p, std::wstring* l) { @@ -503,19 +503,19 @@ struct ParamTraits<ContextNode> { event.append(L"NONE"); } else { event.append(L"("); - if (p.type & ContextNode::PAGE) + if (p.type & ContextNodeType::PAGE) event.append(L"PAGE|"); - if (p.type & ContextNode::FRAME) + if (p.type & ContextNodeType::FRAME) event.append(L"FRAME|"); - if (p.type & ContextNode::LINK) + if (p.type & ContextNodeType::LINK) event.append(L"LINK|"); - if (p.type & ContextNode::IMAGE) + if (p.type & ContextNodeType::IMAGE) event.append(L"IMAGE|"); - if (p.type & ContextNode::SELECTION) + if (p.type & ContextNodeType::SELECTION) event.append(L"SELECTION|"); - if (p.type & ContextNode::EDITABLE) + if (p.type & ContextNodeType::EDITABLE) event.append(L"EDITABLE|"); - if (p.type & ContextNode::MISSPELLED_WORD) + if (p.type & ContextNodeType::MISSPELLED_WORD) event.append(L"MISSPELLED_WORD|"); event.append(L")"); } @@ -838,7 +838,7 @@ template <> struct ParamTraits<ContextMenuParams> { typedef ContextMenuParams param_type; static void Write(Message* m, const param_type& p) { - WriteParam(m, p.node); + WriteParam(m, p.node_type); WriteParam(m, p.x); WriteParam(m, p.y); WriteParam(m, p.link_url); @@ -857,7 +857,7 @@ struct ParamTraits<ContextMenuParams> { } static bool Read(const Message* m, void** iter, param_type* p) { return - ReadParam(m, iter, &p->node) && + ReadParam(m, iter, &p->node_type) && ReadParam(m, iter, &p->x) && ReadParam(m, iter, &p->y) && ReadParam(m, iter, &p->link_url) && @@ -879,6 +879,46 @@ struct ParamTraits<ContextMenuParams> { } }; +template <> +struct ParamTraits<MediaPlayerAction> { + typedef MediaPlayerAction param_type; + static void Write(Message* m, const param_type& p) { + WriteParam(m, p.command); + WriteParam(m, p.playback_rate); + } + static bool Read(const Message* m, void** iter, param_type* p) { + return + ReadParam(m, iter, &p->command) && + ReadParam(m, iter, &p->playback_rate); + } + static void Log(const param_type& p, std::wstring* l) { + std::wstring event = L""; + if (!p.command) { + l->append(L"NONE"); + } else { + l->append(L"("); + if (p.command & MediaPlayerAction::PLAY) + l->append(L"PLAY|"); + if (p.command & MediaPlayerAction::PAUSE) + l->append(L"PAUSE|"); + if (p.command & MediaPlayerAction::MUTE) + l->append(L"MUTE|"); + if (p.command & MediaPlayerAction::UNMUTE) + l->append(L"UNMUTE|"); + if (p.command & MediaPlayerAction::LOOP) + l->append(L"LOOP|"); + if (p.command & MediaPlayerAction::NO_LOOP) + l->append(L"NO_LOOP|"); + if (p.command & MediaPlayerAction::SET_PLAYBACK_RATE) { + l->append(L"SET_PLAYBACK_RATE ["); + LogParam(p.playback_rate, l); + l->append(L"]|"); + } + l->append(L")"); + } + } +}; + // Traits for ViewHostMsg_PaintRect_Params structure to pack/unpack. template <> struct ParamTraits<ViewHostMsg_PaintRect_Params> { diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 344ebad..f240a34 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -65,6 +65,13 @@ IPC_BEGIN_MESSAGES(View) IPC_MESSAGE_ROUTED1(ViewMsg_SetRendererPrefs, RendererPreferences) + // Tells the renderer to perform the given action on the media player + // located at |x|, |y|. + IPC_MESSAGE_ROUTED3(ViewMsg_MediaPlayerActionAt, + int32 /* x */, + int32 /* y */, + MediaPlayerAction) + // Tells the render view to close. IPC_MESSAGE_ROUTED0(ViewMsg_Close) diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index fd8f61a..6af62ef 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -59,6 +59,7 @@ #include "webkit/api/public/WebDragData.h" #include "webkit/api/public/WebForm.h" #include "webkit/api/public/WebHistoryItem.h" +#include "webkit/api/public/WebNode.h" #include "webkit/api/public/WebPoint.h" #include "webkit/api/public/WebRect.h" #include "webkit/api/public/WebScriptSource.h" @@ -423,6 +424,7 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_EnableIntrinsicWidthChangedMode, OnEnableIntrinsicWidthChangedMode) IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs) + IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerActionAt, OnMediaPlayerActionAt) IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive) // Have the super handle all other messages. @@ -1977,7 +1979,7 @@ void RenderView::SyncNavigationState() { } void RenderView::ShowContextMenu(WebView* webview, - ContextNode node, + ContextNodeType node_type, int x, int y, const GURL& link_url, @@ -1991,7 +1993,7 @@ void RenderView::ShowContextMenu(WebView* webview, const std::string& security_info, const std::string& frame_charset) { ContextMenuParams params; - params.node = node; + params.node_type = node_type; params.x = x; params.y = y; params.src_url = src_url; @@ -2635,6 +2637,15 @@ void RenderView::OnSetRendererPrefs(const RendererPreferences& renderer_prefs) { // and |subpixel_rendering| through to Skia. } +void RenderView::OnMediaPlayerActionAt(int x, + int y, + const MediaPlayerAction& action) { + if (!webview()) + return; + + webview()->MediaPlayerActionAt(x, y, action); +} + void RenderView::OnUpdateBackForwardListCount(int back_list_count, int forward_list_count) { history_back_list_count_ = back_list_count; diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index d83bab9..d4214c0 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -262,7 +262,7 @@ class RenderView : public RenderWidget, ErrorPageType error_type); virtual void ShowContextMenu(WebView* webview, - ContextNode node, + ContextNodeType node_type, int x, int y, const GURL& link_url, @@ -531,6 +531,9 @@ class RenderView : public RenderWidget, void OnEnableViewSourceMode(); void OnEnableIntrinsicWidthChangedMode(); void OnSetRendererPrefs(const RendererPreferences& renderer_prefs); + void OnMediaPlayerActionAt(int x, + int y, + const MediaPlayerAction& action); void OnUpdateBackForwardListCount(int back_list_count, int forward_list_count); void OnGetAccessibilityInfo( diff --git a/webkit/glue/context_menu.h b/webkit/glue/context_menu.h index e6c4660..620338a 100644 --- a/webkit/glue/context_menu.h +++ b/webkit/glue/context_menu.h @@ -12,7 +12,7 @@ // The type of node that the user may perform a contextual action on // in the WebView. -struct ContextNode { +struct ContextNodeType { enum TypeBit { // No node is selected NONE = 0x0, @@ -57,8 +57,8 @@ struct ContextNode { }; int32 type; - ContextNode() : type(NONE) {} - explicit ContextNode(int32 t) : type(t) {} + ContextNodeType() : type(NONE) {} + explicit ContextNodeType(int32 t) : type(t) {} }; // Parameters structure used in ContextMenuParams with attributes needed to @@ -67,15 +67,15 @@ struct ContextNode { // TODO(ajwong): Add support for multiple audio tracks and subtitles. struct ContextMenuMediaParams { // Values for the bitfield representing the state of the media player. - // If the state is in ERROR, most media controls should disable + // If the state is IN_ERROR, most media controls should disable // themselves. - enum PlayerState { - PLAYER_NO_STATE = 0x0, - PLAYER_ERROR = 0x1, - PLAYER_PAUSED = 0x2, - PLAYER_MUTED = 0x4, - PLAYER_LOOP = 0x8, - PLAYER_CAN_SAVE = 0x10, + enum PlayerStateBit { + NO_STATE = 0x0, + IN_ERROR = 0x1, + PAUSED = 0x2, + MUTED = 0x4, + LOOP = 0x8, + CAN_SAVE = 0x10, }; // A bitfield representing the current state of the player, such as @@ -86,7 +86,7 @@ struct ContextMenuMediaParams { double playback_rate; ContextMenuMediaParams() - : player_state(PLAYER_NO_STATE), playback_rate(1.0f) { + : player_state(NO_STATE), playback_rate(1.0f) { } }; @@ -98,7 +98,7 @@ struct ContextMenuMediaParams { // could be used for more contextual actions. struct ContextMenuParams { // This is the type of Context Node that the context menu was invoked on. - ContextNode node; + ContextNodeType node_type; // These values represent the coordinates of the mouse when the context menu // was invoked. Coords are relative to the associated RenderView's origin. @@ -157,4 +157,28 @@ struct ContextMenuParams { std::string frame_charset; }; +struct MediaPlayerAction { + enum CommandTypeBit { + NONE = 0x0, + PLAY = 0x1, + PAUSE = 0x2, + MUTE = 0x4, + UNMUTE = 0x8, + LOOP = 0x10, + NO_LOOP = 0x20, + SET_PLAYBACK_RATE = 0x40, + }; + + // A bitfield representing the actions that the context menu should execute + // on the originating node. + int32 command; + + // The new playback rate to set if the action is SET_PLAYBACK_RATE. + double playback_rate; + + MediaPlayerAction() : command(NONE), playback_rate(1.0f) {} + explicit MediaPlayerAction(int c) : command(c), playback_rate(1.0f) {} + MediaPlayerAction(int c, double rate) : command(c), playback_rate(rate) {} +}; + #endif // WEBKIT_GLUE_CONTEXT_NODE_TYPES_H__ diff --git a/webkit/glue/context_menu_client_impl.cc b/webkit/glue/context_menu_client_impl.cc index ec57257..210fb24 100644 --- a/webkit/glue/context_menu_client_impl.cc +++ b/webkit/glue/context_menu_client_impl.cc @@ -124,24 +124,25 @@ void ContextMenuClientImpl::contextMenuDestroyed() { } // Figure out the URL of a page or subframe. Returns |page_type| as the type, -// which indicates page or subframe, or ContextNode::NONE if the URL could not +// which indicates page or subframe, or ContextNodeType::NONE if the URL could not // be determined for some reason. -static ContextNode GetTypeAndURLFromFrame(WebCore::Frame* frame, - GURL* url, - ContextNode page_node) { - ContextNode node; +static ContextNodeType GetTypeAndURLFromFrame( + WebCore::Frame* frame, + GURL* url, + ContextNodeType page_node_type) { + ContextNodeType node_type; if (frame) { WebCore::DocumentLoader* dl = frame->loader()->documentLoader(); if (dl) { WebDataSource* ds = WebDataSourceImpl::FromLoader(dl); if (ds) { - node = page_node; + node_type = page_node_type; *url = ds->hasUnreachableURL() ? ds->unreachableURL() : ds->request().url(); } } } - return node; + return node_type; } WebCore::PlatformMenuDescription @@ -161,13 +162,13 @@ WebCore::PlatformMenuDescription WebCore::IntPoint menu_point = selected_frame->view()->contentsToWindow(r.point()); - ContextNode node; + ContextNodeType node_type; // Links, Images, Media tags, and Image/Media-Links take preference over // all else. WebCore::KURL link_url = r.absoluteLinkURL(); if (!link_url.isEmpty()) { - node.type |= ContextNode::LINK; + node_type.type |= ContextNodeType::LINK; } WebCore::KURL src_url; @@ -176,7 +177,7 @@ WebCore::PlatformMenuDescription if (!r.absoluteImageURL().isEmpty()) { src_url = r.absoluteImageURL(); - node.type |= ContextNode::IMAGE; + node_type.type |= ContextNodeType::IMAGE; } else if (!r.absoluteMediaURL().isEmpty()) { src_url = r.absoluteMediaURL(); @@ -185,25 +186,26 @@ WebCore::PlatformMenuDescription WebCore::HTMLMediaElement* media_element = static_cast<WebCore::HTMLMediaElement*>(r.innerNonSharedNode()); if (media_element->hasTagName(WebCore::HTMLNames::videoTag)) { - node.type |= ContextNode::VIDEO; + node_type.type |= ContextNodeType::VIDEO; } else if (media_element->hasTagName(WebCore::HTMLNames::audioTag)) { - node.type |= ContextNode::AUDIO; + node_type.type |= ContextNodeType::AUDIO; } media_params.playback_rate = media_element->playbackRate(); if (media_element->paused()) { - media_params.player_state |= ContextMenuMediaParams::PLAYER_PAUSED; + media_params.player_state |= ContextMenuMediaParams::PAUSED; } if (media_element->muted()) { - media_params.player_state |= ContextMenuMediaParams::PLAYER_MUTED; + media_params.player_state |= ContextMenuMediaParams::MUTED; } if (media_element->loop()) { - media_params.player_state |= ContextMenuMediaParams::PLAYER_LOOP; + media_params.player_state |= ContextMenuMediaParams::LOOP; } if (media_element->supportsSave()) { - media_params.player_state |= ContextMenuMediaParams::PLAYER_CAN_SAVE; + media_params.player_state |= ContextMenuMediaParams::CAN_SAVE; } + // TODO(ajwong): Report error states in the media player. } // If it's not a link, an image, a media element, or an image/media link, @@ -217,26 +219,27 @@ WebCore::PlatformMenuDescription std::string frame_charset = WideToASCII( webkit_glue::StringToStdWString(selected_frame->loader()->encoding())); // Send the frame and page URLs in any case. - ContextNode frame_node = ContextNode(ContextNode::NONE); - ContextNode page_node = + ContextNodeType frame_node = ContextNodeType(ContextNodeType::NONE); + ContextNodeType page_node = GetTypeAndURLFromFrame(webview_->main_frame()->frame(), &page_url, - ContextNode(ContextNode::PAGE)); + ContextNodeType(ContextNodeType::PAGE)); if (selected_frame != webview_->main_frame()->frame()) { - frame_node = GetTypeAndURLFromFrame(selected_frame, - &frame_url, - ContextNode(ContextNode::FRAME)); + frame_node = + GetTypeAndURLFromFrame(selected_frame, + &frame_url, + ContextNodeType(ContextNodeType::FRAME)); } if (r.isSelected()) { - node.type |= ContextNode::SELECTION; + node_type.type |= ContextNodeType::SELECTION; selection_text_string = CollapseWhitespace( webkit_glue::StringToStdWString(selected_frame->selectedText()), false); } if (r.isContentEditable()) { - node.type |= ContextNode::EDITABLE; + node_type.type |= ContextNodeType::EDITABLE; if (webview_->GetFocusedWebCoreFrame()->editor()-> isContinuousSpellCheckingEnabled()) { misspelled_word_string = GetMisspelledWord(default_menu, @@ -244,11 +247,11 @@ WebCore::PlatformMenuDescription } } - if (node.type == ContextNode::NONE) { + if (node_type.type == ContextNodeType::NONE) { if (selected_frame != webview_->main_frame()->frame()) { - node = frame_node; + node_type = frame_node; } else { - node = page_node; + node_type = page_node; } } @@ -258,26 +261,26 @@ WebCore::PlatformMenuDescription if (ds) security_info = ds->response().securityInfo(); - int edit_flags = ContextNode::CAN_DO_NONE; + int edit_flags = ContextNodeType::CAN_DO_NONE; if (webview_->GetFocusedWebCoreFrame()->editor()->canUndo()) - edit_flags |= ContextNode::CAN_UNDO; + edit_flags |= ContextNodeType::CAN_UNDO; if (webview_->GetFocusedWebCoreFrame()->editor()->canRedo()) - edit_flags |= ContextNode::CAN_REDO; + edit_flags |= ContextNodeType::CAN_REDO; if (webview_->GetFocusedWebCoreFrame()->editor()->canCut()) - edit_flags |= ContextNode::CAN_CUT; + edit_flags |= ContextNodeType::CAN_CUT; if (webview_->GetFocusedWebCoreFrame()->editor()->canCopy()) - edit_flags |= ContextNode::CAN_COPY; + edit_flags |= ContextNodeType::CAN_COPY; if (webview_->GetFocusedWebCoreFrame()->editor()->canPaste()) - edit_flags |= ContextNode::CAN_PASTE; + edit_flags |= ContextNodeType::CAN_PASTE; if (webview_->GetFocusedWebCoreFrame()->editor()->canDelete()) - edit_flags |= ContextNode::CAN_DELETE; + edit_flags |= ContextNodeType::CAN_DELETE; // We can always select all... - edit_flags |= ContextNode::CAN_SELECT_ALL; + edit_flags |= ContextNodeType::CAN_SELECT_ALL; WebViewDelegate* d = webview_->delegate(); if (d) { d->ShowContextMenu(webview_, - node, + node_type, menu_point.x(), menu_point.y(), webkit_glue::KURLToGURL(link_url), diff --git a/webkit/glue/glue_util.cc b/webkit/glue/glue_util.cc index f12be0b..8b9f1fa 100644 --- a/webkit/glue/glue_util.cc +++ b/webkit/glue/glue_util.cc @@ -22,6 +22,7 @@ #include "IntPoint.h" #include "IntRect.h" #include "KURL.h" +#include "Node.h" #include "PlatformString.h" #include "ResourceError.h" @@ -36,6 +37,7 @@ #include "webkit/api/public/WebDragData.h" #include "webkit/api/public/WebForm.h" #include "webkit/api/public/WebHistoryItem.h" +#include "webkit/api/public/WebNode.h" #include "webkit/api/public/WebPoint.h" #include "webkit/api/public/WebRect.h" #include "webkit/api/public/WebSize.h" @@ -261,6 +263,14 @@ WTF::PassRefPtr<WebCore::HTMLFormElement> WebFormToHTMLFormElement( return form; } +// WebNode conversions --------------------------------------------------------- +WebKit::WebNode NodeToWebNode(const WTF::PassRefPtr<WebCore::Node>& node) { + return node; +} +WTF::PassRefPtr<WebCore::Node> WebNodeToNode(const WebKit::WebNode& node) { + return node; +} + // WebHistoryItem conversions -------------------------------------------------- WebKit::WebHistoryItem HistoryItemToWebHistoryItem( diff --git a/webkit/glue/glue_util.h b/webkit/glue/glue_util.h index beafe125..4163f29 100644 --- a/webkit/glue/glue_util.h +++ b/webkit/glue/glue_util.h @@ -20,6 +20,7 @@ class IntPoint; class IntRect; class IntSize; class KURL; +class Node; class ResourceError; class ResourceResponse; class SharedBuffer; @@ -33,6 +34,7 @@ class WebData; class WebDragData; class WebForm; class WebHistoryItem; +class WebNode; class WebString; class WebURL; class WebURLRequest; @@ -120,6 +122,10 @@ WebKit::WebSize IntSizeToWebSize(const WebCore::IntSize&); // WebCursorInfo <- Cursor WebKit::WebCursorInfo CursorToWebCursorInfo(const WebCore::Cursor&); +// WebNode <-> Node +WebKit::WebNode NodeToWebNode(const WTF::PassRefPtr<WebCore::Node>&); +WTF::PassRefPtr<WebCore::Node> WebNodeToNode(const WebKit::WebNode&); + // WebDragData <-> ChromiumDataObject WebKit::WebDragData ChromiumDataObjectToWebDragData( const WTF::PassRefPtr<WebCore::ChromiumDataObject>&); diff --git a/webkit/glue/webview.h b/webkit/glue/webview.h index 565143d..dcc3643 100644 --- a/webkit/glue/webview.h +++ b/webkit/glue/webview.h @@ -16,6 +16,7 @@ class WebDragData; struct WebPoint; } +struct MediaPlayerAction; struct WebPreferences; class GURL; class WebDevToolsAgent; @@ -230,6 +231,12 @@ class WebView : public WebKit::WebWidget { virtual void SetIsTransparent(bool is_transparent) = 0; virtual bool GetIsTransparent() const = 0; + // Performs an action from a context menu for the node at the given + // location. + virtual void MediaPlayerActionAt(int x, + int y, + const MediaPlayerAction& action) = 0; + // Updates the WebView's active state (i.e., control tints). virtual void SetActive(bool active) = 0; diff --git a/webkit/glue/webview_delegate.h b/webkit/glue/webview_delegate.h index 77624b3..8f2371b 100644 --- a/webkit/glue/webview_delegate.h +++ b/webkit/glue/webview_delegate.h @@ -50,6 +50,7 @@ class WebWorker; class WebWorkerClient; class WebMediaPlayer; class WebMediaPlayerClient; +class WebNode; class WebURLRequest; class WebURLResponse; class WebWidget; @@ -615,7 +616,8 @@ class WebViewDelegate : virtual public WebKit::WebWidgetClient { // @abstract Shows a context menu with commands relevant to a specific // element on the current page. // @param webview The WebView sending the delegate method. - // @param node The node(s) the context menu is being invoked on + // @param node_type The type of the node(s) the context menu is being + // invoked on // @param x The x position of the mouse pointer (relative to the webview) // @param y The y position of the mouse pointer (relative to the webview) // @param link_url The absolute URL of the link that contains the node the @@ -635,7 +637,7 @@ class WebViewDelegate : virtual public WebKit::WebWidgetClient { // @param frame_charset which indicates the character encoding of // the currently focused frame. virtual void ShowContextMenu(WebView* webview, - ContextNode node, + ContextNodeType node_type, int x, int y, const GURL& link_url, diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc index 89af941..17ff9eb 100644 --- a/webkit/glue/webview_impl.cc +++ b/webkit/glue/webview_impl.cc @@ -52,6 +52,7 @@ MSVC_PUSH_WARNING_LEVEL(0); #include "GraphicsContext.h" #include "HTMLNames.h" #include "HTMLInputElement.h" +#include "HTMLMediaElement.h" #include "HitTestResult.h" #include "Image.h" #include "InspectorController.h" @@ -1804,6 +1805,41 @@ bool WebViewImpl::GetIsTransparent() const { return is_transparent_; } +void WebViewImpl::MediaPlayerActionAt(int x, + int y, + const MediaPlayerAction& action) { + HitTestResult result = HitTestResultForWindowPos(IntPoint(x, y)); + + WTF::RefPtr<WebCore::Node> node = result.innerNonSharedNode(); + if (node->hasTagName(WebCore::HTMLNames::videoTag) || + node->hasTagName(WebCore::HTMLNames::audioTag)) { + WTF::RefPtr<WebCore::HTMLMediaElement> media_element = + static_pointer_cast<WebCore::HTMLMediaElement>(node); + if (action.command & MediaPlayerAction::PLAY) { + media_element->play(); + } + if (action.command & MediaPlayerAction::PAUSE) { + media_element->pause(); + } + if (action.command & MediaPlayerAction::MUTE) { + media_element->setMuted(true); + } + if (action.command & MediaPlayerAction::UNMUTE) { + media_element->setMuted(false); + } + if (action.command & MediaPlayerAction::LOOP) { + media_element->setLoop(true); + } + if (action.command & MediaPlayerAction::NO_LOOP) { + media_element->setLoop(false); + } + if (action.command & MediaPlayerAction::SET_PLAYBACK_RATE) { + // TODO(ajwong): We should test for overflow. + media_element->setPlaybackRate(static_cast<float>(action.playback_rate)); + } + } +} + void WebViewImpl::SetActive(bool active) { if (page() && page()->focusController()) page()->focusController()->setActive(active); diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h index 92dd080..4ab05dd 100644 --- a/webkit/glue/webview_impl.h +++ b/webkit/glue/webview_impl.h @@ -131,6 +131,10 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { virtual void SetIsTransparent(bool is_transparent); virtual bool GetIsTransparent() const; + virtual void MediaPlayerActionAt(int x, + int y, + const MediaPlayerAction& action); + virtual void SetActive(bool active); virtual bool IsActive(); diff --git a/webkit/tools/test_shell/test_webview_delegate.cc b/webkit/tools/test_shell/test_webview_delegate.cc index 55a2d8b..197cc16 100644 --- a/webkit/tools/test_shell/test_webview_delegate.cc +++ b/webkit/tools/test_shell/test_webview_delegate.cc @@ -574,7 +574,7 @@ void TestWebViewDelegate::StartDragging(WebView* webview, void TestWebViewDelegate::ShowContextMenu( WebView* webview, - ContextNode node, + ContextNodeType node_type, int x, int y, const GURL& link_url, @@ -587,7 +587,7 @@ void TestWebViewDelegate::ShowContextMenu( int edit_flags, const std::string& security_info, const std::string& frame_charset) { - CapturedContextMenuEvent context(node, x, y); + CapturedContextMenuEvent context(node_type, x, y); captured_context_menu_events_.push_back(context); } diff --git a/webkit/tools/test_shell/test_webview_delegate.h b/webkit/tools/test_shell/test_webview_delegate.h index f86bc56..4e9de10 100644 --- a/webkit/tools/test_shell/test_webview_delegate.h +++ b/webkit/tools/test_shell/test_webview_delegate.h @@ -45,15 +45,15 @@ class TestWebViewDelegate : public base::RefCounted<TestWebViewDelegate>, public WebViewDelegate { public: struct CapturedContextMenuEvent { - CapturedContextMenuEvent(ContextNode in_node, + CapturedContextMenuEvent(ContextNodeType in_node_type, int in_x, int in_y) - : node(in_node), + : node_type(in_node_type), x(in_x), y(in_y) { } - ContextNode node; + ContextNodeType node_type; int x; int y; }; @@ -130,7 +130,7 @@ class TestWebViewDelegate : public base::RefCounted<TestWebViewDelegate>, virtual void StartDragging(WebView* webview, const WebKit::WebDragData& drag_data); virtual void ShowContextMenu(WebView* webview, - ContextNode node, + ContextNodeType node_type, int x, int y, const GURL& link_url, |