diff options
-rw-r--r-- | chrome/browser/extensions/api/media_galleries/media_galleries_api.cc | 15 | ||||
-rw-r--r-- | chrome/browser/extensions/api/messaging/message_service.cc | 38 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function_dispatcher.cc | 1 | ||||
-rw-r--r-- | chrome/common/extensions/extension_messages.h | 3 | ||||
-rw-r--r-- | chrome/renderer/extensions/dispatcher.cc | 21 | ||||
-rw-r--r-- | chrome/renderer/extensions/dispatcher.h | 5 | ||||
-rw-r--r-- | chrome/renderer/extensions/messaging_bindings.cc | 64 | ||||
-rw-r--r-- | chrome/renderer/extensions/request_sender.cc | 18 | ||||
-rw-r--r-- | chrome/renderer/extensions/request_sender.h | 17 | ||||
-rw-r--r-- | extensions/browser/extension_function.cc | 13 | ||||
-rw-r--r-- | extensions/browser/extension_function.h | 7 |
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); }; |