[M47_2526] Chromium upversion to m47_2526 branch
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / efl_integration / renderer / render_frame_observer_efl.cc
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.
4
5 #include "renderer/render_frame_observer_efl.h"
6
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"
20 #undef private
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"
31
32 #include "base/logging.h"
33
34 using blink::WebDocument;
35 using blink::WebElement;
36 using blink::WebElementCollection;
37 using blink::WebFrame;
38 using blink::WebLocalFrame;
39 using blink::WebView;
40
41 namespace content {
42
43 namespace {
44
45 WebElement GetFocusedElement(WebLocalFrame* frame) {
46   WebDocument doc = frame->document();
47   if (!doc.isNull())
48     return doc.focusedElement();
49
50   return WebElement();
51 }
52
53 bool hasHTMLTagNameSelect(const WebElement& element) {
54   if (element.isNull())
55     return false;
56
57   if (element.hasHTMLTagName("select"))
58     return true;
59
60   return false;
61 }
62
63 } // namespace
64
65 RenderFrameObserverEfl::RenderFrameObserverEfl(RenderFrame* render_frame)
66     : content::RenderFrameObserver(render_frame) {
67 }
68
69 RenderFrameObserverEfl::~RenderFrameObserverEfl() {
70 }
71
72 bool RenderFrameObserverEfl::OnMessageReceived(const IPC::Message& message) {
73   bool handled = true;
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)
80   IPC_END_MESSAGE_MAP()
81   return handled;
82 }
83
84 void RenderFrameObserverEfl::OnSelectPopupMenuItems(
85     bool canceled,
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)
90     return;
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);
97   if (canceled)
98     render_frame_impl_->DidHideExternalPopupMenu();
99 }
100
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);
106   bool replace = true;
107
108   std::string error_html;
109   GetContentClientExport()->renderer()->GetNavigationErrorStrings(
110       render_frame()->GetRenderView(), frame, failed_request, error, &error_html, NULL);
111
112   frame->loadHTMLString(error_html,
113                        GURL(kUnreachableWebDataURL),
114                        error.unreachableURL,
115                        replace);
116 }
117
118 void RenderFrameObserverEfl::OnMoveToNextOrPreviousSelectElement(bool direction) {
119   content::RenderView* render_view_ = render_frame()->GetRenderView();
120   if (direction)
121     render_view_->GetWebView()->moveFocusToNext(WebView::TraverseFocusThrough::SelectElement);
122   else
123     render_view_->GetWebView()->moveFocusToPrevious(WebView::TraverseFocusThrough::SelectElement);
124 }
125
126 void RenderFrameObserverEfl::OnRequestSelectCollectionInformation() {
127   WebElement focused_element = GetFocusedElement(render_frame()->GetWebFrame());
128   if (focused_element.isNull())
129     return;
130
131   content::RenderView* render_view_ = render_frame()->GetRenderView();
132   WebFrame* focused_frame = render_view_->GetWebView()->focusedFrame();
133   if (!focused_frame)
134     return;
135
136   WebDocument document = focused_frame->document();
137   if (document.isNull())
138       return;
139
140   WebElementCollection select_elements = document.getElementsByHTMLTagName("select");
141   int count = 0;
142   int index = 0;
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)
151         index = count;
152       ++count;
153     }
154   }
155 #endif
156
157   if (count) {
158     bool prev_status = index > 0;
159     bool next_status = index < count - 1;
160
161     Send(new EwkHostMsg_RequestSelectCollectionInformationUpdateACK(
162         render_frame()->GetRoutingID(), count, index, prev_status, next_status));
163   }
164 }
165
166 void RenderFrameObserverEfl::DidChangeScrollOffset() {
167   if (render_frame()->GetRenderView()->GetMainRenderFrame() != render_frame())
168     return;
169
170   blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
171
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));
180   }
181 #endif
182
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));
188   }
189 }
190
191 void RenderFrameObserverEfl::WillSubmitForm(
192     const blink::WebFormElement& form) {
193   GURL url(form.action());
194   Send(new EwkHostMsg_FormSubmit(render_frame()->GetRoutingID(), url));
195 }
196
197 } // namespace content