Commit 04931909 authored by nyquist@chromium.org's avatar nyquist@chromium.org

Add support for showing CSS with distilled articles.

Adds the Readability CSS and also makes the DOM Distiller viewer load it.

BUG=319881

Review URL: https://codereview.chromium.org/138923002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247675 0039d316-1c4b-4281-b951-d872f2087c98
parent 07fe275d
......@@ -198,8 +198,40 @@ void DomDistillerViewerSourceBrowserTest::ViewSingleDistilledPage() {
// Ensure no bindings.
const content::RenderViewHost* render_view_host = observer.render_view_host();
ASSERT_EQ(0, render_view_host->GetEnabledBindings());
// The MIME-type should always be text/html.
// The MIME-type should always be text/html for the distilled articles.
EXPECT_EQ("text/html", observer.web_contents()->GetContentsMimeType());
}
// The DomDistillerViewerSource renders untrusted content, so ensure no bindings
// are enabled when the CSS resource is loaded. This CSS might be bundle with
// Chrome or provided by an extension.
IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest,
NoWebUIBindingsDisplayCSS) {
// Ensure the source is registered.
// TODO(nyquist): Remove when the source is always registered on startup.
DomDistillerViewerSource* source =
new DomDistillerViewerSource(NULL, chrome::kDomDistillerScheme);
content::URLDataSource::Add(browser()->profile(), source);
// Setup observer to inspect the RenderViewHost after committed navigation.
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
LoadSuccessObserver observer(contents);
// Navigate to a URL which the source should respond to with CSS.
std::string url_without_scheme = "://foobar/readability.css";
GURL url(chrome::kDomDistillerScheme + url_without_scheme);
ui_test_utils::NavigateToURL(browser(), url);
// A navigation should have succeeded to the correct URL.
ASSERT_FALSE(observer.load_failed());
ASSERT_TRUE(observer.finished_load());
ASSERT_EQ(url, observer.validated_url());
// Ensure no bindings.
const content::RenderViewHost* render_view_host = observer.render_view_host();
ASSERT_EQ(0, render_view_host->GetEnabledBindings());
// The MIME-type should always be text/css for the CSS resources.
EXPECT_EQ("text/css", observer.web_contents()->GetContentsMimeType());
}
} // namespace dom_distiller
......@@ -26,14 +26,17 @@
namespace {
const char kCssPath[] = "readability.css";
std::string ReplaceHtmlTemplateValues(std::string title, std::string content) {
base::StringPiece html_template =
ResourceBundle::GetSharedInstance().GetRawDataResource(
IDR_DOM_DISTILLER_VIEWER_HTML);
std::vector<std::string> substitutions;
substitutions.push_back(title); // $1
substitutions.push_back(title); // $2
substitutions.push_back(content); // $3
substitutions.push_back(title); // $1
substitutions.push_back(kCssPath); // $2
substitutions.push_back(title); // $3
substitutions.push_back(content); // $4
return ReplaceStringPlaceholders(html_template, substitutions, NULL);
}
......@@ -114,6 +117,14 @@ void DomDistillerViewerSource::StartDataRequest(
DCHECK(render_view_host);
CHECK_EQ(0, render_view_host->GetEnabledBindings());
if (kCssPath == path) {
std::string css = ResourceBundle::GetSharedInstance()
.GetRawDataResource(IDR_DISTILLER_CSS)
.as_string();
callback.Run(base::RefCountedString::TakeString(&css));
return;
}
RequestViewerHandle* request_viewer_handle =
new RequestViewerHandle(callback);
std::string entry_id = StringToUpperASCII(path);
......@@ -141,6 +152,8 @@ void DomDistillerViewerSource::StartDataRequest(
std::string DomDistillerViewerSource::GetMimeType(const std::string& path)
const {
if (path == kCssPath)
return "text/css";
return "text/html";
}
......@@ -152,9 +165,16 @@ bool DomDistillerViewerSource::ShouldServiceRequest(
void DomDistillerViewerSource::WillServiceRequest(
const net::URLRequest* request,
std::string* path) const {
// Since the full request is not available to StartDataRequest, replace the
// path to contain the data needed.
*path = request->url().host();
if (*path != kCssPath) {
// Since the full request is not available to StartDataRequest, replace the
// path to contain the data needed.
*path = request->url().host();
}
};
std::string DomDistillerViewerSource::GetContentSecurityPolicyObjectSrc()
const {
return "object-src 'none'; style-src 'self'";
}
} // namespace dom_distiller
......@@ -33,6 +33,7 @@ class DomDistillerViewerSource : public content::URLDataSource {
const OVERRIDE;
virtual void WillServiceRequest(const net::URLRequest* request,
std::string* path) const OVERRIDE;
virtual std::string GetContentSecurityPolicyObjectSrc() const OVERRIDE;
// The scheme this URLDataSource is hosted under.
std::string scheme_;
......
......@@ -8,15 +8,16 @@ found in the LICENSE file.
<head>
<meta charset="utf-8">
<title>$1</title>
<link rel="stylesheet" type="text/css" href="$2">
</head>
<body>
<div id="mainContent">
<div id="article">
<article>
<header>
<h1>$2</h1>
<h1>$3</h1>
</header>
<div id="content">$3</div>
<div id="content">$4</div>
</article>
</div>
</div>
......
......@@ -14,6 +14,7 @@
<include name="IDR_ABOUT_DOM_DISTILLER_JS" file="dom_distiller/webui/resources/about_dom_distiller.js" type="BINDATA" />
<include name="IDR_DOM_DISTILLER_VIEWER_HTML" file="dom_distiller/content/resources/dom_distiller_viewer.html" type="BINDATA" />
<include name="IDR_DISTILLER_JS" file="../third_party/readability/js/readability.js" type="BINDATA" />
<include name="IDR_DISTILLER_CSS" file="../third_party/readability/css/readability.css" type="BINDATA" />
</includes>
</release>
</grit>
......@@ -6,7 +6,7 @@ Security Critical: yes
Description:
Readability operates on the DOM of a Web page to extract article content and
present it in an easy-to-read form.
present it in an easy-to-read form. The CSS of readability is unchanged.
Local Modifications:
- Removed all writes to innerHTML in the JavaScript.
......
@charset "utf-8";
/* Document */
body{font-size:10px;line-height:1;}
#readTools a{background-color:transparent!important;background-image:url(http://kerrick.github.com/readability-js/sprite-readability.png)!important;background-repeat:no-repeat!important;}
#readOverlay{text-rendering:optimizeLegibility;display:block;position:absolute;top:0;left:0;width:100%;}
#readInner{max-width:800px;margin:1em auto;}
#readInner a{color:#039;text-decoration:none;}
#readInner a:hover,#readInner a:focus{text-decoration:underline;}
#readInner img{float:left;clear:both;margin:0 12px 12px 0;}
#readInner img.blockImage{clear:both;float:none;display:block;margin-left:auto;margin-right:auto;}
#readInner h1{display:block;width:100%;border-bottom:1px solid #333;font-size:1.2em;padding-bottom:.5em;margin-bottom:.75em;}
#readInner sup{line-height:.8em;}
#readInner .page-separator{clear:both;display:block;font-size:.85em;filter:alpha(opacity=20);opacity:.20;text-align:center;}
.style-apertura #readInner h1{border-bottom-color:#ededed;}
.style-terminal #readInner h1{border-bottom-color:#c6ffc6;}
#readInner blockquote{margin-left:3em;margin-right:3em;}
#readability-inner *{margin-bottom:16px;border:none;background:none;}
#readability-footnotes{clear:both;}
/* Footer */
#rdb-footer-wrapper{display:block;border-top:1px solid #333;clear:both;overflow:hidden;margin:2em 0;}
.style-apertura #rdb-footer-wrapper{border-top-color:#ededed;}
.style-terminal #rdb-footer-wrapper{border-top-color:#c6ffc6;}
#rdb-footer-left{display:inline;float:left;margin-top:15px;width:285px;background-position:0 -36px;}
.rdbTypekit #rdb-footer-left{width:475px;}
#rdb-footer-left a,#rdb-footer-left a:link{float:left;}
#readability-logo{display:inline;background-position:0 -36px;height:29px;width:189px;text-indent:-9000px;}
#arc90-logo{display:inline;background-position:right -36px;height:29px;width:96px;text-indent:-9000px;}
.style-apertura #readability-logo,.style-terminal #readability-logo{background-position:0 -67px;}
.style-apertura #arc90-logo,.style-terminal #arc90-logo{background-position:right -67px;}
#rdb-footer-right{display:inline;float:right;text-align:right;font-size:.75em;margin-top:18px;}
#rdb-footer-right a{display:inline-block;float:left;overflow:visible;line-height:16px;vertical-align:baseline;}
.footer-twitterLink{height:20px;margin-left:20px;background-position:0 -123px;font-size:12px;padding:4px 0 0 28px;}
#rdb-footer-left .footer-twitterLink{display:none;margin-top:1px;padding-top:2px;}
.rdbTypekit #rdb-footer-left .footer-twitterLink{display:inline-block!important;}
a.rdbTK-powered,a.rdbTK-powered:link,a.rdbTK-powered:hover{font-size:16px;color:#858789!important;text-decoration:none!important;}
a.rdbTK-powered span{display:inline-block;height:22px;margin-left:2px;background-position:0 -146px!important;padding:4px 0 0 26px;}
.style-apertura #rdb-inverse,.style-athelas #rdb-athelas{display:block;}
#rdb-footer-print,#readability-url,.rdbTypekit #rdb-footer-right .footer-twitterLink,span.version{display:none;}
/* Tools */
#readTools{width:34px;height:150px;position:fixed;z-index:100;top:10px;left:10px;}
#readTools a{overflow:hidden;margin-bottom:8px;display:block;opacity:.4;text-indent:-99999px;height:34px;width:34px;text-decoration:none;filter:alpha(opacity=40);}
#reload-page{background-position:0 0;}
#print-page{background-position:-36px 0;}
#readTools a:hover,#readTools a:focus{opacity:1;filter:alpha(opacity=100);}
/* @group User Styles */
/* Size */
.size-x-small{font-size:1.1em;line-height:1.5em;}
.size-small{font-size:1.4em;line-height:1.5em;}
.size-medium{font-size:1.7em;line-height:1.48em;}
.size-large{font-size:2em;line-height:1.47em;}
.size-x-large{font-size:2.5em;line-height:1.43em;}
.size-x-small h1,.size-small h1,.size-medium h1,.size-large h1{font-size:1.6em;line-height:1.5em;}
.size-x-large h1{font-size:1.6em;line-height:1.3em;}
/* Style */
.style-newspaper {font-family:Georgia,"Times New Roman", Times, serif;background:#fbfbfb;color:#080000;}
.style-newspaper h1 {text-transform:capitalize;font-family:Georgia, "Times New Roman", Times, serif;}
.style-newspaper #readInner a {color:#0924e1;}
.style-novel {font-family:"Palatino Linotype", "Book Antiqua", Palatino, serif;background:#f4eed9;color:#1d1916;}
.style-novel #readInner a {color:#1856ba;}
.style-ebook {font-family:Arial, Helvetica, sans-serif;background:#edebe8;color:#2c2d32;}
.style-ebook #readInner a {color:#187dc9;}
.style-ebook h1 {font-family:"Arial Black", Gadget, sans-serif;font-weight:400;}
.style-terminal {font-family:"Lucida Console", Monaco, monospace;background:#1d4e2c;color:#c6ffc6;}
.style-terminal #readInner a {color:#093;}
/* Typekit */
.style-apertura{font-family:apertura-1,apertura-2,sans-serif;background-color:#2d2828;color:#eae8e9;}
.style-apertura #readInner a{color:#58b0ff;}
.style-athelas{font-family:athelas-1,athelas-2,"Palatino Linotype","Book Antiqua",Palatino,serif;background-color:#f7f7f7;color:#2b373d;}
.style-athelas #readInner a{color:#1e83cb;}
/* Margin */
.margin-x-narrow{width:95%;}
.margin-narrow{width:85%;}
.margin-medium{width:75%;}
.margin-wide{width:55%;}
.margin-x-wide{width:35%;}
/* @end User Styles */
/* -- DEBUG -- */
.bug-green{background:#bbf9b0;border:4px solid green;}
.bug-red{background:red;}
.bug-yellow{background:#ffff8e;}
.bug-blue{background:#bfdfff;}
/* Override html styling attributes */
table,tr,td{background-color:transparent!important;}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment