1 // Copyright 2014 Samsung Electronics. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "renderer/render_frame_observer_efl.h"
7 #include "content/common/content_client_export.h"
8 #include "content/common/frame_messages.h"
9 #include "content/public/common/content_client.h"
10 #include "content/public/common/url_constants.h"
11 #include "content/public/renderer/content_renderer_client.h"
12 #include "content/public/renderer/render_frame.h"
13 #include "content/public/renderer/render_view.h"
14 // RenderFrameImpl declares itself as a friend class to
15 // RenderFrameObserver. In order to access private members of
16 // the former from a descendant class of RenderFrameObserver,
17 // we define redefine "private" while including the associated header.
18 #define private public
19 #include "content/renderer/render_frame_impl.h"
21 #include "content/renderer/external_popup_menu.h"
22 #include "common/render_messages_ewk.h"
23 #include "third_party/WebKit/public/platform/WebURLError.h"
24 #include "third_party/WebKit/public/platform/WebURLRequest.h"
25 #include "third_party/WebKit/public/web/WebDocument.h"
26 #include "third_party/WebKit/public/web/WebElement.h"
27 #include "third_party/WebKit/public/web/WebElementCollection.h"
28 #include "third_party/WebKit/public/web/WebFormElement.h"
29 #include "third_party/WebKit/public/web/WebLocalFrame.h"
30 #include "third_party/WebKit/public/web/WebView.h"
32 #include "base/logging.h"
34 using blink::WebDocument;
35 using blink::WebElement;
36 using blink::WebElementCollection;
37 using blink::WebFrame;
38 using blink::WebLocalFrame;
45 WebElement GetFocusedElement(WebLocalFrame* frame) {
46 WebDocument doc = frame->document();
48 return doc.focusedElement();
53 bool hasHTMLTagNameSelect(const WebElement& element) {
57 if (element.hasHTMLTagName("select"))
65 RenderFrameObserverEfl::RenderFrameObserverEfl(RenderFrame* render_frame)
66 : content::RenderFrameObserver(render_frame) {
69 RenderFrameObserverEfl::~RenderFrameObserverEfl() {
72 bool RenderFrameObserverEfl::OnMessageReceived(const IPC::Message& message) {
74 IPC_BEGIN_MESSAGE_MAP(RenderFrameObserverEfl, message)
75 IPC_MESSAGE_HANDLER(EwkFrameMsg_LoadNotFoundErrorPage, OnLoadNotFoundErrorPage)
76 IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
77 IPC_MESSAGE_HANDLER(EwkFrameMsg_MoveToNextOrPreviousSelectElement, OnMoveToNextOrPreviousSelectElement)
78 IPC_MESSAGE_HANDLER(EwkFrameMsg_RequestSelectCollectionInformation, OnRequestSelectCollectionInformation);
79 IPC_MESSAGE_UNHANDLED(handled = false)
84 void RenderFrameObserverEfl::OnSelectPopupMenuItems(
86 const std::vector<int>& selected_indices) {
87 RenderFrameImpl* render_frame_impl_ = static_cast<RenderFrameImpl*>(render_frame());
88 ExternalPopupMenu* external_popup_menu_ = render_frame_impl_->external_popup_menu_.get();
89 if (external_popup_menu_ == NULL)
91 // It is possible to receive more than one of these calls if the user presses
92 // a select faster than it takes for the show-select-popup IPC message to make
93 // it to the browser UI thread. Ignore the extra-messages.
94 // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
95 canceled = canceled || !hasHTMLTagNameSelect(GetFocusedElement(render_frame()->GetWebFrame()));
96 external_popup_menu_->DidSelectItems(canceled, selected_indices);
98 render_frame_impl_->DidHideExternalPopupMenu();
101 void RenderFrameObserverEfl::OnLoadNotFoundErrorPage(std::string errorUrl) {
102 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
103 blink::WebURLError error;
104 error.unreachableURL = GURL(errorUrl);
105 blink::WebURLRequest failed_request(error.unreachableURL);
108 std::string error_html;
109 GetContentClientExport()->renderer()->GetNavigationErrorStrings(
110 render_frame()->GetRenderView(), frame, failed_request, error, &error_html, NULL);
112 frame->loadHTMLString(error_html,
113 GURL(kUnreachableWebDataURL),
114 error.unreachableURL,
118 void RenderFrameObserverEfl::OnMoveToNextOrPreviousSelectElement(bool direction) {
119 content::RenderView* render_view_ = render_frame()->GetRenderView();
121 render_view_->GetWebView()->moveFocusToNext(WebView::TraverseFocusThrough::SelectElement);
123 render_view_->GetWebView()->moveFocusToPrevious(WebView::TraverseFocusThrough::SelectElement);
126 void RenderFrameObserverEfl::OnRequestSelectCollectionInformation() {
127 WebElement focused_element = GetFocusedElement(render_frame()->GetWebFrame());
128 if (focused_element.isNull())
131 content::RenderView* render_view_ = render_frame()->GetRenderView();
132 WebFrame* focused_frame = render_view_->GetWebView()->focusedFrame();
136 WebDocument document = focused_frame->document();
137 if (document.isNull())
140 WebElementCollection select_elements = document.getElementsByHTMLTagName("select");
143 #if !defined(EWK_BRINGUP)
144 // [M47_2526] The hasNonEmptyBoundingBox was removed
145 // FIXME: http://web.sec.samsung.net/bugzilla/show_bug.cgi?id=14509
146 for (WebElement e = select_elements.firstItem();
147 !e.isNull(); e = select_elements.nextItem()) {
148 // take only visible elements into account
149 if (e.hasNonEmptyBoundingBox()) {
150 if (e == focused_element)
158 bool prev_status = index > 0;
159 bool next_status = index < count - 1;
161 Send(new EwkHostMsg_RequestSelectCollectionInformationUpdateACK(
162 render_frame()->GetRoutingID(), count, index, prev_status, next_status));
166 void RenderFrameObserverEfl::DidChangeScrollOffset() {
167 if (render_frame()->GetRenderView()->GetMainRenderFrame() != render_frame())
170 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
172 #if !defined(EWK_BRINGUP)
173 // [M47_2526] The maximumScrollOffset was removed in WebLocalFrameImpl class
174 // FIXME: http://web.sec.samsung.net/bugzilla/show_bug.cgi?id=14511
175 if (max_scroll_offset_ != frame->maximumScrollOffset()) {
176 max_scroll_offset_ = frame->maximumScrollOffset();
177 Send(new EwkHostMsg_DidChangeMaxScrollOffset(render_frame()->GetRoutingID(),
178 frame->maximumScrollOffset().width,
179 frame->maximumScrollOffset().height));
183 if (last_scroll_offset_ != frame->scrollOffset()) {
184 last_scroll_offset_ = frame->scrollOffset();
185 Send(new EwkHostMsg_DidChangeScrollOffset(render_frame()->GetRoutingID(),
186 frame->scrollOffset().width,
187 frame->scrollOffset().height));
191 void RenderFrameObserverEfl::WillSubmitForm(
192 const blink::WebFormElement& form) {
193 GURL url(form.action());
194 Send(new EwkHostMsg_FormSubmit(render_frame()->GetRoutingID(), url));
197 } // namespace content