summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/api/media_galleries/media_galleries_api.cc15
-rw-r--r--chrome/browser/extensions/api/messaging/message_service.cc38
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc1
-rw-r--r--chrome/common/extensions/extension_messages.h3
-rw-r--r--chrome/renderer/extensions/dispatcher.cc21
-rw-r--r--chrome/renderer/extensions/dispatcher.h5
-rw-r--r--chrome/renderer/extensions/messaging_bindings.cc64
-rw-r--r--chrome/renderer/extensions/request_sender.cc18
-rw-r--r--chrome/renderer/extensions/request_sender.h17
-rw-r--r--extensions/browser/extension_function.cc13
-rw-r--r--extensions/browser/extension_function.h7
11 files changed, 148 insertions, 54 deletions
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
index aeb41d0..bc56c96 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
@@ -21,6 +21,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/file_system/file_system_api.h"
#include "chrome/browser/extensions/blob_reader.h"
+#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/media_galleries/media_file_system_registry.h"
#include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
#include "chrome/browser/media_galleries/media_galleries_histograms.h"
@@ -539,8 +540,16 @@ void MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit() {
const std::string& app_id = GetExtension()->id();
WebContents* contents = GetWebContents(render_view_host(), profile, app_id);
if (!contents) {
- SendResponse(false);
- return;
+ // When the request originated from a background page, but there is no app
+ // window open, check to see if it originated from a tab and display the
+ // dialog in that tab.
+ bool found_tab = extensions::ExtensionTabUtil::GetTabById(
+ source_tab_id(), profile, profile->IsOffTheRecord(),
+ NULL, NULL, &contents, NULL);
+ if (!found_tab || !contents) {
+ SendResponse(false);
+ return;
+ }
}
if (!user_gesture()) {
@@ -691,7 +700,7 @@ bool MediaGalleriesAddScanResultsFunction::RunImpl() {
void MediaGalleriesAddScanResultsFunction::OnPreferencesInit() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const Extension* extension = GetExtension();
- MediaGalleriesPreferences * preferences =
+ MediaGalleriesPreferences* preferences =
media_file_system_registry()->GetPreferences(GetProfile());
if (MediaGalleriesScanResultDialogController::ScanResultCountForExtension(
preferences, extension) == 0) {
diff --git a/chrome/browser/extensions/api/messaging/message_service.cc b/chrome/browser/extensions/api/messaging/message_service.cc
index 8afd54f..9c54e78 100644
--- a/chrome/browser/extensions/api/messaging/message_service.cc
+++ b/chrome/browser/extensions/api/messaging/message_service.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/extensions/api/messaging/extension_message_port.h"
#include "chrome/browser/extensions/api/messaging/incognito_connectability.h"
#include "chrome/browser/extensions/api/messaging/native_message_port.h"
+#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
@@ -119,14 +120,9 @@ static base::StaticAtomicSequenceNumber g_channel_id_overflow_count;
static content::RenderProcessHost* GetExtensionProcess(
Profile* profile, const std::string& extension_id) {
SiteInstance* site_instance =
- ExtensionSystem::Get(profile)->process_manager()->
- GetSiteInstanceForURL(
- Extension::GetBaseURLFromExtensionId(extension_id));
-
- if (!site_instance->HasProcess())
- return NULL;
-
- return site_instance->GetProcess();
+ ExtensionSystem::Get(profile)->process_manager()->GetSiteInstanceForURL(
+ Extension::GetBaseURLFromExtensionId(extension_id));
+ return site_instance->HasProcess() ? site_instance->GetProcess() : NULL;
}
} // namespace
@@ -152,12 +148,12 @@ void MessageService::AllocatePortIdPair(int* port1, int* port2) {
// Sanity checks to make sure our channel<->port converters are correct.
DCHECK(IS_OPENER_PORT_ID(port1_id));
- DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id);
- DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id);
- DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id));
- DCHECK(GET_CHANNEL_ID(port1_id) == channel_id);
- DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id);
- DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id);
+ DCHECK_EQ(GET_OPPOSITE_PORT_ID(port1_id), port2_id);
+ DCHECK_EQ(GET_OPPOSITE_PORT_ID(port2_id), port1_id);
+ DCHECK_EQ(GET_CHANNEL_ID(port1_id), GET_CHANNEL_ID(port2_id));
+ DCHECK_EQ(GET_CHANNEL_ID(port1_id), channel_id);
+ DCHECK_EQ(GET_CHANNEL_OPENER_ID(channel_id), port1_id);
+ DCHECK_EQ(GET_CHANNEL_RECEIVERS_ID(channel_id), port2_id);
*port1 = port1_id;
*port2 = port2_id;
@@ -300,9 +296,10 @@ void MessageService::OpenChannelToExtension(
GURL source_url_for_tab;
if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) {
- // Platform apps can be sent messages, but don't have a Tab concept.
- if (!target_extension->is_platform_app())
- source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents));
+ // Only the tab id is useful to platform apps for internal use. The
+ // unnecessary bits will be stripped out in
+ // MessagingBindings::DispatchOnConnect().
+ source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents));
source_url_for_tab = source_url;
}
@@ -323,7 +320,9 @@ void MessageService::OpenChannelToExtension(
if (include_tls_channel_id) {
pending_tls_channel_id_channels_[GET_CHANNEL_ID(params->receiver_port_id)]
= PendingMessagesQueue();
- property_provider_.GetDomainBoundCert(profile, params->source_url,
+ property_provider_.GetDomainBoundCert(
+ profile,
+ source_url,
base::Bind(&MessageService::GotDomainBoundCert,
weak_factory_.GetWeakPtr(),
base::Passed(make_scoped_ptr(params))));
@@ -551,8 +550,7 @@ void MessageService::CloseChannelImpl(
channels_.erase(channel_iter);
}
-void MessageService::PostMessage(
- int source_port_id, const Message& message) {
+void MessageService::PostMessage(int source_port_id, const Message& message) {
int channel_id = GET_CHANNEL_ID(source_port_id);
MessageChannelMap::iterator iter = channels_.find(channel_id);
if (iter == channels_.end()) {
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 6ac7e78..1de6920 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -509,6 +509,7 @@ ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction(
function->set_extension(extension);
function->set_profile_id(profile);
function->set_response_callback(callback);
+ function->set_source_tab_id(params.source_tab_id);
return function;
}
diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h
index 3a58cf4..e4e5ec4 100644
--- a/chrome/common/extensions/extension_messages.h
+++ b/chrome/common/extensions/extension_messages.h
@@ -84,6 +84,9 @@ IPC_STRUCT_BEGIN(ExtensionHostMsg_Request_Params)
// extension. Or, they can originate from hosted apps or normal web pages.
IPC_STRUCT_MEMBER(GURL, source_url)
+ // The id of the tab that sent this request, or -1 if there is no source tab.
+ IPC_STRUCT_MEMBER(int, source_tab_id)
+
// Unique request id to match requests and responses.
IPC_STRUCT_MEMBER(int, request_id)
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc
index c2b7499..270a182 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -587,6 +587,12 @@ void Dispatcher::OnDispatchOnConnect(
const base::DictionaryValue& source_tab,
const ExtensionMsg_ExternalConnectionInfo& info,
const std::string& tls_channel_id) {
+ DCHECK(!ContainsKey(port_to_tab_id_map_, target_port_id));
+ DCHECK_EQ(1, target_port_id % 2); // target renderer ports have odd IDs.
+ int sender_tab_id = -1;
+ source_tab.GetInteger("id", &sender_tab_id);
+ port_to_tab_id_map_[target_port_id] = sender_tab_id;
+
MessagingBindings::DispatchOnConnect(
v8_context_set_.GetAll(),
target_port_id, channel_name, source_tab,
@@ -597,6 +603,14 @@ void Dispatcher::OnDispatchOnConnect(
void Dispatcher::OnDeliverMessage(int target_port_id,
const Message& message) {
+ scoped_ptr<RequestSender::ScopedTabID> scoped_tab_id;
+ std::map<int, int>::const_iterator it =
+ port_to_tab_id_map_.find(target_port_id);
+ if (it != port_to_tab_id_map_.end()) {
+ scoped_tab_id.reset(new RequestSender::ScopedTabID(request_sender(),
+ it->second));
+ }
+
MessagingBindings::DeliverMessage(
v8_context_set_.GetAll(),
target_port_id,
@@ -1665,4 +1679,11 @@ void Dispatcher::InvokeModuleSystemMethod(
}
}
+void Dispatcher::ClearPortData(int port_id) {
+ // Only the target port side has entries in |port_to_tab_id_map_|. If
+ // |port_id| is a source port, std::map::erase() will just silently fail
+ // here as a no-op.
+ port_to_tab_id_map_.erase(port_id);
+}
+
} // namespace extensions
diff --git a/chrome/renderer/extensions/dispatcher.h b/chrome/renderer/extensions/dispatcher.h
index bcdece9..57a52e4 100644
--- a/chrome/renderer/extensions/dispatcher.h
+++ b/chrome/renderer/extensions/dispatcher.h
@@ -143,6 +143,8 @@ class Dispatcher : public content::RenderProcessObserver {
const base::ListValue& args,
bool user_gesture);
+ void ClearPortData(int port_id);
+
private:
friend class ::ChromeRenderViewTest;
FRIEND_TEST_ALL_PREFIXES(RendererPermissionsPolicyDelegateTest,
@@ -309,6 +311,9 @@ class Dispatcher : public content::RenderProcessObserver {
std::string system_font_family_;
std::string system_font_size_;
+ // Mapping of port IDs to tabs. If there is no tab, the value would be -1.
+ std::map<int, int> port_to_tab_id_map_;
+
DISALLOW_COPY_AND_ASSIGN(Dispatcher);
};
diff --git a/chrome/renderer/extensions/messaging_bindings.cc b/chrome/renderer/extensions/messaging_bindings.cc
index a265292..8c3bad9 100644
--- a/chrome/renderer/extensions/messaging_bindings.cc
+++ b/chrome/renderer/extensions/messaging_bindings.cc
@@ -47,6 +47,8 @@
using content::RenderThread;
using content::V8ValueConverter;
+namespace extensions {
+
namespace {
struct ExtensionData {
@@ -57,19 +59,19 @@ struct ExtensionData {
std::map<int, PortData> ports; // port ID -> data
};
-static base::LazyInstance<ExtensionData> g_extension_data =
+base::LazyInstance<ExtensionData> g_extension_data =
LAZY_INSTANCE_INITIALIZER;
-static bool HasPortData(int port_id) {
+bool HasPortData(int port_id) {
return g_extension_data.Get().ports.find(port_id) !=
g_extension_data.Get().ports.end();
}
-static ExtensionData::PortData& GetPortData(int port_id) {
+ExtensionData::PortData& GetPortData(int port_id) {
return g_extension_data.Get().ports[port_id];
}
-static void ClearPortData(int port_id) {
+void ClearPortData(int port_id) {
g_extension_data.Get().ports.erase(port_id);
}
@@ -77,11 +79,10 @@ const char kPortClosedError[] = "Attempting to use a disconnected port object";
const char kReceivingEndDoesntExistError[] =
"Could not establish connection. Receiving end does not exist.";
-class ExtensionImpl : public extensions::ChromeV8Extension {
+class ExtensionImpl : public ChromeV8Extension {
public:
- explicit ExtensionImpl(extensions::Dispatcher* dispatcher,
- extensions::ChromeV8Context* context)
- : extensions::ChromeV8Extension(dispatcher, context) {
+ ExtensionImpl(Dispatcher* dispatcher, ChromeV8Context* context)
+ : ChromeV8Extension(dispatcher, context) {
RouteFunction("CloseChannel",
base::Bind(&ExtensionImpl::CloseChannel, base::Unretained(this)));
RouteFunction("PortAddRef",
@@ -97,6 +98,11 @@ class ExtensionImpl : public extensions::ChromeV8Extension {
virtual ~ExtensionImpl() {}
+ void ClearPortDataAndNotifyDispatcher(int port_id) {
+ ClearPortData(port_id);
+ dispatcher()->ClearPortData(port_id);
+ }
+
// Sends a message along the given channel.
void PostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
content::RenderView* renderview = GetRenderView();
@@ -117,9 +123,8 @@ class ExtensionImpl : public extensions::ChromeV8Extension {
renderview->Send(new ExtensionHostMsg_PostMessage(
renderview->GetRoutingID(), port_id,
- extensions::Message(
- *v8::String::Utf8Value(args[1]),
- blink::WebUserGestureIndicator::isProcessingUserGesture())));
+ Message(*v8::String::Utf8Value(args[1]),
+ blink::WebUserGestureIndicator::isProcessingUserGesture())));
}
// Forcefully disconnects a port.
@@ -140,7 +145,7 @@ class ExtensionImpl : public extensions::ChromeV8Extension {
new ExtensionHostMsg_CloseChannel(port_id, std::string()));
}
- ClearPortData(port_id);
+ ClearPortDataAndNotifyDispatcher(port_id);
}
// A new port has been created for a context. This occurs both when script
@@ -167,7 +172,7 @@ class ExtensionImpl : public extensions::ChromeV8Extension {
// Send via the RenderThread because the RenderView might be closing.
content::RenderThread::Get()->Send(
new ExtensionHostMsg_CloseChannel(port_id, std::string()));
- ClearPortData(port_id);
+ ClearPortDataAndNotifyDispatcher(port_id);
}
}
@@ -210,8 +215,8 @@ class ExtensionImpl : public extensions::ChromeV8Extension {
callback->Call(context->Global(), 0, NULL);
}
- extensions::ScopedPersistent<v8::Object> object_;
- extensions::ScopedPersistent<v8::Function> callback_;
+ ScopedPersistent<v8::Object> object_;
+ ScopedPersistent<v8::Function> callback_;
v8::Isolate* isolate_;
DISALLOW_COPY_AND_ASSIGN(GCCallback);
@@ -232,8 +237,6 @@ class ExtensionImpl : public extensions::ChromeV8Extension {
} // namespace
-namespace extensions {
-
ChromeV8Extension* MessagingBindings::Get(
Dispatcher* dispatcher,
ChromeV8Context* context) {
@@ -272,13 +275,14 @@ void MessagingBindings::DispatchOnConnect(
continue;
v8::Handle<v8::Value> tab = v8::Null(isolate);
- if (!source_tab.empty())
- tab = converter->ToV8Value(&source_tab, (*it)->v8_context());
-
v8::Handle<v8::Value> tls_channel_id_value = v8::Undefined(isolate);
- if ((*it)->extension()) {
+ const Extension* extension = (*it)->extension();
+ if (extension) {
+ if (!source_tab.empty() && !extension->is_platform_app())
+ tab = converter->ToV8Value(&source_tab, (*it)->v8_context());
+
ExternallyConnectableInfo* externally_connectable =
- ExternallyConnectableInfo::Get((*it)->extension());
+ ExternallyConnectableInfo::Get(extension);
if (externally_connectable &&
externally_connectable->accepts_tls_channel_id) {
tls_channel_id_value =
@@ -290,23 +294,31 @@ void MessagingBindings::DispatchOnConnect(
}
v8::Handle<v8::Value> arguments[] = {
+ // portId
v8::Integer::New(isolate, target_port_id),
+ // channelName
v8::String::NewFromUtf8(isolate,
channel_name.c_str(),
v8::String::kNormalString,
channel_name.size()),
- tab, v8::String::NewFromUtf8(isolate,
- source_extension_id.c_str(),
- v8::String::kNormalString,
- source_extension_id.size()),
+ // sourceTab
+ tab,
+ // sourceExtensionId
+ v8::String::NewFromUtf8(isolate,
+ source_extension_id.c_str(),
+ v8::String::kNormalString,
+ source_extension_id.size()),
+ // targetExtensionId
v8::String::NewFromUtf8(isolate,
target_extension_id.c_str(),
v8::String::kNormalString,
target_extension_id.size()),
+ // sourceUrl
v8::String::NewFromUtf8(isolate,
source_url_spec.c_str(),
v8::String::kNormalString,
source_url_spec.size()),
+ // tlsChannelId
tls_channel_id_value,
};
diff --git a/chrome/renderer/extensions/request_sender.cc b/chrome/renderer/extensions/request_sender.cc
index a08cca3..c01e0ba 100644
--- a/chrome/renderer/extensions/request_sender.cc
+++ b/chrome/renderer/extensions/request_sender.cc
@@ -26,7 +26,22 @@ struct PendingRequest {
RequestSender::Source* source;
};
-RequestSender::RequestSender(Dispatcher* dispatcher) : dispatcher_(dispatcher) {
+RequestSender::ScopedTabID::ScopedTabID(RequestSender* request_sender,
+ int tab_id)
+ : request_sender_(request_sender),
+ tab_id_(tab_id),
+ previous_tab_id_(request_sender->source_tab_id_) {
+ request_sender_->source_tab_id_ = tab_id;
+}
+
+RequestSender::ScopedTabID::~ScopedTabID() {
+ DCHECK_EQ(tab_id_, request_sender_->source_tab_id_);
+ request_sender_->source_tab_id_ = previous_tab_id_;
+}
+
+RequestSender::RequestSender(Dispatcher* dispatcher)
+ : dispatcher_(dispatcher),
+ source_tab_id_(-1) {
}
RequestSender::~RequestSender() {
@@ -90,6 +105,7 @@ void RequestSender::StartRequest(Source* source,
params.arguments.Swap(value_args);
params.extension_id = context->GetExtensionID();
params.source_url = source_url;
+ params.source_tab_id = source_tab_id_;
params.request_id = request_id;
params.has_callback = has_callback;
params.user_gesture =
diff --git a/chrome/renderer/extensions/request_sender.h b/chrome/renderer/extensions/request_sender.h
index 618a967..1f59ab8 100644
--- a/chrome/renderer/extensions/request_sender.h
+++ b/chrome/renderer/extensions/request_sender.h
@@ -42,6 +42,20 @@ class RequestSender {
const std::string& error) = 0;
};
+ // Helper class to (re)set the |source_tab_id_| below.
+ class ScopedTabID {
+ public:
+ ScopedTabID(RequestSender* request_sender, int tab_id);
+ ~ScopedTabID();
+
+ private:
+ RequestSender* const request_sender_;
+ const int tab_id_;
+ const int previous_tab_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedTabID);
+ };
+
explicit RequestSender(Dispatcher* dispatcher);
~RequestSender();
@@ -73,6 +87,7 @@ class RequestSender {
void InvalidateSource(Source* source);
private:
+ friend class ScopedTabID;
typedef std::map<int, linked_ptr<PendingRequest> > PendingRequestMap;
void InsertRequest(int request_id, PendingRequest* pending_request);
@@ -81,6 +96,8 @@ class RequestSender {
Dispatcher* dispatcher_;
PendingRequestMap pending_requests_;
+ int source_tab_id_; // Id of the tab sending the request, or -1 if no tab.
+
DISALLOW_COPY_AND_ASSIGN(RequestSender);
};
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc
index be5192d..8c7c752 100644
--- a/extensions/browser/extension_function.cc
+++ b/extensions/browser/extension_function.cc
@@ -37,7 +37,7 @@ class UIThreadExtensionFunction::RenderHostTracker
public:
explicit RenderHostTracker(UIThreadExtensionFunction* function)
: content::WebContentsObserver(
- function->render_view_host() ?
+ function->render_view_host() ?
WebContents::FromRenderViewHost(function->render_view_host()) :
WebContents::FromRenderFrameHost(
function->render_frame_host())),
@@ -77,7 +77,9 @@ ExtensionFunction::ExtensionFunction()
include_incognito_(false),
user_gesture_(false),
bad_message_(false),
- histogram_value_(extensions::functions::UNKNOWN) {}
+ histogram_value_(extensions::functions::UNKNOWN),
+ source_tab_id_(-1) {
+}
ExtensionFunction::~ExtensionFunction() {
}
@@ -157,8 +159,11 @@ void ExtensionFunction::SendResponseImpl(bool success) {
}
UIThreadExtensionFunction::UIThreadExtensionFunction()
- : render_view_host_(NULL), render_frame_host_(NULL), context_(NULL),
- delegate_(NULL) {}
+ : render_view_host_(NULL),
+ render_frame_host_(NULL),
+ context_(NULL),
+ delegate_(NULL) {
+}
UIThreadExtensionFunction::~UIThreadExtensionFunction() {
if (dispatcher() && render_view_host())
diff --git a/extensions/browser/extension_function.h b/extensions/browser/extension_function.h
index 49d370e..099dff1 100644
--- a/extensions/browser/extension_function.h
+++ b/extensions/browser/extension_function.h
@@ -192,6 +192,9 @@ class ExtensionFunction
response_callback_ = callback;
}
+ void set_source_tab_id(int source_tab_id) { source_tab_id_ = source_tab_id; }
+ int source_tab_id() const { return source_tab_id_; }
+
protected:
friend struct ExtensionFunctionDeleteTraits;
@@ -264,6 +267,10 @@ class ExtensionFunction
// The callback to run once the function has done execution.
ResponseCallback response_callback_;
+ // The ID of the tab triggered this function call, or -1 if there is no tab.
+ int source_tab_id_;
+
+ private:
DISALLOW_COPY_AND_ASSIGN(ExtensionFunction);
};