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.
5 #include "mojo/services/html_viewer/html_document_view.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"
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);
45 Target WebNavigationPolicyToNavigationTarget(
46 blink::WebNavigationPolicy 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;
56 return TARGET_DEFAULT;
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.
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())
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.
81 HTMLDocumentView::HTMLDocumentView(ServiceProvider* service_provider,
82 ViewManager* view_manager)
83 : view_manager_(view_manager),
86 repaint_pending_(false),
87 navigator_host_(service_provider),
91 HTMLDocumentView::~HTMLDocumentView() {
95 root_->RemoveObserver(this);
98 void HTMLDocumentView::AttachToView(View* view) {
100 root_->SetColor(SK_ColorCYAN); // Dummy background color.
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());
107 root_->AddObserver(this);
110 void HTMLDocumentView::Load(URLResponsePtr response) {
113 GURL url(response->url);
115 WebURLRequestExtraData* extra_data = new WebURLRequestExtraData;
116 extra_data->synthetic_response = response.Pass();
118 blink::WebURLRequest web_request;
119 web_request.initialize();
120 web_request.setURL(url);
121 web_request.setExtraData(extra_data);
123 web_view_->mainFrame()->loadRequest(web_request);
126 blink::WebStorageNamespace* HTMLDocumentView::createSessionStorageNamespace() {
127 return new WebStorageNamespaceImpl();
130 void HTMLDocumentView::didInvalidateRect(const blink::WebRect& rect) {
131 if (!repaint_pending_) {
132 repaint_pending_ = true;
133 base::ThreadTaskRunnerHandle::Get()->PostTask(
135 base::Bind(&HTMLDocumentView::Repaint, weak_factory_.GetWeakPtr()));
139 bool HTMLDocumentView::allowsBrokenNullLayerTreeView() const {
140 // TODO(darin): Switch to using compositor bindings.
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.
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();
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;
161 NavigationDetailsPtr nav_details(NavigationDetails::New());
162 nav_details->request = URLRequest::From(request);
164 navigator_host_->RequestNavigate(
166 WebNavigationPolicyToNavigationTarget(default_policy),
169 return blink::WebNavigationPolicyIgnore;
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) {
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());
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());
193 void HTMLDocumentView::OnViewDestroyed(View* view) {
194 DCHECK_EQ(view, root_);
195 view->RemoveObserver(this);
199 void HTMLDocumentView::OnViewInputEvent(View* view, const EventPtr& event) {
200 scoped_ptr<blink::WebInputEvent> web_event =
201 TypeConverter<EventPtr, scoped_ptr<blink::WebInputEvent> >::ConvertTo(
204 web_view_->handleInputEvent(*web_event);
207 void HTMLDocumentView::Repaint() {
208 repaint_pending_ = false;
210 web_view_->animate(0.0);
213 int width = web_view_->size().width;
214 int height = web_view_->size().height;
216 skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(SkCanvas::NewRaster(
217 SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType)));
219 web_view_->paint(canvas.get(), gfx::Rect(0, 0, width, height));
221 root_->SetContents(canvas->getDevice()->accessBitmap(false));