Index: content/browser/frame_host/navigation_entry_screenshot_manager.cc |
diff --git a/content/browser/frame_host/navigation_entry_screenshot_manager.cc b/content/browser/frame_host/navigation_entry_screenshot_manager.cc |
index b2bf429dc0a6c66a34266a5267ed62267a8aacb6..034220abf9a9f9e92d17e289a66a2210b1e1a84d 100644 |
--- a/content/browser/frame_host/navigation_entry_screenshot_manager.cc |
+++ b/content/browser/frame_host/navigation_entry_screenshot_manager.cc |
@@ -8,9 +8,11 @@ |
#include "base/threading/worker_pool.h" |
#include "content/browser/frame_host/navigation_controller_impl.h" |
#include "content/browser/frame_host/navigation_entry_impl.h" |
+#include "content/browser/frame_host/render_frame_host_manager.h" |
#include "content/browser/renderer_host/render_view_host_impl.h" |
#include "content/public/browser/render_widget_host.h" |
#include "content/public/browser/render_widget_host_view.h" |
+#include "content/public/browser/site_instance.h" |
#include "content/public/common/content_switches.h" |
#include "third_party/skia/include/core/SkCanvas.h" |
#include "third_party/skia/include/core/SkPaint.h" |
@@ -75,6 +77,33 @@ class ScreenshotData : public base::RefCountedThreadSafe<ScreenshotData> { |
DISALLOW_COPY_AND_ASSIGN(ScreenshotData); |
}; |
+// A temporary solution to keep a RenderViewHost and SiteInstanceImpl live |
+// (after cross-process/cross-site navigation) for long enough to get the |
+// screenshot. |
+// TODO(sad): This can be removed when RenderFrameProxy replaces swappedout:// |
+class SiteInstanceKeepAlive { |
+ public: |
+ explicit SiteInstanceKeepAlive(scoped_refptr<SiteInstanceImpl> site_instance) |
+ : site_instance_(site_instance) { |
+ site_instance_->increment_active_view_count(); |
+ site_instance_->GetProcess()->AddPendingView(); |
+ } |
+ |
+ ~SiteInstanceKeepAlive() { |
+ site_instance_->GetProcess()->RemovePendingView(); |
+ site_instance_->decrement_active_view_count(); |
+ if (!site_instance_->active_view_count()) { |
+ RenderFrameHostManager::ShutdownRenderFrameHostsInSiteInstance( |
+ site_instance_->GetId()); |
+ } |
+ } |
+ |
+ private: |
+ scoped_refptr<SiteInstanceImpl> site_instance_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SiteInstanceKeepAlive); |
+}; |
+ |
NavigationEntryScreenshotManager::NavigationEntryScreenshotManager( |
NavigationControllerImpl* owner) |
: owner_(owner), |
@@ -134,11 +163,18 @@ void NavigationEntryScreenshotManager::TakeScreenshotImpl( |
NavigationEntryImpl* entry) { |
DCHECK(host && host->GetView()); |
DCHECK(entry); |
+ scoped_refptr<SiteInstanceImpl> site_instance( |
+ static_cast<SiteInstanceImpl*>(host->GetSiteInstance())); |
+ SiteInstanceKeepAlive* keep_alive = new SiteInstanceKeepAlive(site_instance); |
+ keep_alives_.push_back(keep_alive); |
+ if (!web_contents()) |
+ Observe(owner_->GetWebContents()); |
host->CopyFromBackingStore(gfx::Rect(), |
host->GetView()->GetViewBounds().size(), |
base::Bind(&NavigationEntryScreenshotManager::OnScreenshotTaken, |
screenshot_factory_.GetWeakPtr(), |
- entry->GetUniqueID())); |
+ entry->GetUniqueID(), |
+ keep_alive)); |
} |
void NavigationEntryScreenshotManager::SetMinScreenshotIntervalMS( |
@@ -147,9 +183,20 @@ void NavigationEntryScreenshotManager::SetMinScreenshotIntervalMS( |
min_screenshot_interval_ms_ = interval_ms; |
} |
-void NavigationEntryScreenshotManager::OnScreenshotTaken(int unique_id, |
- bool success, |
- const SkBitmap& bitmap) { |
+void NavigationEntryScreenshotManager::OnScreenshotTaken( |
+ int unique_id, |
+ SiteInstanceKeepAlive* keep_alive, |
+ bool success, |
+ const SkBitmap& bitmap) { |
+ if (keep_alive) { |
+ // |keep_alive| can be NULL in tests. |
+ keep_alives_.erase(std::find(keep_alives_.begin(), keep_alives_.end(), |
+ keep_alive)); |
+ keep_alive = NULL; |
+ if (keep_alives_.empty()) |
+ Observe(NULL); |
+ } |
+ |
NavigationEntryImpl* entry = NULL; |
int entry_count = owner_->GetEntryCount(); |
for (int i = 0; i < entry_count; ++i) { |
@@ -166,8 +213,7 @@ void NavigationEntryScreenshotManager::OnScreenshotTaken(int unique_id, |
} |
if (!success || bitmap.empty() || bitmap.isNull()) { |
- if (!ClearScreenshot(entry)) |
- OnScreenshotSet(entry); |
+ ClearScreenshot(entry); |
return; |
} |
@@ -212,8 +258,8 @@ void NavigationEntryScreenshotManager::OnScreenshotEncodeComplete( |
void NavigationEntryScreenshotManager::OnScreenshotSet( |
NavigationEntryImpl* entry) { |
- if (entry->screenshot().get()) |
- PurgeScreenshotsIfNecessary(); |
+ CHECK(entry->screenshot().get()); |
+ PurgeScreenshotsIfNecessary(); |
} |
bool NavigationEntryScreenshotManager::ClearScreenshot( |
@@ -290,4 +336,12 @@ void NavigationEntryScreenshotManager::PurgeScreenshotsIfNecessary() { |
CHECK_LE(screenshot_count, kMaxScreenshots); |
} |
+void NavigationEntryScreenshotManager::WebContentsDestroyed( |
+ WebContents* contents) { |
+ // The WebContents is going to be destroyed. So discard all pending screenshot |
+ // requests and destroy all the SiteInstanceKeepAlives. |
+ screenshot_factory_.InvalidateWeakPtrs(); |
+ keep_alives_.clear(); |
+} |
+ |
} // namespace content |