Commit ac928976 authored by mlamouri@chromium.org's avatar mlamouri@chromium.org

Detect <link rel='manifest'> and notify embedder.

WebFrameClient gets a dispatchManifestChange method that will
be called by the FrameLoaderClient when the manifest
information might have changed. The embedder is not aware of
the manifest URL.

BUG=366145

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

git-svn-id: svn://svn.chromium.org/blink/trunk@173664 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent cd389f6a
...@@ -2451,6 +2451,8 @@ ...@@ -2451,6 +2451,8 @@
'html/LabelableElement.cpp', 'html/LabelableElement.cpp',
'html/LabelsNodeList.cpp', 'html/LabelsNodeList.cpp',
'html/LabelsNodeList.h', 'html/LabelsNodeList.h',
'html/LinkManifest.cpp',
'html/LinkManifest.h',
'html/LinkRelAttribute.cpp', 'html/LinkRelAttribute.cpp',
'html/LinkRelAttribute.h', 'html/LinkRelAttribute.h',
'html/LinkResource.cpp', 'html/LinkResource.cpp',
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "core/frame/FrameView.h" #include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h" #include "core/frame/LocalFrame.h"
#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/LinkManifest.h"
#include "core/html/imports/LinkImport.h" #include "core/html/imports/LinkImport.h"
#include "core/loader/FrameLoader.h" #include "core/loader/FrameLoader.h"
#include "core/loader/FrameLoaderClient.h" #include "core/loader/FrameLoaderClient.h"
...@@ -206,9 +207,11 @@ LinkResource* HTMLLinkElement::linkResourceToProcess() ...@@ -206,9 +207,11 @@ LinkResource* HTMLLinkElement::linkResourceToProcess()
} }
if (!m_link) { if (!m_link) {
if (m_relAttribute.isImport() && RuntimeEnabledFeatures::htmlImportsEnabled()) if (m_relAttribute.isImport() && RuntimeEnabledFeatures::htmlImportsEnabled()) {
m_link = LinkImport::create(this); m_link = LinkImport::create(this);
else { } else if (m_relAttribute.isManifest() && RuntimeEnabledFeatures::manifestEnabled()) {
m_link = LinkManifest::create(this);
} else {
OwnPtrWillBeRawPtr<LinkStyle> link = LinkStyle::create(this); OwnPtrWillBeRawPtr<LinkStyle> link = LinkStyle::create(this);
if (fastHasAttribute(disabledAttr)) if (fastHasAttribute(disabledAttr))
link->setDisabledState(true); link->setDisabledState(true);
......
// Copyright 2014 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 "config.h"
#include "core/html/LinkManifest.h"
#include "core/dom/Document.h"
#include "core/frame/LocalFrame.h"
#include "core/html/HTMLLinkElement.h"
#include "core/loader/FrameLoaderClient.h"
namespace WebCore {
PassOwnPtrWillBeRawPtr<LinkManifest> LinkManifest::create(HTMLLinkElement* owner)
{
return adoptPtrWillBeNoop(new LinkManifest(owner));
}
LinkManifest::LinkManifest(HTMLLinkElement* owner)
: LinkResource(owner)
{
}
LinkManifest::~LinkManifest()
{
}
void LinkManifest::process()
{
if (!m_owner || !m_owner->document().frame())
return;
m_owner->document().frame()->loader().client()->dispatchDidChangeManifest();
}
bool LinkManifest::hasLoaded() const
{
return false;
}
void LinkManifest::ownerRemoved()
{
process();
}
} // namespace WebCore
// Copyright 2014 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.
#ifndef LinkManifest_h
#define LinkManifest_h
#include "core/html/LinkResource.h"
#include "wtf/FastAllocBase.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/RefPtr.h"
namespace WebCore {
class HTMLLinkElement;
class LinkManifest FINAL : public LinkResource {
WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
public:
static PassOwnPtrWillBeRawPtr<LinkManifest> create(HTMLLinkElement* owner);
virtual ~LinkManifest();
// LinkResource
virtual void process() OVERRIDE;
virtual Type type() const OVERRIDE { return Manifest; }
virtual bool hasLoaded() const OVERRIDE;
virtual void ownerRemoved() OVERRIDE;
private:
explicit LinkManifest(HTMLLinkElement* owner);
};
}
#endif // LinkManifest_h
...@@ -46,6 +46,7 @@ LinkRelAttribute::LinkRelAttribute(const String& rel) ...@@ -46,6 +46,7 @@ LinkRelAttribute::LinkRelAttribute(const String& rel)
, m_isLinkPrerender(false) , m_isLinkPrerender(false)
, m_isLinkNext(false) , m_isLinkNext(false)
, m_isImport(false) , m_isImport(false)
, m_isManifest(false)
{ {
if (rel.isEmpty()) if (rel.isEmpty())
return; return;
...@@ -84,6 +85,8 @@ LinkRelAttribute::LinkRelAttribute(const String& rel) ...@@ -84,6 +85,8 @@ LinkRelAttribute::LinkRelAttribute(const String& rel)
} else if (equalIgnoringCase(*it, "apple-touch-icon-precomposed")) { } else if (equalIgnoringCase(*it, "apple-touch-icon-precomposed")) {
if (RuntimeEnabledFeatures::touchIconLoadingEnabled()) if (RuntimeEnabledFeatures::touchIconLoadingEnabled())
m_iconType = TouchPrecomposedIcon; m_iconType = TouchPrecomposedIcon;
} else if (equalIgnoringCase(*it, "manifest")) {
m_isManifest = true;
} }
} }
} }
......
...@@ -50,6 +50,7 @@ public: ...@@ -50,6 +50,7 @@ public:
bool isLinkPrerender() const { return m_isLinkPrerender; } bool isLinkPrerender() const { return m_isLinkPrerender; }
bool isLinkNext() const { return m_isLinkNext; } bool isLinkNext() const { return m_isLinkNext; }
bool isImport() const { return m_isImport; } bool isImport() const { return m_isImport; }
bool isManifest() const { return m_isManifest; }
private: private:
IconType m_iconType; IconType m_iconType;
...@@ -61,6 +62,7 @@ private: ...@@ -61,6 +62,7 @@ private:
bool m_isLinkPrerender : 1; bool m_isLinkPrerender : 1;
bool m_isLinkNext : 1; bool m_isLinkNext : 1;
bool m_isImport : 1; bool m_isImport : 1;
bool m_isManifest : 1;
}; };
} }
......
...@@ -45,7 +45,8 @@ class LinkResource : public NoBaseWillBeGarbageCollectedFinalized<LinkResource> ...@@ -45,7 +45,8 @@ class LinkResource : public NoBaseWillBeGarbageCollectedFinalized<LinkResource>
public: public:
enum Type { enum Type {
Style, Style,
Import Import,
Manifest
}; };
explicit LinkResource(HTMLLinkElement*); explicit LinkResource(HTMLLinkElement*);
......
...@@ -229,6 +229,8 @@ namespace WebCore { ...@@ -229,6 +229,8 @@ namespace WebCore {
virtual void didStopAllLoaders() { } virtual void didStopAllLoaders() { }
virtual void dispatchDidChangeManifest() { }
virtual bool isFrameLoaderClientImpl() const { return false; } virtual bool isFrameLoaderClientImpl() const { return false; }
}; };
......
...@@ -72,6 +72,7 @@ LangAttributeAwareFormControlUI ...@@ -72,6 +72,7 @@ LangAttributeAwareFormControlUI
LayerSquashing status=test LayerSquashing status=test
PrefixedEncryptedMedia status=stable PrefixedEncryptedMedia status=stable
LocalStorage status=stable LocalStorage status=stable
Manifest status=test
Media status=stable Media status=stable
MediaController depends_on=Media, status=experimental MediaController depends_on=Media, status=experimental
MediaQueryParser status=test MediaQueryParser status=test
......
...@@ -809,4 +809,10 @@ void FrameLoaderClientImpl::didStopAllLoaders() ...@@ -809,4 +809,10 @@ void FrameLoaderClientImpl::didStopAllLoaders()
m_webFrame->client()->didAbortLoading(m_webFrame); m_webFrame->client()->didAbortLoading(m_webFrame);
} }
void FrameLoaderClientImpl::dispatchDidChangeManifest()
{
if (m_webFrame->client())
m_webFrame->client()->didChangeManifest(m_webFrame);
}
} // namespace blink } // namespace blink
...@@ -159,6 +159,8 @@ public: ...@@ -159,6 +159,8 @@ public:
virtual void didStopAllLoaders() OVERRIDE; virtual void didStopAllLoaders() OVERRIDE;
virtual void dispatchDidChangeManifest() OVERRIDE;
private: private:
virtual bool isFrameLoaderClientImpl() const OVERRIDE { return true; } virtual bool isFrameLoaderClientImpl() const OVERRIDE { return true; }
......
...@@ -5403,4 +5403,29 @@ TEST_F(WebFrameTest, HasVisibleContentOnHiddenFrames) ...@@ -5403,4 +5403,29 @@ TEST_F(WebFrameTest, HasVisibleContentOnHiddenFrames)
} }
} }
class ManifestChangeWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
public:
ManifestChangeWebFrameClient() : m_manifestChangeCount(0) { }
virtual void didChangeManifest(WebLocalFrame*) OVERRIDE
{
++m_manifestChangeCount;
}
int manifestChangeCount() { return m_manifestChangeCount; }
private:
int m_manifestChangeCount;
};
TEST_F(WebFrameTest, NotifyManifestChange)
{
registerMockedHttpURLLoad("link-manifest-change.html");
ManifestChangeWebFrameClient webFrameClient;
FrameTestHelpers::WebViewHelper webViewHelper;
webViewHelper.initializeAndLoad(m_baseURL + "link-manifest-change.html", true, &webFrameClient);
EXPECT_EQ(14, webFrameClient.manifestChangeCount());
}
} // namespace } // namespace
<!DOCTYPE html>
<!-- This file is meant to test how many times the WebFrameClient will be
notified of a change in the current manifest URL associated with the document. -->
<html>
<head>
<link rel='manifest' href=''>
<link rel='manifest'>
<link rel='manifest foo'>
<link rel='manifest' crossorigin foo bar>
<!-- 4 times (= 4) -->
</head>
<body>
<link rel='manifest'>
<!-- 1 time (= 5) -->
</body>
<script>
function createLink(href, rel) {
var link = document.createElement('link');
link.href = href;
link.rel = rel;
return link;
}
var links = document.getElementsByTagName('link');
var link = document.createElement('link');
document.head.appendChild(createLink('foo.json', 'manifest'));
document.head.appendChild(createLink('foo.json', ''));
document.head.appendChild(createLink('foo.json', 'manifest'));
document.head.insertBefore(createLink('foo.json', 'manifest'), links[0]);
// 3 times (= 8)
links[0].crossOrigin = 'use-credentials';
links[0].media = '';
links[0].type = 'image/gif';
// 2 times (= 10)
links[0].href = 'bar.json';
links[0].rel = 'blah';
links[0].rel = 'manifest';
// 3 times (= 13)
document.head.removeChild(links[0]);
// 1 time (= 14)
</script>
</html>
...@@ -262,6 +262,10 @@ public: ...@@ -262,6 +262,10 @@ public:
// WARNING: This method may be called very frequently. // WARNING: This method may be called very frequently.
virtual void didUpdateCurrentHistoryItem(WebLocalFrame*) { } virtual void didUpdateCurrentHistoryItem(WebLocalFrame*) { }
// The frame's manifest has changed.
virtual void didChangeManifest(WebLocalFrame*) { }
// Misc ---------------------------------------------------------------- // Misc ----------------------------------------------------------------
// Called to retrieve the provider of desktop notifications. // Called to retrieve the provider of desktop notifications.
......
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