#include "base/android/jni_string.h"
#include "base/base_paths_android.h"
#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/path_service.h"
#include "base/pickle.h"
#include "content/public/browser/browser_context.h"
#include "xwalk/runtime/browser/android/xwalk_web_contents_delegate.h"
#include "xwalk/runtime/browser/runtime_context.h"
#include "xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate_android.h"
-#include "xwalk/runtime/browser/xwalk_browser_main_parts.h"
-#include "xwalk/runtime/browser/xwalk_content_browser_client.h"
+#include "xwalk/runtime/browser/xwalk_runner.h"
#include "jni/XWalkContent_jni.h"
using base::android::AttachCurrentThread;
using content::BrowserThread;
using content::WebContents;
using navigation_interception::InterceptNavigationDelegate;
+using xwalk::application_manifest_keys::kDisplay;
+
+namespace keys = xwalk::application_manifest_keys;
namespace xwalk {
XWalkContent* content_;
};
-} // namespace
+// FIXME(wang16): Remove following methods after deprecated fields
+// are not supported any more.
+void PrintManifestDeprecationWarning(std::string field) {
+ LOG(WARNING) << "\"" << field << "\" is deprecated for Crosswalk. "
+ << "Please follow "
+ << "https://www.crosswalk-project.org/#documentation/manifest.";
+}
-XWalkContent::XWalkContent(JNIEnv* env,
- jobject obj,
- jobject web_contents_delegate,
- jobject contents_client_bridge)
- : java_ref_(env, obj),
- web_contents_delegate_(
- new XWalkWebContentsDelegate(env, web_contents_delegate)),
- contents_client_bridge_(
- new XWalkContentsClientBridge(env, contents_client_bridge)) {
+bool ManifestHasPath(const xwalk::application::Manifest& manifest,
+ const std::string& path,
+ const std::string& deprecated_path) {
+ if (manifest.HasPath(path))
+ return true;
+ if (manifest.HasPath(deprecated_path)) {
+ PrintManifestDeprecationWarning(deprecated_path);
+ return true;
+ }
+ return false;
}
-XWalkContent::~XWalkContent() {
+bool ManifestGetString(const xwalk::application::Manifest& manifest,
+ const std::string& path,
+ const std::string& deprecated_path,
+ std::string* out_value) {
+ if (manifest.GetString(path, out_value))
+ return true;
+ if (manifest.GetString(deprecated_path, out_value)) {
+ PrintManifestDeprecationWarning(deprecated_path);
+ return true;
+ }
+ return false;
}
+} // namespace
+
// static
XWalkContent* XWalkContent::FromID(int render_process_id,
int render_view_id) {
return XWalkContentUserData::GetContents(web_contents);
}
-jint XWalkContent::GetWebContents(
- JNIEnv* env, jobject obj, jobject io_thread_client,
- jobject intercept_navigation_delegate) {
- if (!web_contents_) {
- web_contents_.reset(CreateWebContents(env, io_thread_client,
- intercept_navigation_delegate));
-
- render_view_host_ext_.reset(
- new XWalkRenderViewHostExt(web_contents_.get()));
- }
- return reinterpret_cast<jint>(web_contents_.get());
+XWalkContent::XWalkContent(scoped_ptr<content::WebContents> web_contents)
+ : web_contents_(web_contents.Pass()) {
}
-content::WebContents* XWalkContent::CreateWebContents(
- JNIEnv* env, jobject io_thread_client,
- jobject intercept_navigation_delegate) {
+XWalkContent::~XWalkContent() {
+}
- XWalkBrowserMainParts* main_parts =
- XWalkContentBrowserClient::Get()->main_parts();
- CHECK(main_parts);
- // FIXME : need a better way to get context.
- RuntimeContext* runtime_context = main_parts->runtime_context();
- CHECK(runtime_context);
+void XWalkContent::SetJavaPeers(JNIEnv* env,
+ jobject obj,
+ jobject xwalk_content,
+ jobject web_contents_delegate,
+ jobject contents_client_bridge,
+ jobject io_thread_client,
+ jobject intercept_navigation_delegate) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ java_ref_ = JavaObjectWeakGlobalRef(env, xwalk_content);
- content::WebContents* web_contents = content::WebContents::Create(
- content::WebContents::CreateParams(runtime_context));
+ web_contents_delegate_.reset(new XWalkWebContentsDelegate(
+ env, web_contents_delegate));
+ contents_client_bridge_.reset(new XWalkContentsClientBridge(
+ env, contents_client_bridge, web_contents_.get()));
- web_contents->SetUserData(kXWalkContentUserDataKey,
- new XWalkContentUserData(this));
+ web_contents_->SetUserData(
+ kXWalkContentUserDataKey, new XWalkContentUserData(this));
- XWalkContentsIoThreadClientImpl::RegisterPendingContents(web_contents);
+ XWalkContentsIoThreadClientImpl::RegisterPendingContents(web_contents_.get());
// XWalk does not use disambiguation popup for multiple targets.
content::RendererPreferences* prefs =
- web_contents->GetMutableRendererPrefs();
+ web_contents_->GetMutableRendererPrefs();
prefs->tap_multiple_targets_strategy =
content::TAP_MULTIPLE_TARGETS_STRATEGY_NONE;
- XWalkContentsClientBridgeBase::Associate(web_contents,
+ XWalkContentsClientBridgeBase::Associate(web_contents_.get(),
contents_client_bridge_.get());
- XWalkContentsIoThreadClientImpl::Associate(web_contents,
+ XWalkContentsIoThreadClientImpl::Associate(web_contents_.get(),
ScopedJavaLocalRef<jobject>(env, io_thread_client));
- int child_id = web_contents->GetRenderProcessHost()->GetID();
- int route_id = web_contents->GetRoutingID();
+ int render_process_id = web_contents_->GetRenderProcessHost()->GetID();
+ int render_frame_id = web_contents_->GetRoutingID();
RuntimeResourceDispatcherHostDelegateAndroid::OnIoThreadClientReady(
- child_id, route_id);
- InterceptNavigationDelegate::Associate(web_contents,
+ render_process_id, render_frame_id);
+ InterceptNavigationDelegate::Associate(web_contents_.get(),
make_scoped_ptr(new InterceptNavigationDelegate(
env, intercept_navigation_delegate)));
- web_contents->SetDelegate(web_contents_delegate_.get());
- return web_contents;
+ web_contents_->SetDelegate(web_contents_delegate_.get());
+
+ render_view_host_ext_.reset(new XWalkRenderViewHostExt(web_contents_.get()));
+}
+
+jlong XWalkContent::GetWebContents(JNIEnv* env, jobject obj) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(web_contents_);
+ return reinterpret_cast<intptr_t>(web_contents_.get());
+}
+
+void XWalkContent::SetPendingWebContentsForPopup(
+ scoped_ptr<content::WebContents> pending) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (pending_contents_.get()) {
+ // TODO(benm): Support holding multiple pop up window requests.
+ LOG(WARNING) << "Blocking popup window creation as an outstanding "
+ << "popup window is still pending.";
+ base::MessageLoop::current()->DeleteSoon(FROM_HERE, pending.release());
+ return;
+ }
+ pending_contents_.reset(new XWalkContent(pending.Pass()));
+}
+
+jlong XWalkContent::ReleasePopupXWalkContent(JNIEnv* env, jobject obj) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ return reinterpret_cast<intptr_t>(pending_contents_.release());
}
void XWalkContent::ClearCache(
ScopedJavaLocalRef<jstring> XWalkContent::DevToolsAgentId(JNIEnv* env,
jobject obj) {
- content::RenderViewHost* rvh = web_contents_->GetRenderViewHost();
scoped_refptr<content::DevToolsAgentHost> agent_host(
- content::DevToolsAgentHost::GetOrCreateFor(rvh));
+ content::DevToolsAgentHost::GetOrCreateFor(web_contents_.get()));
return base::android::ConvertUTF8ToJavaString(env, agent_host->GetId());
}
manifest_dictionary_ptr(manifest_dictionary);
xwalk::application::Manifest manifest(
- xwalk::application::Manifest::INVALID_TYPE,
manifest_dictionary_ptr.Pass());
std::string url;
- if (manifest.GetString(
- xwalk::application_manifest_keys::kLaunchLocalPathKey, &url)) {
+ if (manifest.GetString(keys::kStartURLKey, &url)) {
+ std::string scheme = GURL(url).scheme();
+ if (scheme.empty())
+ url = path_str + url;
+ } else if (manifest.GetString(keys::kLaunchLocalPathKey, &url)) {
+ PrintManifestDeprecationWarning(keys::kLaunchLocalPathKey);
// According to original proposal for "app:launch:local_path", the "http"
// and "https" schemes are supported. So |url| should do nothing when it
// already has "http" or "https" scheme.
- std::string lower_url = url;
- std::transform(lower_url.begin(), lower_url.end(),
- lower_url.begin(), std::tolower);
- if (lower_url.find(content::kHttpScheme) == std::string::npos &&
- lower_url.find(content::kHttpsScheme) == std::string::npos) {
+ std::string scheme = GURL(url).scheme();
+ if (scheme != url::kHttpScheme && scheme != url::kHttpsScheme)
url = path_str + url;
- }
+ } else if (manifest.GetString(keys::kLaunchWebURLKey, &url)) {
+ PrintManifestDeprecationWarning(keys::kLaunchWebURLKey);
} else {
- manifest.GetString(
- xwalk::application_manifest_keys::kLaunchWebURLKey, &url);
+ NOTIMPLEMENTED();
}
+ std::string match_patterns;
+ const base::ListValue* xwalk_hosts = NULL;
+ if (manifest.GetList(
+ xwalk::application_manifest_keys::kXWalkHostsKey, &xwalk_hosts)) {
+ base::JSONWriter::Write(xwalk_hosts, &match_patterns);
+ }
+ render_view_host_ext_->SetOriginAccessWhitelist(url, match_patterns);
+
std::string csp;
- manifest.GetString(
- xwalk::application_manifest_keys::kCSPKey, &csp);
- XWalkBrowserMainParts* main_parts =
- XWalkContentBrowserClient::Get()->main_parts();
- CHECK(main_parts);
- RuntimeContext* runtime_context = main_parts->runtime_context();
+ ManifestGetString(manifest, keys::kCSPKey, keys::kDeprecatedCSPKey, &csp);
+ RuntimeContext* runtime_context =
+ XWalkRunner::GetInstance()->runtime_context();
CHECK(runtime_context);
runtime_context->SetCSPString(csp);
ScopedJavaLocalRef<jstring> url_buffer =
base::android::ConvertUTF8ToJavaString(env, url);
+ if (manifest.HasPath(kDisplay)) {
+ std::string display_string;
+ manifest.GetString(kDisplay, &display_string);
+ // TODO(David): update the handling process of the display strings
+ // including fullscreen etc.
+ bool display_as_fullscreen = (
+ display_string.find("fullscreen") != std::string::npos);
+ Java_XWalkContent_onGetFullscreenFlagFromManifest(
+ env, obj, display_as_fullscreen ? JNI_TRUE : JNI_FALSE);
+ }
+
// Check whether need to display launch screen. (Read from manifest.json)
- if (manifest.HasPath(
- xwalk::application_manifest_keys::kLaunchScreen)) {
+ if (ManifestHasPath(manifest,
+ keys::kXWalkLaunchScreen,
+ keys::kLaunchScreen)) {
std::string ready_when;
- // Get the value of 'ready_when' from manifest.json and callback
- // to Java side.
- manifest.GetString(
- xwalk::application_manifest_keys::kLaunchScreenReadyWhen, &ready_when);
+ // Get the value of 'ready_when' from manifest.json
+ ManifestGetString(manifest,
+ keys::kXWalkLaunchScreenReadyWhen,
+ keys::kLaunchScreenReadyWhen,
+ &ready_when);
ScopedJavaLocalRef<jstring> ready_when_buffer =
base::android::ConvertUTF8ToJavaString(env, ready_when);
+
+ // Get the value of 'image_border'
+ // 1. When 'launch_screen.[orientation]' was defined, but no 'image_border'
+ // The value of 'image_border' will be set as 'empty'.
+ // 2. Otherwise, there is no 'launch_screen.[orientation]' defined,
+ // The value of 'image_border' will be empty.
+ const char empty[] = "empty";
+ std::string image_border_default;
+ ManifestGetString(manifest,
+ keys::kXWalkLaunchScreenImageBorderDefault,
+ keys::kLaunchScreenImageBorderDefault,
+ &image_border_default);
+ if (image_border_default.empty() &&
+ ManifestHasPath(manifest,
+ keys::kXWalkLaunchScreenDefault,
+ keys::kLaunchScreenDefault)) {
+ image_border_default = empty;
+ }
+
+ std::string image_border_landscape;
+ ManifestGetString(manifest,
+ keys::kXWalkLaunchScreenImageBorderLandscape,
+ keys::kLaunchScreenImageBorderLandscape,
+ &image_border_landscape);
+ if (image_border_landscape.empty() &&
+ ManifestHasPath(manifest,
+ keys::kXWalkLaunchScreenLandscape,
+ keys::kLaunchScreenLandscape)) {
+ image_border_landscape = empty;
+ }
+
+ std::string image_border_portrait;
+ ManifestGetString(manifest,
+ keys::kXWalkLaunchScreenImageBorderPortrait,
+ keys::kLaunchScreenImageBorderPortrait,
+ &image_border_portrait);
+ if (image_border_portrait.empty() &&
+ ManifestHasPath(manifest,
+ keys::kXWalkLaunchScreenPortrait,
+ keys::kLaunchScreenPortrait)) {
+ image_border_portrait = empty;
+ }
+
+ std::string image_border = image_border_default + ';' +
+ image_border_landscape + ';' + image_border_portrait;
+ ScopedJavaLocalRef<jstring> image_border_buffer =
+ base::android::ConvertUTF8ToJavaString(env, image_border);
+
Java_XWalkContent_onGetUrlAndLaunchScreenFromManifest(
- env, obj, url_buffer.obj(), ready_when_buffer.obj());
+ env, obj, url_buffer.obj(), ready_when_buffer.obj(),
+ image_border_buffer.obj());
} else {
// No need to display launch screen, load the url directly.
Java_XWalkContent_onGetUrlFromManifest(env, obj, url_buffer.obj());
return RestoreFromPickle(&iterator, web_contents_.get());
}
-static jint Init(JNIEnv* env, jobject obj, jobject web_contents_delegate,
- jobject contents_client_bridge) {
- XWalkContent* xwalk_core_content =
- new XWalkContent(env, obj, web_contents_delegate, contents_client_bridge);
- return reinterpret_cast<jint>(xwalk_core_content);
+static jlong Init(JNIEnv* env, jobject obj) {
+ scoped_ptr<WebContents> web_contents(content::WebContents::Create(
+ content::WebContents::CreateParams(
+ XWalkRunner::GetInstance()->runtime_context())));
+ return reinterpret_cast<intptr_t>(new XWalkContent(web_contents.Pass()));
}
bool RegisterXWalkContent(JNIEnv* env) {
- return RegisterNativesImpl(env) >= 0;
+ return RegisterNativesImpl(env);
}
namespace {
void XWalkContent::ShowGeolocationPrompt(
const GURL& requesting_frame,
- const base::Callback<void(bool)>& callback) {
+ const base::Callback<void(bool)>& callback) { // NOLINT
GURL origin = requesting_frame.GetOrigin();
bool show_prompt = pending_geolocation_prompts_.empty();
pending_geolocation_prompts_.push_back(OriginCallback(origin, callback));
}
}
}
+
+// Called by Java.
+void XWalkContent::SetBackgroundColor(JNIEnv* env, jobject obj, jint color) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ render_view_host_ext_->SetBackgroundColor(color);
+}
+
} // namespace xwalk