1 // Copyright (c) 2013 Intel Corporation. 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 "xwalk/runtime/browser/runtime.h"
10 #include "base/command_line.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/public/browser/navigation_entry.h"
14 #include "content/public/browser/notification_details.h"
15 #include "content/public/browser/notification_service.h"
16 #include "content/public/browser/render_frame_host.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "grit/xwalk_resources.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/gfx/image/image_skia.h"
23 #include "ui/gfx/native_widget_types.h"
24 #include "xwalk/runtime/browser/image_util.h"
25 #include "xwalk/runtime/browser/media/media_capture_devices_dispatcher.h"
26 #include "xwalk/runtime/browser/runtime_file_select_helper.h"
27 #include "xwalk/runtime/browser/ui/color_chooser.h"
28 #include "xwalk/runtime/browser/xwalk_browser_context.h"
29 #include "xwalk/runtime/browser/xwalk_runner.h"
30 #include "xwalk/runtime/common/xwalk_notification_types.h"
31 #include "xwalk/runtime/common/xwalk_switches.h"
34 #include "content/public/browser/site_instance.h"
35 #include "xwalk/application/browser/application.h"
36 #include "xwalk/application/browser/application_system.h"
37 #include "xwalk/application/browser/application_service.h"
40 #if !defined(OS_ANDROID)
41 #include "xwalk/runtime/browser/runtime_ui_delegate.h"
44 using content::FaviconURL;
45 using content::WebContents;
50 Runtime* Runtime::Create(XWalkBrowserContext* browser_context,
51 content::SiteInstance* site) {
52 WebContents::CreateParams params(browser_context, site);
53 params.routing_id = MSG_ROUTING_NONE;
54 WebContents* web_contents = WebContents::Create(params);
56 return new Runtime(web_contents);
59 Runtime::Runtime(content::WebContents* web_contents)
60 : WebContentsObserver(web_contents),
61 web_contents_(web_contents),
62 fullscreen_options_(NO_FULLSCREEN),
63 remote_debugging_enabled_(false),
64 ui_delegate_(nullptr),
66 weak_ptr_factory_(this) {
67 web_contents_->SetDelegate(this);
69 content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
70 content::Source<content::WebContents>(web_contents_.get()));
75 ui_delegate_->DeleteDelegate();
78 void Runtime::LoadURL(const GURL& url) {
79 content::NavigationController::LoadURLParams params(url);
80 params.transition_type = ui::PageTransitionFromInt(
81 ui::PAGE_TRANSITION_TYPED |
82 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
83 web_contents_->GetController().LoadURLWithParams(params);
84 web_contents_->Focus();
87 void Runtime::Show() {
92 void Runtime::Close() {
93 web_contents_->Close();
96 NativeAppWindow* Runtime::window() {
98 return static_cast<DefaultRuntimeUIDelegate*>(ui_delegate_)->window();
102 content::RenderProcessHost* Runtime::GetRenderProcessHost() {
103 return web_contents_->GetRenderProcessHost();
106 //////////////////////////////////////////////////////
107 // content::WebContentsDelegate:
108 //////////////////////////////////////////////////////
109 content::WebContents* Runtime::OpenURLFromTab(
110 content::WebContents* source, const content::OpenURLParams& params) {
111 #if defined(OS_ANDROID)
112 DCHECK(params.disposition == CURRENT_TAB);
113 source->GetController().LoadURL(
114 params.url, params.referrer, params.transition, std::string());
116 if (params.disposition == CURRENT_TAB) {
117 source->GetController().LoadURL(
118 params.url, params.referrer, params.transition, std::string());
119 } else if (params.disposition == NEW_WINDOW ||
120 params.disposition == NEW_POPUP ||
121 params.disposition == NEW_FOREGROUND_TAB ||
122 params.disposition == NEW_BACKGROUND_TAB) {
123 // TODO(xinchao): Excecuting JaveScript code is a temporary solution,
124 // need to be implemented by creating a new runtime window instead.
125 web_contents()->GetFocusedFrame()->ExecuteJavaScript(
126 base::UTF8ToUTF16("window.open('" + params.url.spec() + "')"));
132 void Runtime::LoadingStateChanged(content::WebContents* source,
133 bool to_different_document) {
136 void Runtime::ToggleFullscreenModeForTab(content::WebContents* web_contents,
137 bool enter_fullscreen) {
138 if (enter_fullscreen)
139 fullscreen_options_ |= FULLSCREEN_FOR_TAB;
141 fullscreen_options_ &= ~FULLSCREEN_FOR_TAB;
143 ui_delegate_->SetFullscreen(
144 enter_fullscreen || (fullscreen_options_ & FULLSCREEN_FOR_LAUNCH));
147 bool Runtime::IsFullscreenForTabOrPending(
148 const content::WebContents* web_contents) const {
149 return (fullscreen_options_ & FULLSCREEN_FOR_TAB) != 0;
152 void Runtime::RequestToLockMouse(content::WebContents* web_contents,
154 bool last_unlocked_by_target) {
155 web_contents->GotResponseToLockMouseRequest(true);
158 void Runtime::CloseContents(content::WebContents* source) {
160 ui_delegate_->Close();
163 observer_->OnRuntimeClosed(this);
166 bool Runtime::CanOverscrollContent() const {
170 bool Runtime::PreHandleKeyboardEvent(
171 content::WebContents* source,
172 const content::NativeWebKeyboardEvent& event,
173 bool* is_keyboard_shortcut) {
174 // Escape exits tabbed fullscreen mode.
175 if (event.windowsKeyCode == 27 && IsFullscreenForTabOrPending(source)) {
176 ToggleFullscreenModeForTab(source, false);
182 void Runtime::HandleKeyboardEvent(
183 content::WebContents* source,
184 const content::NativeWebKeyboardEvent& event) {
187 void Runtime::WebContentsCreated(
188 content::WebContents* source_contents,
189 int opener_render_frame_id,
190 const base::string16& frame_name,
191 const GURL& target_url,
192 content::WebContents* new_contents) {
194 observer_->OnNewRuntimeAdded(new Runtime(new_contents));
196 LOG(WARNING) << "New web contents is left unhandled.";
199 void Runtime::DidNavigateMainFramePostCommit(
200 content::WebContents* web_contents) {
203 content::JavaScriptDialogManager* Runtime::GetJavaScriptDialogManager() {
207 void Runtime::ActivateContents(content::WebContents* contents) {
208 contents->GetRenderViewHost()->Focus();
211 void Runtime::DeactivateContents(content::WebContents* contents) {
212 contents->GetRenderViewHost()->Blur();
215 content::ColorChooser* Runtime::OpenColorChooser(
216 content::WebContents* web_contents,
217 SkColor initial_color,
218 const std::vector<content::ColorSuggestion>& suggestions) {
219 #if defined(TOOLKIT_VIEWS)
220 return xwalk::ShowColorChooser(web_contents, initial_color);
222 return WebContentsDelegate::OpenColorChooser(web_contents,
228 void Runtime::RunFileChooser(
229 content::WebContents* web_contents,
230 const content::FileChooserParams& params) {
231 #if defined(USE_AURA) && defined(OS_LINUX)
234 RuntimeFileSelectHelper::RunFileChooser(web_contents, params);
238 void Runtime::EnumerateDirectory(content::WebContents* web_contents,
240 const base::FilePath& path) {
241 #if defined(USE_AURA) && defined(OS_LINUX)
244 RuntimeFileSelectHelper::EnumerateDirectory(web_contents, request_id, path);
248 void Runtime::DidUpdateFaviconURL(const std::vector<FaviconURL>& candidates) {
249 DLOG(INFO) << "Candidates: ";
250 for (size_t i = 0; i < candidates.size(); ++i)
251 DLOG(INFO) << candidates[i].icon_url.spec();
253 if (candidates.empty())
256 // Avoid using any previous download.
257 weak_ptr_factory_.InvalidateWeakPtrs();
259 // We only select the first favicon as the window app icon.
260 FaviconURL favicon = candidates[0];
261 // Passing 0 as the |image_size| parameter results in only receiving the first
262 // bitmap, according to content/public/browser/web_contents.h
263 web_contents()->DownloadImage(
265 true, // Is a favicon
266 0, // No maximum size
268 &Runtime::DidDownloadFavicon, weak_ptr_factory_.GetWeakPtr()));
271 void Runtime::DidDownloadFavicon(int id,
272 int http_status_code,
273 const GURL& image_url,
274 const std::vector<SkBitmap>& bitmaps,
275 const std::vector<gfx::Size>& sizes) {
278 app_icon_ = gfx::Image::CreateFrom1xBitmap(bitmaps[0]);
280 ui_delegate_->UpdateIcon(app_icon_);
283 void Runtime::Observe(int type,
284 const content::NotificationSource& source,
285 const content::NotificationDetails& details) {
286 if (type == content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) {
287 std::pair<content::NavigationEntry*, bool>* title =
288 content::Details<std::pair<content::NavigationEntry*, bool> >(
291 if (title->first && ui_delegate_)
292 ui_delegate_->UpdateTitle(title->first->GetTitle());
296 void Runtime::RequestMediaAccessPermission(
297 content::WebContents* web_contents,
298 const content::MediaStreamRequest& request,
299 const content::MediaResponseCallback& callback) {
300 XWalkMediaCaptureDevicesDispatcher::RunRequestMediaAccessPermission(
301 web_contents, request, callback);