diff options
author | kaznacheev@chromium.org <kaznacheev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-21 22:14:59 +0000 |
---|---|---|
committer | kaznacheev@chromium.org <kaznacheev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-21 22:14:59 +0000 |
commit | 8ee610354614da5dd5f14081e840dc485ac7699f (patch) | |
tree | 42bf6dd62e88766d320a26e39acbb5d99b1a5984 | |
parent | d51245a1b22d127b0a16e581221aee591d808ab8 (diff) | |
download | chromium_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.java | 29 | ||||
-rw-r--r-- | chrome/browser/android/dev_tools_server.cc | 128 | ||||
-rw-r--r-- | chrome/browser/android/tab_android.cc | 36 | ||||
-rw-r--r-- | chrome/browser/android/tab_android.h | 18 | ||||
-rw-r--r-- | chrome/browser/ui/android/tab_model/tab_model.cc | 7 | ||||
-rw-r--r-- | chrome/browser/ui/android/tab_model/tab_model.h | 6 | ||||
-rw-r--r-- | chrome/browser/ui/android/tab_model/tab_model_unittest.cc | 3 |
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) { |