blob: 3b8a576e27cf5508270c3e7cb9369b008191a2ca [file] [log] [blame]
// 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 IOS_WEB_WEBUI_URL_DATA_SOURCE_IOS_IMPL_H_
#define IOS_WEB_WEBUI_URL_DATA_SOURCE_IOS_IMPL_H_
#include <memory>
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner_helpers.h"
#include "ios/web/webui/url_data_manager_ios.h"
#include "ui/base/template_expressions.h"
namespace base {
class RefCountedMemory;
}
namespace web {
class URLDataManagerIOSBackend;
class URLDataSourceIOS;
class URLDataSourceIOSImpl;
// Trait used to handle deleting a URLDataSourceIOS. Deletion happens on the UI
// thread.
//
// Implementation note: the normal shutdown sequence is for the UI loop to stop
// pumping events then the IO loop and thread are stopped. When the
// URLDataSourceIOSs are no longer referenced (which happens when IO thread
// stops) they get added to the UI message loop for deletion. But because the
// UI loop has stopped by the time this happens the URLDataSourceIOSs would be
// leaked.
//
// To make sure URLDataSourceIOSs are properly deleted URLDataManagerIOS
// manages deletion of the URLDataSourceIOSs. When a URLDataSourceIOS is no
// longer referenced it is added to |data_sources_| and a task is posted to the
// UI thread to handle the actual deletion. During shutdown |DeleteDataSources|
// is invoked so that all pending URLDataSourceIOSs are properly deleted.
struct DeleteURLDataSourceIOS {
static void Destruct(const URLDataSourceIOSImpl* data_source) {
URLDataManagerIOS::DeleteDataSource(data_source);
}
};
// A URLDataSourceIOS is an object that can answer requests for data
// asynchronously. URLDataSourceIOSs are collectively owned with refcounting
// smart pointers and should never be deleted on the IO thread, since their
// calls are handled almost always on the UI thread and there's a possibility
// of a data race. The |DeleteDataSource| trait above is used to enforce this.
class URLDataSourceIOSImpl
: public base::RefCountedThreadSafe<URLDataSourceIOSImpl,
DeleteURLDataSourceIOS> {
public:
// See source_name_ below for docs on that parameter. Takes ownership of
// |source|.
URLDataSourceIOSImpl(const std::string& source_name,
URLDataSourceIOS* source);
// Report that a request has resulted in the data |bytes|.
// If the request can't be satisfied, pass NULL for |bytes| to indicate
// the request is over.
virtual void SendResponse(int request_id,
scoped_refptr<base::RefCountedMemory> bytes);
const std::string& source_name() const { return source_name_; }
URLDataSourceIOS* source() const { return source_.get(); }
// Replacements for i18n or null if no replacements are desired.
virtual const ui::TemplateReplacements* GetReplacements() const;
protected:
virtual ~URLDataSourceIOSImpl();
private:
friend class URLDataManagerIOS;
friend class URLDataManagerIOSBackend;
friend class base::DeleteHelper<URLDataSourceIOSImpl>;
// SendResponse invokes this on the IO thread. Notifies the backend to
// handle the actual work of sending the data.
virtual void SendResponseOnIOThread(
int request_id,
scoped_refptr<base::RefCountedMemory> bytes);
// The name of this source.
// E.g., for favicons, this could be "favicon", which results in paths for
// specific resources like "favicon/34" getting sent to this source.
const std::string source_name_;
// This field is set and maintained by URLDataManagerIOSBackend. It is set
// when the DataSource is added, and unset if the DataSource is removed. A
// DataSource can be removed in two ways: the URLDataManagerIOSBackend is
// deleted, or another DataSource is registered with the same name. backend_
// should only be accessed on the IO thread. This reference can't be via a
// scoped_refptr else there would be a cycle between the backend and data
// source.
URLDataManagerIOSBackend* backend_;
std::unique_ptr<URLDataSourceIOS> source_;
};
} // namespace web
#endif // IOS_WEB_WEBUI_URL_DATA_SOURCE_IOS_IMPL_H_