Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / services / html_viewer / html_document_view.cc
1 // Copyright 2014 The Chromium Authors. 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 "mojo/services/html_viewer/html_document_view.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/string_util.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "mojo/public/cpp/system/data_pipe.h"
13 #include "mojo/services/html_viewer/blink_input_events_type_converters.h"
14 #include "mojo/services/html_viewer/blink_url_request_type_converters.h"
15 #include "mojo/services/html_viewer/webstoragenamespace_impl.h"
16 #include "mojo/services/html_viewer/weburlloader_impl.h"
17 #include "mojo/services/public/cpp/view_manager/view.h"
18 #include "skia/ext/refptr.h"
19 #include "third_party/WebKit/public/platform/Platform.h"
20 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
21 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
22 #include "third_party/WebKit/public/web/WebDocument.h"
23 #include "third_party/WebKit/public/web/WebElement.h"
24 #include "third_party/WebKit/public/web/WebInputEvent.h"
25 #include "third_party/WebKit/public/web/WebLocalFrame.h"
26 #include "third_party/WebKit/public/web/WebScriptSource.h"
27 #include "third_party/WebKit/public/web/WebSettings.h"
28 #include "third_party/WebKit/public/web/WebView.h"
29 #include "third_party/skia/include/core/SkCanvas.h"
30 #include "third_party/skia/include/core/SkColor.h"
31 #include "third_party/skia/include/core/SkDevice.h"
32
33 namespace mojo {
34 namespace {
35
36 void ConfigureSettings(blink::WebSettings* settings) {
37   settings->setAcceleratedCompositingEnabled(false);
38   settings->setCookieEnabled(true);
39   settings->setDefaultFixedFontSize(13);
40   settings->setDefaultFontSize(16);
41   settings->setLoadsImagesAutomatically(true);
42   settings->setJavaScriptEnabled(true);
43 }
44
45 Target WebNavigationPolicyToNavigationTarget(
46     blink::WebNavigationPolicy policy) {
47   switch (policy) {
48     case blink::WebNavigationPolicyCurrentTab:
49       return TARGET_SOURCE_NODE;
50     case blink::WebNavigationPolicyNewBackgroundTab:
51     case blink::WebNavigationPolicyNewForegroundTab:
52     case blink::WebNavigationPolicyNewWindow:
53     case blink::WebNavigationPolicyNewPopup:
54       return TARGET_NEW_NODE;
55     default:
56       return TARGET_DEFAULT;
57   }
58 }
59
60 bool CanNavigateLocally(blink::WebFrame* frame,
61                         const blink::WebURLRequest& request) {
62   // For now, we just load child frames locally.
63   // TODO(aa): In the future, this should use embedding to connect to a
64   // different instance of Blink if the frame is cross-origin.
65   if (frame->parent())
66     return true;
67
68   // If we have extraData() it means we already have the url response
69   // (presumably because we are being called via Navigate()). In that case we
70   // can go ahead and navigate locally.
71   if (request.extraData())
72     return true;
73
74   // Otherwise we don't know if we're the right app to handle this request. Ask
75   // host to do the navigation for us.
76   return false;
77 }
78
79 }  // namespace
80
81 HTMLDocumentView::HTMLDocumentView(ServiceProvider* service_provider,
82                                    ViewManager* view_manager)
83     : view_manager_(view_manager),
84       web_view_(NULL),
85       root_(NULL),
86       repaint_pending_(false),
87       navigator_host_(service_provider),
88       weak_factory_(this) {
89 }
90
91 HTMLDocumentView::~HTMLDocumentView() {
92   if (web_view_)
93     web_view_->close();
94   if (root_)
95     root_->RemoveObserver(this);
96 }
97
98 void HTMLDocumentView::AttachToView(View* view) {
99   root_ = view;
100   root_->SetColor(SK_ColorCYAN);  // Dummy background color.
101
102   web_view_ = blink::WebView::create(this);
103   ConfigureSettings(web_view_->settings());
104   web_view_->setMainFrame(blink::WebLocalFrame::create(this));
105   web_view_->resize(root_->bounds().size());
106
107   root_->AddObserver(this);
108 }
109
110 void HTMLDocumentView::Load(URLResponsePtr response) {
111   DCHECK(web_view_);
112
113   GURL url(response->url);
114
115   WebURLRequestExtraData* extra_data = new WebURLRequestExtraData;
116   extra_data->synthetic_response = response.Pass();
117
118   blink::WebURLRequest web_request;
119   web_request.initialize();
120   web_request.setURL(url);
121   web_request.setExtraData(extra_data);
122
123   web_view_->mainFrame()->loadRequest(web_request);
124 }
125
126 blink::WebStorageNamespace* HTMLDocumentView::createSessionStorageNamespace() {
127   return new WebStorageNamespaceImpl();
128 }
129
130 void HTMLDocumentView::didInvalidateRect(const blink::WebRect& rect) {
131   if (!repaint_pending_) {
132     repaint_pending_ = true;
133     base::ThreadTaskRunnerHandle::Get()->PostTask(
134         FROM_HERE,
135         base::Bind(&HTMLDocumentView::Repaint, weak_factory_.GetWeakPtr()));
136   }
137 }
138
139 bool HTMLDocumentView::allowsBrokenNullLayerTreeView() const {
140   // TODO(darin): Switch to using compositor bindings.
141   //
142   // NOTE: Note to Blink maintainers, feel free to break this code if it is the
143   // last NOT using compositor bindings and you want to delete this code path.
144   //
145   return true;
146 }
147
148 blink::WebCookieJar* HTMLDocumentView::cookieJar(blink::WebLocalFrame* frame) {
149   // TODO(darin): Blink does not fallback to the Platform provided WebCookieJar.
150   // Either it should, as it once did, or we should find another solution here.
151   return blink::Platform::current()->cookieJar();
152 }
153
154 blink::WebNavigationPolicy HTMLDocumentView::decidePolicyForNavigation(
155     blink::WebLocalFrame* frame, blink::WebDataSource::ExtraData* data,
156     const blink::WebURLRequest& request, blink::WebNavigationType nav_type,
157     blink::WebNavigationPolicy default_policy, bool is_redirect) {
158   if (CanNavigateLocally(frame, request))
159     return default_policy;
160
161   NavigationDetailsPtr nav_details(NavigationDetails::New());
162   nav_details->request = URLRequest::From(request);
163
164   navigator_host_->RequestNavigate(
165       root_->id(),
166       WebNavigationPolicyToNavigationTarget(default_policy),
167       nav_details.Pass());
168
169   return blink::WebNavigationPolicyIgnore;
170 }
171
172 void HTMLDocumentView::didAddMessageToConsole(
173     const blink::WebConsoleMessage& message,
174     const blink::WebString& source_name,
175     unsigned source_line,
176     const blink::WebString& stack_trace) {
177 }
178
179 void HTMLDocumentView::didNavigateWithinPage(
180     blink::WebLocalFrame* frame, const blink::WebHistoryItem& history_item,
181     blink::WebHistoryCommitType commit_type) {
182   navigator_host_->DidNavigateLocally(root_->id(),
183                                       history_item.urlString().utf8());
184 }
185
186 void HTMLDocumentView::OnViewBoundsChanged(View* view,
187                                            const gfx::Rect& old_bounds,
188                                            const gfx::Rect& new_bounds) {
189   DCHECK_EQ(view, root_);
190   web_view_->resize(view->bounds().size());
191 }
192
193 void HTMLDocumentView::OnViewDestroyed(View* view) {
194   DCHECK_EQ(view, root_);
195   view->RemoveObserver(this);
196   root_ = NULL;
197 }
198
199 void HTMLDocumentView::OnViewInputEvent(View* view, const EventPtr& event) {
200   scoped_ptr<blink::WebInputEvent> web_event =
201       TypeConverter<EventPtr, scoped_ptr<blink::WebInputEvent> >::ConvertTo(
202           event);
203   if (web_event)
204     web_view_->handleInputEvent(*web_event);
205 }
206
207 void HTMLDocumentView::Repaint() {
208   repaint_pending_ = false;
209
210   web_view_->animate(0.0);
211   web_view_->layout();
212
213   int width = web_view_->size().width;
214   int height = web_view_->size().height;
215
216   skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(SkCanvas::NewRaster(
217       SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType)));
218
219   web_view_->paint(canvas.get(), gfx::Rect(0, 0, width, height));
220
221   root_->SetContents(canvas->getDevice()->accessBitmap(false));
222 }
223
224 }  // namespace mojo