Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Unified Diff: content/browser/appcache/appcache_frame_node_navigation.cc

Issue 2501343003: PlzNavigate: AppCache support. (Closed)
Patch Set: Add DCHECKs for PlzNavigate and fix a double Release problem which caused one unit_test to fail wit… Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/appcache/appcache_frame_node_navigation.cc
diff --git a/content/browser/appcache/appcache_frame_node_navigation.cc b/content/browser/appcache/appcache_frame_node_navigation.cc
new file mode 100644
index 0000000000000000000000000000000000000000..afe4c3f262ccfb4e34ee64184f3c754945bcb0eb
--- /dev/null
+++ b/content/browser/appcache/appcache_frame_node_navigation.cc
@@ -0,0 +1,183 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/appcache/appcache_frame_node_navigation.h"
+
+#include <map>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/lazy_instance.h"
+#include "content/browser/appcache/appcache_dispatcher_host.h"
+#include "content/browser/appcache/chrome_appcache_service.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/browser_side_navigation_policy.h"
+
+namespace {
+
+typedef std::map<int, content::AppCacheFrameNavigationHandler*>
+ FrameToNavigationHandlerMap;
+base::LazyInstance<FrameToNavigationHandlerMap> g_frame_navigation_handler_map;
+
+// PlzNavigate: Used to generate the host id for a navigation initiated by the
+// browser. Starts at -2 and keeps going down.
+static int g_next_appcache_host_id = -2;
+
+} // namespace
+
+namespace content {
+
+AppCacheFrameNavigationHandler::AppCacheFrameNavigationHandler(
+ ChromeAppCacheService* appcache_service,
+ int frame_node_id)
+ : frame_node_id_(frame_node_id),
+ appcache_service_(appcache_service),
+ frontend_proxy_(this),
+ commit_received_(false),
+ weak_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ AddRef();
+ g_frame_navigation_handler_map.Get()[frame_node_id] = this;
+}
+
+AppCacheFrameNavigationHandler::~AppCacheFrameNavigationHandler() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+// static
+int AppCacheFrameNavigationHandler::BeginNavigation(
+ AppCacheServiceImpl* appcache_service,
+ int frame_node_id) {
+ DCHECK(IsBrowserSideNavigationEnabled());
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!appcache_service)
+ return kAppCacheNoHostId;
+
+ // If we have an existing AppCacheFrameNavigationHandler for the
+ // |frame_node_id| passed in, we have no choice at this point but to
+ // release that instance.
+ // Please note this only happens if the tasks we posted below never
+ // ran.
+ FrameToNavigationHandlerMap::iterator index =
+ g_frame_navigation_handler_map.Get().find(frame_node_id);
+ if (index != g_frame_navigation_handler_map.Get().end()) {
+ if (!index->second->commit_received_)
+ index->second->Release();
+ }
+
+ AppCacheFrameNavigationHandler* navigation_handler =
+ new AppCacheFrameNavigationHandler(
+ static_cast<ChromeAppCacheService*>(appcache_service), frame_node_id);
+ g_frame_navigation_handler_map.Get()[frame_node_id] = navigation_handler;
+
+ int host_id = g_next_appcache_host_id--;
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AppCacheFrameNavigationHandler::RegisterPendingHostHelper,
+ navigation_handler->weak_factory_.GetWeakPtr(), host_id));
+
+ return host_id;
+}
+
+// static
+void AppCacheFrameNavigationHandler::CommitNavigation(int frame_node_id,
+ int process_id) {
+ DCHECK(IsBrowserSideNavigationEnabled());
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ DCHECK(g_frame_navigation_handler_map.Get().find(frame_node_id) !=
+ g_frame_navigation_handler_map.Get().end());
+
+ g_frame_navigation_handler_map.Get()[frame_node_id]->commit_received_ = true;
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AppCacheFrameNavigationHandler::CommitNavigationHelper,
+ g_frame_navigation_handler_map.Get()[frame_node_id]
+ ->weak_factory_.GetWeakPtr(),
+ process_id));
+}
+
+void AppCacheFrameNavigationHandler::FailedNavigation(int frame_node_id) {
+ DCHECK(IsBrowserSideNavigationEnabled());
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ FrameToNavigationHandlerMap::iterator index =
+ g_frame_navigation_handler_map.Get().find(frame_node_id);
+
+ DCHECK(index != g_frame_navigation_handler_map.Get().end());
+
+ index->second->Release();
+}
+
+bool AppCacheFrameNavigationHandler::Send(IPC::Message* msg) {
+ DCHECK(false);
+ return false;
+}
+
+void AppCacheFrameNavigationHandler::RegisterPendingHostHelper(int host_id) {
+ DCHECK(IsBrowserSideNavigationEnabled());
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!backend_impl_.get());
+ backend_impl_.reset(new AppCacheBackendImpl);
+ backend_impl_->Initialize(appcache_service_.get(), &frontend_proxy_, -1,
+ frame_node_id_);
+ backend_impl_->RegisterHost(host_id);
+}
+
+void AppCacheFrameNavigationHandler::CommitNavigationHelper(int process_id) {
+ DCHECK(IsBrowserSideNavigationEnabled());
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(backend_impl_.get());
+
+ // When the navigation for a frame tree node commits, we need to switch the
+ // AppCacheBackendImpl instance from a frame based navigation to a process
+ // based navigation. For this we unregister the AppCacheBackendImpl instance
+ // from the AppCache service. We then set the process id in the
+ // AppCacheBackendImpl instance. This ensures that it is registered using
+ // the process id in the AppCacheDispatcherHost::FrameNavigationCommitted()
+ // function.
+ appcache_service_->UnregisterBackendForFrame(backend_impl_.get());
+
+ scoped_refptr<AppCacheDispatcherHost> dispatcher_host =
+ AppCacheDispatcherHost::GetHostForProcess(process_id);
+ if (dispatcher_host.get()) {
+ backend_impl_->set_process_id(process_id);
+ backend_impl_->set_frame_id(-1);
+ dispatcher_host->FrameNavigationCommitted(std::move(backend_impl_));
+ }
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&AppCacheFrameNavigationHandler::Release,
+ base::Unretained(this)));
+ // Don't access any member from here on.
+}
+
+void AppCacheFrameNavigationHandler::DeleteOnCorrectThread() const {
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ // The reference to us in the global map needs to be remove in the UI
+ // thread.
+ FrameToNavigationHandlerMap::iterator index =
+ g_frame_navigation_handler_map.Get().find(frame_node_id_);
+ if ((index != g_frame_navigation_handler_map.Get().end()) &&
+ index->second == this) {
+ g_frame_navigation_handler_map.Get().erase(index);
+ }
+ }
+
+ if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
michaeln 2016/11/22 00:17:27 if we go thru this code path, we do we leave a dan
ananta 2016/11/23 04:05:14 This file has gone
+ delete this;
+ return;
+ }
+
+ if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
+ BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, this);
+ return;
+ }
+
+ // Better to leak than crash on shutdown.
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698