blob: a47b5443d184f367a973b09124bc3289fa452f18 [file] [log] [blame]
// Copyright (c) 2012 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/extensions/api/streams_private/streams_private_api.h"
#include "base/lazy_instance.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/common/extensions/api/streams_private.h"
#include "content/public/browser/stream_handle.h"
#include "content/public/browser/stream_info.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/extension_registry.h"
#include "net/http/http_response_headers.h"
namespace {
void CreateResponseHeadersDictionary(const net::HttpResponseHeaders* headers,
base::DictionaryValue* result) {
if (!headers)
return;
void* iter = NULL;
std::string header_name;
std::string header_value;
while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
base::Value* existing_value = NULL;
if (result->Get(header_name, &existing_value)) {
base::StringValue* existing_string_value =
static_cast<base::StringValue*>(existing_value);
existing_string_value->GetString()->append(", ").append(header_value);
} else {
result->SetString(header_name, header_value);
}
}
}
} // namespace
namespace extensions {
namespace streams_private = api::streams_private;
// static
StreamsPrivateAPI* StreamsPrivateAPI::Get(content::BrowserContext* context) {
return GetFactoryInstance()->Get(context);
}
StreamsPrivateAPI::StreamsPrivateAPI(content::BrowserContext* context)
: browser_context_(context),
extension_registry_observer_(this),
weak_ptr_factory_(this) {
extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
}
StreamsPrivateAPI::~StreamsPrivateAPI() {
}
void StreamsPrivateAPI::ExecuteMimeTypeHandler(
const std::string& extension_id,
content::WebContents* web_contents,
scoped_ptr<content::StreamInfo> stream,
const std::string& view_id,
int64 expected_content_size) {
// Create the event's arguments value.
streams_private::StreamInfo info;
info.mime_type = stream->mime_type;
info.original_url = stream->original_url.spec();
info.stream_url = stream->handle->GetURL().spec();
info.tab_id = ExtensionTabUtil::GetTabId(web_contents);
if (!view_id.empty()) {
info.view_id.reset(new std::string(view_id));
}
int size = -1;
if (expected_content_size <= INT_MAX)
size = expected_content_size;
info.expected_content_size = size;
CreateResponseHeadersDictionary(stream->response_headers.get(),
&info.response_headers.additional_properties);
scoped_ptr<Event> event(
new Event(streams_private::OnExecuteMimeTypeHandler::kEventName,
streams_private::OnExecuteMimeTypeHandler::Create(info)));
EventRouter::Get(browser_context_)
->DispatchEventToExtension(extension_id, event.Pass());
GURL url = stream->handle->GetURL();
streams_[extension_id][url] = make_linked_ptr(stream->handle.release());
}
void StreamsPrivateAPI::AbortStream(const std::string& extension_id,
const GURL& stream_url,
const base::Closure& callback) {
StreamMap::iterator extension_it = streams_.find(extension_id);
if (extension_it == streams_.end()) {
callback.Run();
return;
}
StreamMap::mapped_type* url_map = &extension_it->second;
StreamMap::mapped_type::iterator url_it = url_map->find(stream_url);
if (url_it == url_map->end()) {
callback.Run();
return;
}
url_it->second->AddCloseListener(callback);
url_map->erase(url_it);
}
void StreamsPrivateAPI::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionInfo::Reason reason) {
streams_.erase(extension->id());
}
StreamsPrivateAbortFunction::StreamsPrivateAbortFunction() {
}
ExtensionFunction::ResponseAction StreamsPrivateAbortFunction::Run() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &stream_url_));
StreamsPrivateAPI::Get(browser_context())->AbortStream(
extension_id(), GURL(stream_url_), base::Bind(
&StreamsPrivateAbortFunction::OnClose, this));
return RespondLater();
}
void StreamsPrivateAbortFunction::OnClose() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
Respond(NoArguments());
}
static base::LazyInstance<BrowserContextKeyedAPIFactory<StreamsPrivateAPI> >
g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<StreamsPrivateAPI>*
StreamsPrivateAPI::GetFactoryInstance() {
return g_factory.Pointer();
}
} // namespace extensions