summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaznacheev@chromium.org <kaznacheev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-21 22:14:59 +0000
committerkaznacheev@chromium.org <kaznacheev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-21 22:14:59 +0000
commit8ee610354614da5dd5f14081e840dc485ac7699f (patch)
tree42bf6dd62e88766d320a26e39acbb5d99b1a5984
parentd51245a1b22d127b0a16e581221aee591d808ab8 (diff)
downloadchromium_src-8ee610354614da5dd5f14081e840dc485ac7699f.zip
chromium_src-8ee610354614da5dd5f14081e840dc485ac7699f.tar.gz
chromium_src-8ee610354614da5dd5f14081e840dc485ac7699f.tar.bz2
DevTools: Make Android tabs unloaded from memory accessible via remote debugging protocol (3/3)
Step 3 out of 3: - Implemented GetTitle, GetURL and RestoreIfNeeded in TabAndroid.h/.cc and TabBase.java - Removed tab id parameter from TabBase#nativeInitWebContents - Introduced a new DevToolsTarget implementation for an unloaded tab (relying on the new TabAndroid methods) - Changed DevToolsServerDelegate to enumerate all tabs (including unloaded) - Cleaned up after Step 1: -- Made the new methods in TabModel pure -- Removed the bridge method TabAndroid::InitWebContents with the old signature. -- Removed TabAndroid::android_id() BUG=272174 Review URL: https://codereview.chromium.org/25627004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229934 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/TabBase.java29
-rw-r--r--chrome/browser/android/dev_tools_server.cc128
-rw-r--r--chrome/browser/android/tab_android.cc36
-rw-r--r--chrome/browser/android/tab_android.h18
-rw-r--r--chrome/browser/ui/android/tab_model/tab_model.cc7
-rw-r--r--chrome/browser/ui/android/tab_model/tab_model.h6
-rw-r--r--chrome/browser/ui/android/tab_model/tab_model_unittest.cc3
7 files changed, 164 insertions, 63 deletions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabBase.java b/chrome/android/java/src/org/chromium/chrome/browser/TabBase.java
index 76ca3da..23f99a6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/TabBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/TabBase.java
@@ -508,7 +508,7 @@ public abstract class TabBase implements NavigationClient {
assert mNativeTabAndroid != 0;
nativeInitWebContents(
- mNativeTabAndroid, mId, mIncognito, mContentViewCore, mWebContentsDelegate);
+ mNativeTabAndroid, mIncognito, mContentViewCore, mWebContentsDelegate);
// In the case where restoring a Tab or showing a prerendered one we already have a
// valid infobar container, no need to recreate one.
@@ -539,6 +539,31 @@ public abstract class TabBase implements NavigationClient {
}
}
+ /**
+ * @return The url associated with the tab.
+ */
+ @CalledByNative
+ public String getUrl() {
+ return getPageInfo() != null ? getPageInfo().getUrl() : "";
+ }
+
+ /**
+ * @return The tab title.
+ */
+ @CalledByNative
+ public String getTitle() {
+ return getPageInfo() != null ? getPageInfo().getTitle() : "";
+ }
+
+ /**
+ * Restores the tab if it is frozen or crashed.
+ * @return true iff tab restore was triggered.
+ */
+ @CalledByNative
+ public boolean restoreIfNeeded() {
+ return false;
+ }
+
private void destroyNativePageInternal() {
if (mNativePage == null) return;
@@ -701,7 +726,7 @@ public abstract class TabBase implements NavigationClient {
sIdCounter.addAndGet(diff);
}
- private native void nativeInitWebContents(int nativeTabAndroid, int id, boolean incognito,
+ private native void nativeInitWebContents(int nativeTabAndroid, boolean incognito,
ContentViewCore contentViewCore, ChromeWebContentsDelegateAndroid delegate);
private native void nativeDestroyWebContents(int nativeTabAndroid, boolean deleteNative);
private native Profile nativeGetProfileAndroid(int nativeTabAndroid);
diff --git a/chrome/browser/android/dev_tools_server.cc b/chrome/browser/android/dev_tools_server.cc
index 87014f8..a716d0d 100644
--- a/chrome/browser/android/dev_tools_server.cc
+++ b/chrome/browser/android/dev_tools_server.cc
@@ -15,7 +15,9 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/android/tab_android.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/devtools/devtools_adb_bridge.h"
#include "chrome/browser/history/top_sites.h"
@@ -30,7 +32,6 @@
#include "content/public/browser/devtools_target.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/content_switches.h"
@@ -44,7 +45,6 @@
#include "webkit/common/user_agent/user_agent_util.h"
using content::DevToolsAgentHost;
-using content::RenderViewHost;
using content::WebContents;
namespace {
@@ -56,9 +56,36 @@ const char kTetheringSocketName[] = "chrome_devtools_tethering_%d_%d";
const char kTargetTypePage[] = "page";
+bool FindTab(const std::string& str_id,
+ TabModel** model_result,
+ int* index_result) {
+ int id;
+ if (!base::StringToInt(str_id, &id))
+ return false;
+
+ for (TabModelList::const_iterator iter = TabModelList::begin();
+ iter != TabModelList::end(); ++iter) {
+ TabModel* model = *iter;
+ for (int i = 0; i < model->GetTabCount(); ++i) {
+ TabAndroid* tab = model->GetTabAt(i);
+ if (id == tab->GetAndroidId()) {
+ *model_result = model;
+ *index_result = i;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
class Target : public content::DevToolsTarget {
public:
- explicit Target(WebContents* web_contents);
+ // Constructor for a tab with a valid WebContents.
+ Target(int id, WebContents* web_contents);
+
+ // Constructor for a tab unloaded from memory.
+ Target(int id, const string16& title, const GURL& url);
virtual std::string GetId() const OVERRIDE { return id_; }
virtual std::string GetType() const OVERRIDE { return kTargetTypePage; }
@@ -69,17 +96,12 @@ class Target : public content::DevToolsTarget {
virtual base::TimeTicks GetLastActivityTime() const OVERRIDE {
return last_activity_time_;
}
- virtual bool IsAttached() const OVERRIDE {
- return agent_host_->IsAttached();
- }
- virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE {
- return agent_host_;
- }
+ virtual bool IsAttached() const OVERRIDE;
+ virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE;
virtual bool Activate() const OVERRIDE;
virtual bool Close() const OVERRIDE;
private:
- scoped_refptr<DevToolsAgentHost> agent_host_;
std::string id_;
std::string title_;
GURL url_;
@@ -87,10 +109,8 @@ class Target : public content::DevToolsTarget {
base::TimeTicks last_activity_time_;
};
-Target::Target(WebContents* web_contents) {
- agent_host_ =
- DevToolsAgentHost::GetOrCreateFor(web_contents->GetRenderViewHost());
- id_ = agent_host_->GetId();
+Target::Target(int id, WebContents* web_contents) {
+ id_ = base::IntToString(id);
title_ = UTF16ToUTF8(net::EscapeForHTML(web_contents->GetTitle()));
url_ = web_contents->GetURL();
content::NavigationController& controller = web_contents->GetController();
@@ -100,22 +120,56 @@ Target::Target(WebContents* web_contents) {
last_activity_time_ = web_contents->GetLastSelectedTime();
}
-bool Target::Activate() const {
- RenderViewHost* rvh = agent_host_->GetRenderViewHost();
- if (!rvh)
+Target::Target(int id, const string16& title, const GURL& url) {
+ id_ = base::IntToString(id);
+ title_ = UTF16ToUTF8(net::EscapeForHTML(title));
+ url_ = url;
+}
+
+bool Target::IsAttached() const {
+ TabModel* model;
+ int index;
+ if (!FindTab(id_, &model, &index))
return false;
- WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
+ WebContents* web_contents = model->GetWebContentsAt(index);
if (!web_contents)
return false;
- web_contents->GetDelegate()->ActivateContents(web_contents);
+ return DevToolsAgentHost::IsDebuggerAttached(web_contents);
+}
+
+scoped_refptr<DevToolsAgentHost> Target::GetAgentHost() const {
+ TabModel* model;
+ int index;
+ if (!FindTab(id_, &model, &index))
+ return NULL;
+ WebContents* web_contents = model->GetWebContentsAt(index);
+ if (!web_contents) {
+ // The tab has been pushed out of memory, pull it back.
+ TabAndroid* tab = model->GetTabAt(index);
+ tab->RestoreIfNeeded();
+ web_contents = model->GetWebContentsAt(index);
+ if (!web_contents)
+ return NULL;
+ }
+ content::RenderViewHost* rvh = web_contents->GetRenderViewHost();
+ return rvh ? DevToolsAgentHost::GetOrCreateFor(rvh) : NULL;
+}
+
+bool Target::Activate() const {
+ TabModel* model;
+ int index;
+ if (!FindTab(id_, &model, &index))
+ return false;
+ model->SetActiveIndex(index);
return true;
}
bool Target::Close() const {
- RenderViewHost* rvh = agent_host_->GetRenderViewHost();
- if (!rvh)
+ TabModel* model;
+ int index;
+ if (!FindTab(id_, &model, &index))
return false;
- rvh->ClosePage();
+ model->CloseTabAt(index);
return true;
}
@@ -169,18 +223,32 @@ class DevToolsServerDelegate : public content::DevToolsHttpHandlerDelegate {
tab_model->CreateTabForTesting(GURL(content::kAboutBlankURL));
if (!web_contents)
return scoped_ptr<content::DevToolsTarget>();
- return scoped_ptr<content::DevToolsTarget>(new Target(web_contents));
+
+ for (int i = 0; i < tab_model->GetTabCount(); ++i) {
+ if (web_contents != tab_model->GetWebContentsAt(i))
+ continue;
+ TabAndroid* tab = tab_model->GetTabAt(i);
+ return scoped_ptr<content::DevToolsTarget>(
+ new Target(tab->GetAndroidId(), web_contents));
+ }
+
+ return scoped_ptr<content::DevToolsTarget>();
}
virtual void EnumerateTargets(TargetCallback callback) OVERRIDE {
TargetList targets;
- std::vector<RenderViewHost*> rvh_list =
- DevToolsAgentHost::GetValidRenderViewHosts();
- for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
- it != rvh_list.end(); ++it) {
- WebContents* web_contents = WebContents::FromRenderViewHost(*it);
- if (web_contents)
- targets.push_back(new Target(web_contents));
+ for (TabModelList::const_iterator iter = TabModelList::begin();
+ iter != TabModelList::end(); ++iter) {
+ TabModel* model = *iter;
+ for (int i = 0; i < model->GetTabCount(); ++i) {
+ TabAndroid* tab = model->GetTabAt(i);
+ WebContents* web_contents = model->GetWebContentsAt(i);
+ targets.push_back(
+ web_contents ?
+ new Target(tab->GetAndroidId(), web_contents) :
+ new Target(
+ tab->GetAndroidId(), tab->GetTitle(), tab->GetURL()));
+ }
}
callback.Run(targets);
}
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc
index becad84..c63c105 100644
--- a/chrome/browser/android/tab_android.cc
+++ b/chrome/browser/android/tab_android.cc
@@ -156,6 +156,32 @@ int TabAndroid::GetAndroidId() const {
return Java_TabBase_getId(env, obj.obj());
}
+string16 TabAndroid::GetTitle() const {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = weak_java_tab_.get(env);
+ if (obj.is_null())
+ return string16();
+ return base::android::ConvertJavaStringToUTF16(
+ Java_TabBase_getTitle(env, obj.obj()));
+}
+
+GURL TabAndroid::GetURL() const {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = weak_java_tab_.get(env);
+ if (obj.is_null())
+ return GURL::EmptyGURL();
+ return GURL(base::android::ConvertJavaStringToUTF8(
+ Java_TabBase_getUrl(env, obj.obj())));
+}
+
+bool TabAndroid::RestoreIfNeeded() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = weak_java_tab_.get(env);
+ if (obj.is_null())
+ return false;
+ return Java_TabBase_restoreIfNeeded(env, obj.obj());
+}
+
content::ContentViewCore* TabAndroid::GetContentViewCore() const {
if (!web_contents())
return NULL;
@@ -231,16 +257,6 @@ void TabAndroid::Observe(int type,
void TabAndroid::InitWebContents(JNIEnv* env,
jobject obj,
- jint tab_id,
- jboolean incognito,
- jobject jcontent_view_core,
- jobject jweb_contents_delegate) {
- InitWebContents(
- env, obj, incognito, jcontent_view_core, jweb_contents_delegate);
-}
-
-void TabAndroid::InitWebContents(JNIEnv* env,
- jobject obj,
jboolean incognito,
jobject jcontent_view_core,
jobject jweb_contents_delegate) {
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h
index 45c6401..31e3266 100644
--- a/chrome/browser/android/tab_android.h
+++ b/chrome/browser/android/tab_android.h
@@ -57,8 +57,15 @@ class TabAndroid : public CoreTabHelperDelegate,
// Return specific id information regarding this TabAndroid.
const SessionID& session_id() const { return session_tab_id_; }
int GetAndroidId() const;
- // TODO(kaznacheev) Remove when there are no more downstream usages.
- int android_id() const { return GetAndroidId(); }
+
+ // Return the tab title.
+ string16 GetTitle() const;
+
+ // Return the tab url.
+ GURL GetURL() const;
+
+ // Restore the tab if it was unloaded from memory.
+ bool RestoreIfNeeded();
// Helper methods to make it easier to access objects from the associated
// WebContents. Can return NULL.
@@ -123,13 +130,6 @@ class TabAndroid : public CoreTabHelperDelegate,
// Methods called from Java via JNI -----------------------------------------
- // TODO(kaznacheev) Remove when there are no more downstream usages.
- virtual void InitWebContents(JNIEnv* env,
- jobject obj,
- jint tab_id,
- jboolean incognito,
- jobject jcontent_view_core,
- jobject jweb_contents_delegate);
virtual void InitWebContents(JNIEnv* env,
jobject obj,
jboolean incognito,
diff --git a/chrome/browser/ui/android/tab_model/tab_model.cc b/chrome/browser/ui/android/tab_model/tab_model.cc
index 4e6bc0e..9eb5f7a 100644
--- a/chrome/browser/ui/android/tab_model/tab_model.cc
+++ b/chrome/browser/ui/android/tab_model/tab_model.cc
@@ -123,10 +123,3 @@ void TabModel::Observe(
NOTREACHED();
}
}
-
-// TODO(kaznacheev) Make these two methods pure as soon as they are
-// implemented in TabModelImpl.
-void TabModel::SetActiveIndex(int index) { }
-
-void TabModel::CloseTabAt(int index) { }
-
diff --git a/chrome/browser/ui/android/tab_model/tab_model.h b/chrome/browser/ui/android/tab_model/tab_model.h
index ea53cc1..129164a 100644
--- a/chrome/browser/ui/android/tab_model/tab_model.h
+++ b/chrome/browser/ui/android/tab_model/tab_model.h
@@ -47,10 +47,8 @@ class TabModel : public content::NotificationObserver,
virtual content::WebContents* GetWebContentsAt(int index) const = 0;
virtual TabAndroid* GetTabAt(int index) const = 0;
- // TODO(kaznacheev) Make these two methods pure as soon as they are
- // implemented in TabModelImpl.
- virtual void SetActiveIndex(int index);
- virtual void CloseTabAt(int index);
+ virtual void SetActiveIndex(int index) = 0;
+ virtual void CloseTabAt(int index) = 0;
// Used for restoring tabs from synced foreign sessions.
virtual void CreateTab(content::WebContents* web_contents) = 0;
diff --git a/chrome/browser/ui/android/tab_model/tab_model_unittest.cc b/chrome/browser/ui/android/tab_model/tab_model_unittest.cc
index 3feaf0f..bcddf79 100644
--- a/chrome/browser/ui/android/tab_model/tab_model_unittest.cc
+++ b/chrome/browser/ui/android/tab_model/tab_model_unittest.cc
@@ -43,7 +43,8 @@ class TestTabModel : public TabModel {
virtual TabAndroid* GetTabAt(int index) const OVERRIDE {
return NULL;
}
-
+ virtual void SetActiveIndex(int index) OVERRIDE {}
+ virtual void CloseTabAt(int index) OVERRIDE {}
};
TEST_F(TabModelTest, TestProfileHandling) {