summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordfalcantara@chromium.org <dfalcantara@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-01 01:46:35 +0000
committerdfalcantara@chromium.org <dfalcantara@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-01 01:46:35 +0000
commit33b1c085bdc863004289c7e597eb977afc40d65f (patch)
treec931451e4c7c6242946b846072040de7d144a4b9
parentad7ead3c122bd08da572b6e2230bf1d433eda5f4 (diff)
downloadchromium_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.cc56
-rw-r--r--chrome/browser/android/meta_tag_observer.h47
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/common/chrome_constants.cc4
-rw-r--r--chrome/common/chrome_constants.h5
-rw-r--r--chrome/common/render_messages.h11
-rw-r--r--chrome/renderer/chrome_render_view_observer.cc132
-rw-r--r--chrome/renderer/chrome_render_view_observer.h2
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);