Fix navigation from inside PDF files (issue #1737)

This commit is contained in:
Marshall Greenblatt 2015-10-14 14:23:08 -04:00
parent efbc200b51
commit 5033a27e58
7 changed files with 175 additions and 0 deletions

View File

@ -1328,6 +1328,8 @@
# Include sources for extensions support.
'<(DEPTH)/chrome/common/extensions/chrome_manifest_url_handlers.cc',
'<(DEPTH)/chrome/common/extensions/chrome_manifest_url_handlers.h',
'<(DEPTH)/chrome/common/extensions/extension_process_policy.cc',
'<(DEPTH)/chrome/common/extensions/extension_process_policy.h',
'<(DEPTH)/chrome/common/pepper_permission_util.cc',
'<(DEPTH)/chrome/common/pepper_permission_util.h',
'<(DEPTH)/chrome/common/url_constants.cc',

View File

@ -65,6 +65,7 @@
#include "extensions/browser/guest_view/extensions_guest_view_message_filter.h"
#include "extensions/browser/io_thread_extension_message_filter.h"
#include "extensions/common/constants.h"
#include "extensions/common/switches.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "ppapi/host/ppapi_host.h"
#include "third_party/WebKit/public/web/WebWindowFeatures.h"
@ -325,6 +326,14 @@ int GetCrashSignalFD(const base::CommandLine& command_line) {
if (!breakpad::IsCrashReporterEnabled())
return -1;
// Extensions have the same process type as renderers.
if (command_line.HasSwitch(extensions::switches::kExtensionProcess)) {
static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
if (!crash_handler)
crash_handler = CreateCrashHandlerHost("extension");
return crash_handler->GetDeathSignalSocket();
}
std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
@ -756,6 +765,20 @@ void CefContentBrowserClient::AppendExtraCommandLineSwitches(
};
command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
arraysize(kSwitchNames));
if (extensions::ExtensionsEnabled()) {
// Based on ChromeContentBrowserClientExtensionsPart::
// AppendExtraRendererCommandLineSwitches
content::RenderProcessHost* process =
content::RenderProcessHost::FromID(child_process_id);
content::BrowserContext* browser_context =
process ? process->GetBrowserContext() : NULL;
if (browser_context &&
extensions::ProcessMap::Get(browser_context)->Contains(
process->GetID())) {
command_line->AppendSwitch(extensions::switches::kExtensionProcess);
}
}
}
#if defined(OS_LINUX)

View File

@ -34,6 +34,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_process_policy.h"
#include "chrome/common/pepper_permission_util.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
@ -60,6 +61,7 @@
#include "content/public/renderer/render_view_visitor.h"
#include "content/renderer/render_frame_impl.h"
#include "extensions/common/constants.h"
#include "extensions/common/switches.h"
#include "extensions/renderer/dispatcher.h"
#include "extensions/renderer/dispatcher_delegate.h"
#include "extensions/renderer/extension_frame_helper.h"
@ -163,6 +165,67 @@ std::string GetPluginInstancePosterAttribute(
return std::string();
}
bool IsStandaloneExtensionProcess() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
extensions::switches::kExtensionProcess);
}
bool CrossesExtensionExtents(
blink::WebLocalFrame* frame,
const GURL& new_url,
bool is_extension_url,
bool is_initial_navigation) {
DCHECK(!frame->parent());
GURL old_url(frame->document().url());
extensions::RendererExtensionRegistry* extension_registry =
extensions::RendererExtensionRegistry::Get();
// If old_url is still empty and this is an initial navigation, then this is
// a window.open operation. We should look at the opener URL. Note that the
// opener is a local frame in this case.
if (is_initial_navigation && old_url.is_empty() && frame->opener()) {
blink::WebLocalFrame* opener_frame = frame->opener()->toWebLocalFrame();
// If we're about to open a normal web page from a same-origin opener stuck
// in an extension process, we want to keep it in process to allow the
// opener to script it.
blink::WebDocument opener_document = opener_frame->document();
blink::WebSecurityOrigin opener_origin = opener_document.securityOrigin();
bool opener_is_extension_url = !opener_origin.isUnique() &&
extension_registry->GetExtensionOrAppByURL(
opener_document.url()) != NULL;
if (!is_extension_url &&
!opener_is_extension_url &&
IsStandaloneExtensionProcess() &&
opener_origin.canRequest(blink::WebURL(new_url)))
return false;
// In all other cases, we want to compare against the URL that determines
// the type of process. In default Chrome, that's the URL of the opener's
// top frame and not the opener frame itself. In --site-per-process, we
// can use the opener frame itself.
// TODO(nick): Either wire this up to SiteIsolationPolicy, or to state on
// |opener_frame|/its ancestors.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSitePerProcess) ||
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kIsolateExtensions))
old_url = opener_frame->document().url();
else
old_url = opener_frame->top()->document().url();
}
// Only consider keeping non-app URLs in an app process if this window
// has an opener (in which case it might be an OAuth popup that tries to
// script an iframe within the app).
bool should_consider_workaround = !!frame->opener();
return extensions::CrossesExtensionProcessBoundary(
*extension_registry->GetMainThreadExtensionSet(), old_url, new_url,
should_consider_workaround);
}
} // namespace
CefContentRendererClient::CefContentRendererClient()
@ -565,6 +628,63 @@ bool CefContentRendererClient::HandleNavigation(
return false;
}
bool CefContentRendererClient::ShouldFork(blink::WebLocalFrame* frame,
const GURL& url,
const std::string& http_method,
bool is_initial_navigation,
bool is_server_redirect,
bool* send_referrer) {
DCHECK(!frame->parent());
// For now, we skip the rest for POST submissions. This is because
// http://crbug.com/101395 is more likely to cause compatibility issues
// with hosted apps and extensions than WebUI pages. We will remove this
// check when cross-process POST submissions are supported.
if (http_method != "GET")
return false;
if (extensions::ExtensionsEnabled()) {
const extensions::RendererExtensionRegistry* extension_registry =
extensions::RendererExtensionRegistry::Get();
// Determine if the new URL is an extension (excluding bookmark apps).
const extensions::Extension* new_url_extension =
extensions::GetNonBookmarkAppExtension(
*extension_registry->GetMainThreadExtensionSet(), url);
bool is_extension_url = !!new_url_extension;
// If the navigation would cross an app extent boundary, we also need
// to defer to the browser to ensure process isolation. This is not
// necessary for server redirects, which will be transferred to a new
// process by the browser process when they are ready to commit. It is
// necessary for client redirects, which won't be transferred in the same
// way.
if (!is_server_redirect &&
CrossesExtensionExtents(frame, url, is_extension_url,
is_initial_navigation)) {
// Include the referrer in this case since we're going from a hosted web
// page. (the packaged case is handled previously by the extension
// navigation test)
*send_referrer = true;
return true;
}
// If this is a reload, check whether it has the wrong process type. We
// should send it to the browser if it's an extension URL (e.g., hosted app)
// in a normal process, or if it's a process for an extension that has been
// uninstalled. Without --site-per-process mode, we never fork processes
// for subframes, so this check only makes sense for top-level frames.
// TODO(alexmos,nasko): Figure out how this check should work when reloading
// subframes in --site-per-process mode.
if (!frame->parent() && frame->document().url() == url) {
if (is_extension_url != IsStandaloneExtensionProcess())
return true;
}
}
return false;
}
bool CefContentRendererClient::WillSendRequest(
blink::WebFrame* frame,
ui::PageTransition transition_type,

View File

@ -97,6 +97,12 @@ class CefContentRendererClient : public content::ContentRendererClient,
blink::WebNavigationType type,
blink::WebNavigationPolicy default_policy,
bool is_redirect) override;
bool ShouldFork(blink::WebLocalFrame* frame,
const GURL& url,
const std::string& http_method,
bool is_initial_navigation,
bool is_server_redirect,
bool* send_referrer) override;
bool WillSendRequest(blink::WebFrame* frame,
ui::PageTransition transition_type,
const GURL& url,

View File

@ -212,4 +212,10 @@ patches = [
'name': 'render_widget_host_1070383005',
'path': '../content/browser/renderer_host/',
},
{
# Fix incorrect forward declaration in extension_process_policy.h.
# https://code.google.com/p/chromium/issues/detail?id=543230
'name': 'extension_process_policy_543230',
'path': '../chrome/common/extensions/',
},
]

View File

@ -0,0 +1,18 @@
diff --git extension_process_policy.h extension_process_policy.h
index 7231c0f..2323483 100644
--- extension_process_policy.h
+++ extension_process_policy.h
@@ -5,12 +5,12 @@
#ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_PROCESS_POLICY_H_
#define CHROME_COMMON_EXTENSIONS_EXTENSION_PROCESS_POLICY_H_
-class ExtensionSet;
class GURL;
namespace extensions {
class Extension;
+class ExtensionSet;
// Returns the extension for the given URL. Excludes extension objects for
// bookmark apps, which do not use the app process model.

Binary file not shown.