Upstream version 11.39.244.0
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / browser / android / xwalk_content.cc
index e670c65..0054609 100644 (file)
@@ -14,6 +14,7 @@
 #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"
@@ -35,8 +36,7 @@
 #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;
@@ -45,6 +45,9 @@ using base::android::ScopedJavaLocalRef;
 using content::BrowserThread;
 using content::WebContents;
 using navigation_interception::InterceptNavigationDelegate;
+using xwalk::application_manifest_keys::kDisplay;
+
+namespace keys = xwalk::application_manifest_keys;
 
 namespace xwalk {
 
@@ -68,22 +71,41 @@ class XWalkContentUserData : public base::SupportsUserData::Data {
   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) {
@@ -103,57 +125,77 @@ XWalkContent* XWalkContent::FromWebContents(
   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(
@@ -171,9 +213,8 @@ 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());
 }
 
@@ -211,52 +252,119 @@ jboolean XWalkContent::SetManifest(JNIEnv* env,
       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());
@@ -297,15 +405,15 @@ jboolean XWalkContent::SetState(JNIEnv* env, jobject obj, jbyteArray state) {
   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 {
@@ -340,7 +448,7 @@ void ShowGeolocationPromptHelper(const JavaObjectWeakGlobalRef& java_ref,
 
 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));
@@ -392,4 +500,11 @@ void XWalkContent::HideGeolocationPrompt(const GURL& origin) {
     }
   }
 }
+
+// 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