Commit 244c761f authored by peter's avatar peter Committed by Commit bot

Feed back to the ServiceTabLauncher when the tab has been created.

This is the second part of being able to open new windows on Android from
a background service, where no Activity may be available. New tabs are
launched with a request ID, which will be used to feed back creation of
the tab to the ServiceTabLauncher.

TBR=jbudorick@chromium.org
BUG=454809

Review URL: https://codereview.chromium.org/904453002

Cr-Commit-Position: refs/heads/master@{#317313}
parent 721247d2
...@@ -5,3 +5,4 @@ M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.Pen ...@@ -5,3 +5,4 @@ M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.Pen
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.webContents In PendingDocumentData.java M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.webContents In PendingDocumentData.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.originalIntent In PendingDocumentData.java M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.originalIntent In PendingDocumentData.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.url In PendingDocumentData.java M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.url In PendingDocumentData.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.requestId In PendingDocumentData.java
...@@ -11,6 +11,7 @@ import android.content.pm.PackageManager.NameNotFoundException; ...@@ -11,6 +11,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log; import android.util.Log;
import org.chromium.base.CalledByNative; import org.chromium.base.CalledByNative;
import org.chromium.content_public.browser.WebContents;
/** /**
* Tab Launcher to be used to launch new tabs from background Android Services, when it is not * Tab Launcher to be used to launch new tabs from background Android Services, when it is not
...@@ -23,6 +24,10 @@ public abstract class ServiceTabLauncher { ...@@ -23,6 +24,10 @@ public abstract class ServiceTabLauncher {
private static final String SERVICE_TAB_LAUNCHER_KEY = private static final String SERVICE_TAB_LAUNCHER_KEY =
"org.chromium.chrome.browser.SERVICE_TAB_LAUNCHER"; "org.chromium.chrome.browser.SERVICE_TAB_LAUNCHER";
// Name of the extra containing the Id of a tab launch request id.
public static final String LAUNCH_REQUEST_ID_EXTRA =
"org.chromium.chrome.browser.ServiceTabLauncher.LAUNCH_REQUEST_ID";
private static ServiceTabLauncher sInstance; private static ServiceTabLauncher sInstance;
/** /**
...@@ -88,4 +93,19 @@ public abstract class ServiceTabLauncher { ...@@ -88,4 +93,19 @@ public abstract class ServiceTabLauncher {
return null; return null;
} }
/**
* To be called by the activity when the WebContents for |requestId| has been created, or has
* been recycled from previous use. The |webContents| must not yet have started provisional
* load for the main frame.
*
* @param requestId Id of the tab launching request which has been fulfilled.
* @param webContents The WebContents instance associated with this request.
*/
public static void onWebContentsForRequestAvailable(int requestId, WebContents webContents) {
nativeOnWebContentsForRequestAvailable(requestId, webContents);
}
private static native void nativeOnWebContentsForRequestAvailable(
int requestId, WebContents webContents);
} }
...@@ -31,4 +31,7 @@ public class PendingDocumentData { ...@@ -31,4 +31,7 @@ public class PendingDocumentData {
/** The original intent */ /** The original intent */
public Intent originalIntent; public Intent originalIntent;
/** The tab launch request Id from the service tab launcher. **/
public int requestId;
} }
\ No newline at end of file
...@@ -8,6 +8,7 @@ import android.app.Activity; ...@@ -8,6 +8,7 @@ import android.app.Activity;
import android.app.FragmentManager; import android.app.FragmentManager;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Browser;
import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarActivity;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
...@@ -29,6 +30,7 @@ import org.chromium.base.library_loader.LibraryProcessType; ...@@ -29,6 +30,7 @@ import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.ProcessInitException; import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.chrome.browser.DevToolsServer; import org.chromium.chrome.browser.DevToolsServer;
import org.chromium.chrome.browser.FileProviderHelper; import org.chromium.chrome.browser.FileProviderHelper;
import org.chromium.chrome.browser.ServiceTabLauncher;
import org.chromium.chrome.browser.Tab; import org.chromium.chrome.browser.Tab;
import org.chromium.chrome.browser.appmenu.AppMenuHandler; import org.chromium.chrome.browser.appmenu.AppMenuHandler;
import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate; import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate;
...@@ -244,10 +246,23 @@ public class ChromeShellActivity extends ActionBarActivity implements AppMenuPro ...@@ -244,10 +246,23 @@ public class ChromeShellActivity extends ActionBarActivity implements AppMenuPro
if (MemoryPressureListener.handleDebugIntent(this, intent.getAction())) return; if (MemoryPressureListener.handleDebugIntent(this, intent.getAction())) return;
String url = getUrlFromIntent(intent); String url = getUrlFromIntent(intent);
if (!TextUtils.isEmpty(url)) { if (TextUtils.isEmpty(url)) return;
ChromeShellTab tab = getActiveTab();
if (tab != null) tab.loadUrlWithSanitization(url); if (intent.getBooleanExtra(Browser.EXTRA_CREATE_NEW_TAB, false)) {
if (mTabManager == null) return;
Tab newTab = mTabManager.createTab(url, TabLaunchType.FROM_LINK);
if (newTab != null && intent.hasExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA)) {
ServiceTabLauncher.onWebContentsForRequestAvailable(
intent.getIntExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA, 0),
newTab.getWebContents());
}
return;
} }
ChromeShellTab tab = getActiveTab();
if (tab != null) tab.loadUrlWithSanitization(url);
} }
@Override @Override
......
...@@ -43,6 +43,8 @@ public class ChromeShellServiceTabLauncher extends ServiceTabLauncher { ...@@ -43,6 +43,8 @@ public class ChromeShellServiceTabLauncher extends ServiceTabLauncher {
break; break;
} }
intent.putExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA, requestId);
// TODO(peter): Support |incognito| when ChromeShell supports that. // TODO(peter): Support |incognito| when ChromeShell supports that.
// TODO(peter): Support the referrer information, extra headers and post data if // TODO(peter): Support the referrer information, extra headers and post data if
// ChromeShell gets support for those properties from intent extras. // ChromeShell gets support for those properties from intent extras.
......
...@@ -8,12 +8,21 @@ ...@@ -8,12 +8,21 @@
#include "base/callback.h" #include "base/callback.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/page_navigator.h" #include "content/public/browser/page_navigator.h"
#include "content/public/browser/web_contents.h"
#include "jni/ServiceTabLauncher_jni.h" #include "jni/ServiceTabLauncher_jni.h"
using base::android::AttachCurrentThread; using base::android::AttachCurrentThread;
using base::android::ConvertUTF8ToJavaString; using base::android::ConvertUTF8ToJavaString;
using base::android::GetApplicationContext; using base::android::GetApplicationContext;
// Called by Java when the WebContents instance for a request Id is available.
void OnWebContentsForRequestAvailable(
JNIEnv* env, jclass clazz, jint request_id, jobject android_web_contents) {
chrome::android::ServiceTabLauncher::GetInstance()->OnTabLaunched(
request_id,
content::WebContents::FromJavaWebContents(android_web_contents));
}
namespace chrome { namespace chrome {
namespace android { namespace android {
...@@ -33,7 +42,7 @@ ServiceTabLauncher::~ServiceTabLauncher() {} ...@@ -33,7 +42,7 @@ ServiceTabLauncher::~ServiceTabLauncher() {}
void ServiceTabLauncher::LaunchTab( void ServiceTabLauncher::LaunchTab(
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
const content::OpenURLParams& params, const content::OpenURLParams& params,
const base::Callback<void(content::WebContents*)>& callback) { const TabLaunchedCallback& callback) {
if (!java_object_.obj()) { if (!java_object_.obj()) {
LOG(ERROR) << "No ServiceTabLauncher is available to launch a new tab."; LOG(ERROR) << "No ServiceTabLauncher is available to launch a new tab.";
callback.Run(nullptr); callback.Run(nullptr);
...@@ -58,10 +67,14 @@ void ServiceTabLauncher::LaunchTab( ...@@ -58,10 +67,14 @@ void ServiceTabLauncher::LaunchTab(
ScopedJavaLocalRef<jbyteArray> post_data; ScopedJavaLocalRef<jbyteArray> post_data;
int request_id = tab_launched_callbacks_.Add(
new TabLaunchedCallback(callback));
DCHECK_GE(request_id, 1);
Java_ServiceTabLauncher_launchTab(env, Java_ServiceTabLauncher_launchTab(env,
java_object_.obj(), java_object_.obj(),
GetApplicationContext(), GetApplicationContext(),
0 /* request_id */, request_id,
browser_context->IsOffTheRecord(), browser_context->IsOffTheRecord(),
url.obj(), url.obj(),
disposition, disposition,
...@@ -69,11 +82,17 @@ void ServiceTabLauncher::LaunchTab( ...@@ -69,11 +82,17 @@ void ServiceTabLauncher::LaunchTab(
params.referrer.policy, params.referrer.policy,
headers.obj(), headers.obj(),
post_data.obj()); post_data.obj());
}
void ServiceTabLauncher::OnTabLaunched(int request_id,
content::WebContents* web_contents) {
TabLaunchedCallback* callback = tab_launched_callbacks_.Lookup(request_id);
DCHECK(callback);
if (callback)
callback->Run(web_contents);
// TODO(peter): We need to wait for the Android Activity to reply to the tab_launched_callbacks_.Remove(request_id);
// launch intent with the ID of the launched Web Contents, so that the Java
// side can invoke a method on the native side with the request id and the
// WebContents enabling us to invoke |callback|. See https://crbug.com/454809.
} }
bool ServiceTabLauncher::RegisterServiceTabLauncher(JNIEnv* env) { bool ServiceTabLauncher::RegisterServiceTabLauncher(JNIEnv* env) {
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/android/jni_android.h" #include "base/android/jni_android.h"
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/id_map.h"
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
namespace content { namespace content {
...@@ -19,8 +20,12 @@ namespace chrome { ...@@ -19,8 +20,12 @@ namespace chrome {
namespace android { namespace android {
// Launcher for creating new tabs on Android from a background service, where // Launcher for creating new tabs on Android from a background service, where
// there may not necessarily be an Activity or a tab model at all. // there may not necessarily be an Activity or a tab model at all. When the
// tab has been launched, the user of this class will be informed with the
// content::WebContents instance associated with the tab.
class ServiceTabLauncher { class ServiceTabLauncher {
using TabLaunchedCallback = base::Callback<void(content::WebContents*)>;
public: public:
// Returns the singleton instance of the service tab launcher. // Returns the singleton instance of the service tab launcher.
static ServiceTabLauncher* GetInstance(); static ServiceTabLauncher* GetInstance();
...@@ -30,7 +35,12 @@ class ServiceTabLauncher { ...@@ -30,7 +35,12 @@ class ServiceTabLauncher {
// the tab is avialable. This method must only be called from the UI thread. // the tab is avialable. This method must only be called from the UI thread.
void LaunchTab(content::BrowserContext* browser_context, void LaunchTab(content::BrowserContext* browser_context,
const content::OpenURLParams& params, const content::OpenURLParams& params,
const base::Callback<void(content::WebContents*)>& callback); const TabLaunchedCallback& callback);
// To be called when the tab for |request_id| has launched, with the
// associated |web_contents|. The WebContents must not yet have started
// the provisional load for the main frame of the navigation.
void OnTabLaunched(int request_id, content::WebContents* web_contents);
static bool RegisterServiceTabLauncher(JNIEnv* env); static bool RegisterServiceTabLauncher(JNIEnv* env);
...@@ -40,6 +50,8 @@ class ServiceTabLauncher { ...@@ -40,6 +50,8 @@ class ServiceTabLauncher {
ServiceTabLauncher(); ServiceTabLauncher();
~ServiceTabLauncher(); ~ServiceTabLauncher();
IDMap<TabLaunchedCallback> tab_launched_callbacks_;
base::android::ScopedJavaGlobalRef<jobject> java_object_; base::android::ScopedJavaGlobalRef<jobject> java_object_;
DISALLOW_COPY_AND_ASSIGN(ServiceTabLauncher); DISALLOW_COPY_AND_ASSIGN(ServiceTabLauncher);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment