summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r--chrome/browser/extensions/extension_dom_ui.cc6
-rw-r--r--chrome/browser/extensions/extension_dom_ui.h1
-rw-r--r--chrome/browser/extensions/extension_function.h6
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc2
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.h2
-rw-r--r--chrome/browser/extensions/extension_host.cc3
-rw-r--r--chrome/browser/extensions/extension_host.h1
-rw-r--r--chrome/browser/extensions/extension_tabs_module.cc123
8 files changed, 99 insertions, 45 deletions
diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc
index 7d8d15d..40f11f1 100644
--- a/chrome/browser/extensions/extension_dom_ui.cc
+++ b/chrome/browser/extensions/extension_dom_ui.cc
@@ -91,9 +91,13 @@ void ExtensionDOMUI::RenderViewReused(RenderViewHost* render_view_host) {
void ExtensionDOMUI::ProcessDOMUIMessage(const std::string& message,
const Value* content,
+ const GURL& source_url,
int request_id,
bool has_callback) {
- extension_function_dispatcher_->HandleRequest(message, content, request_id,
+ extension_function_dispatcher_->HandleRequest(message,
+ content,
+ source_url,
+ request_id,
has_callback);
}
diff --git a/chrome/browser/extensions/extension_dom_ui.h b/chrome/browser/extensions/extension_dom_ui.h
index 7892b89..d14eb69 100644
--- a/chrome/browser/extensions/extension_dom_ui.h
+++ b/chrome/browser/extensions/extension_dom_ui.h
@@ -37,6 +37,7 @@ class ExtensionDOMUI
virtual void RenderViewReused(RenderViewHost* render_view_host);
virtual void ProcessDOMUIMessage(const std::string& message,
const Value* content,
+ const GURL& source_url,
int request_id,
bool has_callback);
diff --git a/chrome/browser/extensions/extension_function.h b/chrome/browser/extensions/extension_function.h
index 8e1ab8f..272d6c1 100644
--- a/chrome/browser/extensions/extension_function.h
+++ b/chrome/browser/extensions/extension_function.h
@@ -71,6 +71,9 @@ class ExtensionFunction : public base::RefCounted<ExtensionFunction> {
void set_request_id(int request_id) { request_id_ = request_id; }
int request_id() { return request_id_; }
+ void set_source_url(const GURL& source_url) { source_url_ = source_url; }
+ const GURL& source_url() { return source_url_; }
+
void set_has_callback(bool has_callback) { has_callback_ = has_callback; }
bool has_callback() { return has_callback_; }
@@ -126,6 +129,9 @@ class ExtensionFunction : public base::RefCounted<ExtensionFunction> {
// The name of this function.
std::string name_;
+ // The URL of the frame which is making this request
+ GURL source_url_;
+
// True if the js caller provides a callback function to receive the response
// of this call.
bool has_callback_;
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 78a2c032..8abc84c 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -372,12 +372,14 @@ Extension* ExtensionFunctionDispatcher::GetExtension() {
void ExtensionFunctionDispatcher::HandleRequest(const std::string& name,
const Value* args,
+ const GURL& source_url,
int request_id,
bool has_callback) {
scoped_refptr<ExtensionFunction> function(
FactoryRegistry::instance()->NewFunction(name));
function->set_dispatcher_peer(peer_);
function->SetArgs(args);
+ function->set_source_url(source_url);
function->set_request_id(request_id);
function->set_has_callback(has_callback);
ExtensionsService* service = profile()->GetExtensionsService();
diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h
index 86342cc..08e74bc1 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.h
+++ b/chrome/browser/extensions/extension_function_dispatcher.h
@@ -92,7 +92,7 @@ class ExtensionFunctionDispatcher {
// Handle a request to execute an extension function.
void HandleRequest(const std::string& name, const Value* args,
- int request_id, bool has_callback);
+ const GURL& source_url, int request_id, bool has_callback);
// Send a response to a function.
void SendResponse(ExtensionFunction* api, bool success);
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index 1e04547..a9d2259 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -526,11 +526,12 @@ WebPreferences ExtensionHost::GetWebkitPrefs() {
void ExtensionHost::ProcessDOMUIMessage(const std::string& message,
const Value* content,
+ const GURL& source_url,
int request_id,
bool has_callback) {
if (extension_function_dispatcher_.get()) {
extension_function_dispatcher_->HandleRequest(
- message, content, request_id, has_callback);
+ message, content, source_url, request_id, has_callback);
}
}
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index b7de670..4d6ca59 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -121,6 +121,7 @@ class ExtensionHost : public RenderViewHostDelegate,
virtual WebPreferences GetWebkitPrefs();
virtual void ProcessDOMUIMessage(const std::string& message,
const Value* content,
+ const GURL& source_url,
int request_id,
bool has_callback);
virtual void RunJavaScriptMessage(const std::wstring& message,
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index 934f2d6..28b50e9 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "base/histogram.h"
#include "base/base64.h"
#include "base/string_util.h"
#include "chrome/browser/browser.h"
@@ -48,6 +49,19 @@ static bool GetTabById(int tab_id, Profile* profile,
TabContents** contents,
int* tab_index, std::string* error_message);
+// Takes |url_string| and returns a GURL which is either valid and absolute
+// or invalid. If |url_string| is not directly interpretable as a valid (it is
+// likely a relative URL) an attempt is made to resolve it. |extension| is
+// provided so it can be resolved relative to its extension base
+// (chrome-extension://<id>/). |source_url| is provided so that we can test
+// whether |url_string| resolves differently relative to the source frame url.
+// Using the source frame url would be more correct, but because the api shipped
+// with urls resolved relative to their extension base, we must first measure
+// how much of an inpact making the change would have.
+static GURL ResolvePossiblyRelativeURL(std::string url_string,
+ Extension* extension,
+ const GURL& source_url);
+
// Return the type name for a browser window type.
static std::string GetWindowTypeText(Browser::Type type);
@@ -281,26 +295,22 @@ bool GetAllWindowsFunction::RunImpl() {
}
bool CreateWindowFunction::RunImpl() {
- scoped_ptr<GURL> url(new GURL());
+ GURL url;
// Look for optional url.
if (!args_->IsType(Value::TYPE_NULL)) {
EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
const DictionaryValue *args = args_as_dictionary();
- std::string url_input;
+ std::string url_string;
if (args->HasKey(keys::kUrlKey)) {
EXTENSION_FUNCTION_VALIDATE(args->GetString(keys::kUrlKey,
- &url_input));
- url.reset(new GURL(url_input));
- if (!url->is_valid()) {
- // The path as passed in is not valid. Try converting to absolute path.
- *url = GetExtension()->GetResourceURL(url_input);
- if (!url->is_valid()) {
- error_ = ExtensionErrorUtils::FormatErrorMessage(
- keys::kInvalidUrlError,
- url_input);
- return false;
- }
+ &url_string));
+ url = ResolvePossiblyRelativeURL(url_string, GetExtension(),
+ source_url());
+ if (!url.is_valid()) {
+ error_ = ExtensionErrorUtils::FormatErrorMessage(
+ keys::kInvalidUrlError, url_string);
+ return false;
}
}
}
@@ -374,7 +384,7 @@ bool CreateWindowFunction::RunImpl() {
Browser* new_window = new Browser(window_type, window_profile);
new_window->CreateBrowserWindow();
- new_window->AddTabWithURL(*(url.get()), GURL(), PageTransition::LINK, true,
+ new_window->AddTabWithURL(url, GURL(), PageTransition::LINK, true,
-1, false, NULL);
new_window->window()->SetBounds(bounds);
@@ -532,19 +542,15 @@ bool CreateTabFunction::RunImpl() {
// -favIconUrl
std::string url_string;
- scoped_ptr<GURL> url(new GURL());
+ GURL url;
if (args->HasKey(keys::kUrlKey)) {
EXTENSION_FUNCTION_VALIDATE(args->GetString(keys::kUrlKey,
&url_string));
- url.reset(new GURL(url_string));
- if (!url->is_valid()) {
- // The path as passed in is not valid. Try converting to absolute path.
- *url = GetExtension()->GetResourceURL(url_string);
- if (!url->is_valid()) {
- error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError,
- url_string);
- return false;
- }
+ url = ResolvePossiblyRelativeURL(url_string, GetExtension(), source_url());
+ if (!url.is_valid()) {
+ error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError,
+ url_string);
+ return false;
}
}
@@ -563,7 +569,7 @@ bool CreateTabFunction::RunImpl() {
// We can't load extension URLs into incognito windows. Special case to
// fall back to a normal window.
- if (url->SchemeIs(chrome::kExtensionScheme) &&
+ if (url.SchemeIs(chrome::kExtensionScheme) &&
browser->profile()->IsOffTheRecord()) {
browser = Browser::GetOrCreateTabbedBrowser(
browser->profile()->GetOriginalProfile());
@@ -580,7 +586,7 @@ bool CreateTabFunction::RunImpl() {
index = tab_strip->count();
}
- TabContents* contents = browser->AddTabWithURL(*(url.get()), GURL(),
+ TabContents* contents = browser->AddTabWithURL(url, GURL(),
PageTransition::LINK, selected, index, true, NULL);
index = tab_strip->GetIndexOfTabContents(contents);
@@ -632,25 +638,22 @@ bool UpdateTabFunction::RunImpl() {
// -favIconUrl
// Navigate the tab to a new location if the url different.
- std::string url;
+ std::string url_string;
if (update_props->HasKey(keys::kUrlKey)) {
EXTENSION_FUNCTION_VALIDATE(update_props->GetString(
- keys::kUrlKey, &url));
- GURL new_gurl(url);
-
- if (!new_gurl.is_valid()) {
- // The path as passed in is not valid. Try converting to absolute path.
- new_gurl = GetExtension()->GetResourceURL(url);
- if (!new_gurl.is_valid()) {
- error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError,
- url);
- return false;
- }
+ keys::kUrlKey, &url_string));
+ GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension(),
+ source_url());
+
+ if (!url.is_valid()) {
+ error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError,
+ url_string);
+ return false;
}
// JavaScript URLs can do the same kinds of things as cross-origin XHR, so
// we need to check host permissions before allowing them.
- if (new_gurl.SchemeIs(chrome::kJavaScriptScheme)) {
+ if (url.SchemeIs(chrome::kJavaScriptScheme)) {
if (!GetExtension()->CanExecuteScriptOnHost(contents->GetURL(), &error_))
return false;
@@ -665,12 +668,12 @@ bool UpdateTabFunction::RunImpl() {
return false;
}
- controller.LoadURL(new_gurl, GURL(), PageTransition::LINK);
+ controller.LoadURL(url, GURL(), PageTransition::LINK);
// The URL of a tab contents never actually changes to a JavaScript URL, so
// this check only makes sense in other cases.
- if (!new_gurl.SchemeIs(chrome::kJavaScriptScheme))
- DCHECK_EQ(new_gurl.spec(), contents->GetURL().spec());
+ if (!url.SchemeIs(chrome::kJavaScriptScheme))
+ DCHECK_EQ(url.spec(), contents->GetURL().spec());
}
bool selected = false;
@@ -1033,3 +1036,39 @@ static std::string GetWindowTypeText(Browser::Type type) {
DCHECK(type == Browser::TYPE_NORMAL);
return keys::kWindowTypeValueNormal;
}
+
+// These are histogram buckets passed to UMA in the following test of relative
+// URL use in the tabs & windows API.
+enum ExtensionAPIRelativeURLUse {
+ ABSOLUTE_URL,
+ RELATIVE_URL_RESOLUTIONS_DIFFER,
+ RELATIVE_URL_RESOLUTIONS_AGREE,
+ EXTENSION_API_RELATIVE_URL_USE_MAX_VALUE
+};
+
+static GURL ResolvePossiblyRelativeURL(std::string url_string,
+ Extension* extension,
+ const GURL& source_url) {
+ ExtensionAPIRelativeURLUse use_type = ABSOLUTE_URL;
+
+ GURL url = GURL(url_string);
+ if (!url.is_valid()) {
+ url = extension->GetResourceURL(url_string);
+ GURL resolved_url = source_url.Resolve(url_string);
+
+ // Note: It's possible that GetResourceURL() returned an invalid URL
+ // meaning that the url_string contained some kind of invalid characters.
+ // The first test for url.is_valid on the next line puts this case into
+ // the resolutions agree bucket -- in the sense that both resolutions would
+ // have resulted in an invald URL and thus an error being returned to the
+ // caller.
+ use_type = url.is_valid() && (url != resolved_url) ?
+ RELATIVE_URL_RESOLUTIONS_DIFFER : RELATIVE_URL_RESOLUTIONS_AGREE;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("Extensions.APIUse_RelativeURL", use_type,
+ EXTENSION_API_RELATIVE_URL_USE_MAX_VALUE);
+
+ return url;
+}
+