diff options
author | dfalcantara@chromium.org <dfalcantara@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-01 01:46:35 +0000 |
---|---|---|
committer | dfalcantara@chromium.org <dfalcantara@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-01 01:46:35 +0000 |
commit | 33b1c085bdc863004289c7e597eb977afc40d65f (patch) | |
tree | c931451e4c7c6242946b846072040de7d144a4b9 | |
parent | ad7ead3c122bd08da572b6e2230bf1d433eda5f4 (diff) | |
download | chromium_src-33b1c085bdc863004289c7e597eb977afc40d65f.zip chromium_src-33b1c085bdc863004289c7e597eb977afc40d65f.tar.gz chromium_src-33b1c085bdc863004289c7e597eb977afc40d65f.tar.bz2 |
Add MetaTagObserver for retrieving information about meta tags
Add an observer that grabs information about meta tags when the
page has finished loading.
BUG=332281
Review URL: https://codereview.chromium.org/139413006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248327 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/android/meta_tag_observer.cc | 56 | ||||
-rw-r--r-- | chrome/browser/android/meta_tag_observer.h | 47 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/common/chrome_constants.cc | 4 | ||||
-rw-r--r-- | chrome/common/chrome_constants.h | 5 | ||||
-rw-r--r-- | chrome/common/render_messages.h | 11 | ||||
-rw-r--r-- | chrome/renderer/chrome_render_view_observer.cc | 132 | ||||
-rw-r--r-- | chrome/renderer/chrome_render_view_observer.h | 2 |
8 files changed, 222 insertions, 37 deletions
diff --git a/chrome/browser/android/meta_tag_observer.cc b/chrome/browser/android/meta_tag_observer.cc new file mode 100644 index 0000000..77425b8 --- /dev/null +++ b/chrome/browser/android/meta_tag_observer.cc @@ -0,0 +1,56 @@ +// 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 "chrome/browser/android/meta_tag_observer.h" + +#include "chrome/common/chrome_constants.h" +#include "chrome/common/render_messages.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" + +MetaTagObserver::MetaTagObserver(const std::string& meta_tag) + : meta_tag_(meta_tag) { + if (meta_tag_.size() > chrome::kMaxMetaTagAttributeLength) { + VLOG(1) << "Length of the <meta> name attribute is too large."; + NOTREACHED(); + } +} + +MetaTagObserver::~MetaTagObserver() { +} + +void MetaTagObserver::DidFinishLoad( + int64 frame_id, + const GURL& validated_url, + bool is_main_frame, + content::RenderViewHost* render_view_host) { + if (!is_main_frame) return; + validated_url_ = validated_url; + Send(new ChromeViewMsg_RetrieveMetaTagContent(routing_id(), + validated_url, + meta_tag_)); +} + +bool MetaTagObserver::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(MetaTagObserver, message) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidRetrieveMetaTagContent, + OnDidRetrieveMetaTagContent) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void MetaTagObserver::OnDidRetrieveMetaTagContent( + bool success, + const std::string& tag_name, + const std::string& tag_content, + const GURL& expected_url) { + if (!success || tag_name != meta_tag_ || validated_url_ != expected_url || + tag_content.size() >= chrome::kMaxMetaTagAttributeLength) { + return; + } + HandleMetaTagContent(tag_content, expected_url); +} diff --git a/chrome/browser/android/meta_tag_observer.h b/chrome/browser/android/meta_tag_observer.h new file mode 100644 index 0000000..419fa57 --- /dev/null +++ b/chrome/browser/android/meta_tag_observer.h @@ -0,0 +1,47 @@ +// 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 CHROME_BROWSER_ANDROID_META_TAG_OBSERVER_H_ +#define CHROME_BROWSER_ANDROID_META_TAG_OBSERVER_H_ + +#include "content/public/browser/web_contents_observer.h" + +class GURL; + +// Retrieves the content of a particular meta tag when a page has fully loaded. +// Subclasses must implement |HandleMetaTagContent|, which gets called after +// the DOM has been scanned for the tag. +class MetaTagObserver : public content::WebContentsObserver { + public: + explicit MetaTagObserver(const std::string& meta_tag); + virtual ~MetaTagObserver(); + + // content::WebContentsObserver overrides: + virtual void DidFinishLoad( + int64 frame_id, + const GURL& validated_url, + bool is_main_frame, + content::RenderViewHost* render_view_host) OVERRIDE; + + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + protected: + // Called when the meta tag's content has been retrieved successfully. + virtual void HandleMetaTagContent(const std::string& tag_content, + const GURL& expected_url) = 0; + + private: + // Called when the renderer has returned information about the meta tag. + void OnDidRetrieveMetaTagContent(bool success, + const std::string& tag_name, + const std::string& tag_content, + const GURL& expected_url); + + const std::string meta_tag_; + GURL validated_url_; + + DISALLOW_COPY_AND_ASSIGN(MetaTagObserver); +}; + +#endif // CHROME_BROWSER_ANDROID_META_TAG_OBSERVER_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 3aca70a..643d574 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -121,6 +121,8 @@ 'browser/android/field_trial_helper.h', 'browser/android/foreign_session_helper.cc', 'browser/android/foreign_session_helper.h', + 'browser/android/meta_tag_observer.cc', + 'browser/android/meta_tag_observer.h', 'browser/android/new_tab_page_prefs.cc', 'browser/android/new_tab_page_prefs.h', 'browser/android/google_location_settings_helper.h', diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc index bb629a4..31e7f11 100644 --- a/chrome/common/chrome_constants.cc +++ b/chrome/common/chrome_constants.cc @@ -267,6 +267,10 @@ const char kTestUserProfileDir[] = "test-user"; const char kApplicationClientIDStringForAVScanning[] = "2676A9A2-D919-4FEE-9187-152100393AB2"; +#if defined(OS_ANDROID) +const size_t kMaxMetaTagAttributeLength = 2000; +#endif + } // namespace chrome #undef FPL diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h index 5e7b481..f2a6770 100644 --- a/chrome/common/chrome_constants.h +++ b/chrome/common/chrome_constants.h @@ -155,6 +155,11 @@ extern const char kTestUserProfileDir[]; // Used to identify the application to the system AV function in Windows. extern const char kApplicationClientIDStringForAVScanning[]; +#if defined(OS_ANDROID) +// The largest reasonable length we'd assume for a meta tag attribute. +extern const size_t kMaxMetaTagAttributeLength; +#endif + } // namespace chrome #endif // CHROME_COMMON_CHROME_CONSTANTS_H_ diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index 5381fab..26035c9 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -403,6 +403,11 @@ IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_RequestThumbnailForContextNode_ACK, // be treated as a webapp. IPC_MESSAGE_ROUTED1(ChromeViewMsg_RetrieveWebappInformation, GURL /* expected_url */) + +// Asks the renderer to return information about the given meta tag. +IPC_MESSAGE_ROUTED2(ChromeViewMsg_RetrieveMetaTagContent, + GURL /* expected_url */, + std::string /* tag_name */ ) #endif // defined(OS_ANDROID) // chrome.principals messages ------------------------------------------------ @@ -654,6 +659,12 @@ IPC_MESSAGE_ROUTED4(ChromeViewHostMsg_DidRetrieveWebappInformation, bool /* is_mobile_webapp_capable */, bool /* is_apple_mobile_webapp_capable */, GURL /* expected_url */) + +IPC_MESSAGE_ROUTED4(ChromeViewHostMsg_DidRetrieveMetaTagContent, + bool /* success */, + std::string /* tag_name */, + std::string /* tag_content */, + GURL /* expected_url */) #endif // defined(OS_ANDROID) // The currently displayed PDF has an unsupported feature. diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc index 47509ba..5527529 100644 --- a/chrome/renderer/chrome_render_view_observer.cc +++ b/chrome/renderer/chrome_render_view_observer.cc @@ -196,6 +196,56 @@ extensions::StackTrace GetStackTraceFromMessage( return result; } +#if defined(OS_ANDROID) +// Parses the DOM for a <meta> tag with a particular name. +// |meta_tag_content| is set to the contents of the 'content' attribute. +// |found_tag| is set to true if the tag was successfully found. +// Returns true if the document was parsed without errors. +bool RetrieveMetaTagContent(const WebFrame* main_frame, + const GURL& expected_url, + const std::string& meta_tag_name, + bool* found_tag, + std::string* meta_tag_content) { + WebDocument document = + main_frame ? main_frame->document() : WebDocument(); + WebElement head = document.isNull() ? WebElement() : document.head(); + GURL document_url = document.isNull() ? GURL() : GURL(document.url()); + + // Search the DOM for the <meta> tag with the given name. + *found_tag = false; + *meta_tag_content = ""; + if (!head.isNull()) { + WebNodeList children = head.childNodes(); + for (unsigned i = 0; i < children.length(); ++i) { + WebNode child = children.item(i); + if (!child.isElementNode()) + continue; + WebElement elem = child.to<WebElement>(); + if (elem.hasTagName("meta")) { + if (elem.hasAttribute("name") && elem.hasAttribute("content")) { + std::string name = elem.getAttribute("name").utf8(); + if (name == meta_tag_name) { + *meta_tag_content = elem.getAttribute("content").utf8(); + *found_tag = true; + break; + } + } + } + } + } + + // Make sure we're checking the right page and that the length of the content + // string is reasonable. + bool success = document_url == expected_url; + if (meta_tag_content->size() > chrome::kMaxMetaTagAttributeLength) { + *meta_tag_content = ""; + success = false; + } + + return success; +} +#endif + } // namespace ChromeRenderViewObserver::ChromeRenderViewObserver( @@ -233,6 +283,8 @@ bool ChromeRenderViewObserver::OnMessageReceived(const IPC::Message& message) { OnUpdateTopControlsState) IPC_MESSAGE_HANDLER(ChromeViewMsg_RetrieveWebappInformation, OnRetrieveWebappInformation) + IPC_MESSAGE_HANDLER(ChromeViewMsg_RetrieveMetaTagContent, + OnRetrieveMetaTagContent) #endif IPC_MESSAGE_HANDLER(ChromeViewMsg_SetWindowFeatures, OnSetWindowFeatures) IPC_MESSAGE_UNHANDLED(handled = false) @@ -273,42 +325,28 @@ void ChromeRenderViewObserver::OnUpdateTopControlsState( void ChromeRenderViewObserver::OnRetrieveWebappInformation( const GURL& expected_url) { WebFrame* main_frame = render_view()->GetWebView()->mainFrame(); - WebDocument document = - main_frame ? main_frame->document() : WebDocument(); - - WebElement head = document.isNull() ? WebElement() : document.head(); - GURL document_url = document.isNull() ? GURL() : GURL(document.url()); - - // Make sure we're checking the right page. - bool success = document_url == expected_url; - - bool is_mobile_webapp_capable = false; - bool is_apple_mobile_webapp_capable = false; - - // Search the DOM for the webapp <meta> tags. - if (!head.isNull()) { - WebNodeList children = head.childNodes(); - for (unsigned i = 0; i < children.length(); ++i) { - WebNode child = children.item(i); - if (!child.isElementNode()) - continue; - WebElement elem = child.to<WebElement>(); - - if (elem.hasTagName("meta") && elem.hasAttribute("name")) { - std::string name = elem.getAttribute("name").utf8(); - WebString content = elem.getAttribute("content"); - if (LowerCaseEqualsASCII(content, "yes")) { - if (name == "mobile-web-app-capable") { - is_mobile_webapp_capable = true; - } else if (name == "apple-mobile-web-app-capable") { - is_apple_mobile_webapp_capable = true; - } - } - } - } - } else { - success = false; - } + bool found_tag; + std::string content_str; + + // Search for the "mobile-web-app-capable" tag. + bool mobile_parse_success = RetrieveMetaTagContent( + main_frame, + expected_url, + "mobile-web-app-capable", + &found_tag, + &content_str); + bool is_mobile_webapp_capable = mobile_parse_success && found_tag && + LowerCaseEqualsASCII(content_str, "yes"); + + // Search for the "apple-mobile-web-app-capable" tag. + bool apple_parse_success = RetrieveMetaTagContent( + main_frame, + expected_url, + "apple-mobile-web-app-capable", + &found_tag, + &content_str); + bool is_apple_mobile_webapp_capable = apple_parse_success && found_tag && + LowerCaseEqualsASCII(content_str, "yes"); bool is_only_apple_mobile_webapp_capable = is_apple_mobile_webapp_capable && !is_mobile_webapp_capable; @@ -324,11 +362,31 @@ void ChromeRenderViewObserver::OnRetrieveWebappInformation( Send(new ChromeViewHostMsg_DidRetrieveWebappInformation( routing_id(), - success, + mobile_parse_success && apple_parse_success, is_mobile_webapp_capable, is_apple_mobile_webapp_capable, expected_url)); } + +void ChromeRenderViewObserver::OnRetrieveMetaTagContent( + const GURL& expected_url, + const std::string tag_name) { + bool found_tag; + std::string content_str; + bool parsed_successfully = RetrieveMetaTagContent( + render_view()->GetWebView()->mainFrame(), + expected_url, + tag_name, + &found_tag, + &content_str); + + Send(new ChromeViewHostMsg_DidRetrieveMetaTagContent( + routing_id(), + parsed_successfully && found_tag, + tag_name, + content_str, + expected_url)); +} #endif void ChromeRenderViewObserver::OnSetWindowFeatures( diff --git a/chrome/renderer/chrome_render_view_observer.h b/chrome/renderer/chrome_render_view_observer.h index 786079e..a2e7f68 100644 --- a/chrome/renderer/chrome_render_view_observer.h +++ b/chrome/renderer/chrome_render_view_observer.h @@ -82,6 +82,8 @@ class ChromeRenderViewObserver : public content::RenderViewObserver { content::TopControlsState current, bool animate); void OnRetrieveWebappInformation(const GURL& expected_url); + void OnRetrieveMetaTagContent(const GURL& expected_url, + const std::string tag_name); #endif void OnSetWindowFeatures(const blink::WebWindowFeatures& window_features); |