diff options
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/ui/webui/nacl_ui.cc | 109 |
1 files changed, 104 insertions, 5 deletions
diff --git a/chrome/browser/ui/webui/nacl_ui.cc b/chrome/browser/ui/webui/nacl_ui.cc index fd84893..0c59cc6 100644 --- a/chrome/browser/ui/webui/nacl_ui.cc +++ b/chrome/browser/ui/webui/nacl_ui.cc @@ -40,6 +40,7 @@ #include "base/win/windows_version.h" #endif +using content::BrowserThread; using content::PluginService; using content::UserMetricsAction; using content::WebUIMessageHandler; @@ -66,6 +67,37 @@ content::WebUIDataSource* CreateNaClUIHTMLSource() { // //////////////////////////////////////////////////////////////////////////////// +class NaClDOMHandler; + +// This class performs a check that the PNaCl path which was returned by +// PathService is valid. One class instance is created per NaClDOMHandler +// and it is destroyed after the check is completed. +class NaClDOMHandlerProxy : public + base::RefCountedThreadSafe<NaClDOMHandlerProxy> { + public: + explicit NaClDOMHandlerProxy(NaClDOMHandler* handler); + + // A helper to check if PNaCl path exists. + void ValidatePnaclPath(); + + void set_handler(NaClDOMHandler* handler) { + handler_ = handler; + } + + private: + // A helper callback that receives the result of checking if PNaCl path + // exists. + void ValidatePnaclPathCallback(bool is_valid); + + virtual ~NaClDOMHandlerProxy() {} + friend class base::RefCountedThreadSafe<NaClDOMHandlerProxy>; + + // The handler that requested checking PNaCl file path. + NaClDOMHandler* handler_; + + DISALLOW_COPY_AND_ASSIGN(NaClDOMHandlerProxy); +}; + // The handler for JavaScript messages for the about:flags page. class NaClDOMHandler : public WebUIMessageHandler { public: @@ -81,6 +113,11 @@ class NaClDOMHandler : public WebUIMessageHandler { // Callback for the NaCl plugin information. void OnGotPlugins(const std::vector<webkit::WebPluginInfo>& plugins); + // A helper callback that receives the result of checking if PNaCl path + // exists. is_valid is true if the PNaCl path that was returned by + // PathService is valid, and false otherwise. + void DidValidatePnaclPath(bool is_valid); + private: // Called when enough information is gathered to return data back to the page. void MaybeRespondToPage(); @@ -98,18 +135,70 @@ class NaClDOMHandler : public WebUIMessageHandler { // Whether the plugin information is ready. bool has_plugin_info_; + // Whether PNaCl path was validated. PathService can return a path + // that does not exists, so it needs to be validated. + bool pnacl_path_validated_; + bool pnacl_path_exists_; + + // A proxy for handling cross threads messages. + scoped_refptr<NaClDOMHandlerProxy> proxy_; + DISALLOW_COPY_AND_ASSIGN(NaClDOMHandler); }; +NaClDOMHandlerProxy::NaClDOMHandlerProxy(NaClDOMHandler* handler) + : handler_(handler) { +} + +void NaClDOMHandlerProxy::ValidatePnaclPath() { + if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&NaClDOMHandlerProxy::ValidatePnaclPath, this)); + return; + } + + bool is_valid = true; + base::FilePath pnacl_path; + bool got_path = PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_path); + // The PathService may return an empty string if PNaCl is not yet installed. + // However, do not trust that the path returned by the PathService exists. + // Check for existence here. + if (!got_path || pnacl_path.empty() || !file_util::PathExists(pnacl_path)) { + is_valid = false; + } + ValidatePnaclPathCallback(is_valid); +} + +void NaClDOMHandlerProxy::ValidatePnaclPathCallback(bool is_valid) { + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&NaClDOMHandlerProxy::ValidatePnaclPathCallback, + this, is_valid)); + return; + } + + // Check that handler_ is still valid, it could be set to NULL if navigation + // happened while checking that the PNaCl file exists. + if (handler_) + handler_->DidValidatePnaclPath(is_valid); +} + NaClDOMHandler::NaClDOMHandler() : weak_ptr_factory_(this), page_has_requested_data_(false), - has_plugin_info_(false) { + has_plugin_info_(false), + pnacl_path_validated_(false), + pnacl_path_exists_(false), + proxy_(new NaClDOMHandlerProxy(this)) { PluginService::GetInstance()->GetPlugins(base::Bind( &NaClDOMHandler::OnGotPlugins, weak_ptr_factory_.GetWeakPtr())); } NaClDOMHandler::~NaClDOMHandler() { + if (proxy_) + proxy_->set_handler(NULL); } void NaClDOMHandler::RegisterMessages() { @@ -154,6 +243,7 @@ void NaClDOMHandler::OnGotPlugins( } void NaClDOMHandler::PopulatePageInformation(DictionaryValue* naclInfo) { + DCHECK(pnacl_path_validated_); // Store Key-Value pairs of about-information. scoped_ptr<ListValue> list(new ListValue()); @@ -233,10 +323,7 @@ void NaClDOMHandler::PopulatePageInformation(DictionaryValue* naclInfo) { // Obtain the version of the PNaCl translator. base::FilePath pnacl_path; bool got_path = PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_path); - // The PathService may return an empty string if PNaCl is not yet installed. - // However, do not trust that the path returned by the PathService exists. - // Check for existence here. - if (!got_path || pnacl_path.empty() || !file_util::PathExists(pnacl_path)) { + if (!got_path || pnacl_path.empty() || !pnacl_path_exists_) { AddPair(list.get(), ASCIIToUTF16("PNaCl translator"), ASCIIToUTF16("Not installed")); @@ -254,12 +341,24 @@ void NaClDOMHandler::PopulatePageInformation(DictionaryValue* naclInfo) { naclInfo->Set("naclInfo", list.release()); } +void NaClDOMHandler::DidValidatePnaclPath(bool is_valid) { + pnacl_path_validated_ = true; + pnacl_path_exists_ = is_valid; + MaybeRespondToPage(); +} + void NaClDOMHandler::MaybeRespondToPage() { // Don't reply until everything is ready. The page will show a 'loading' // message until then. if (!page_has_requested_data_ || !has_plugin_info_) return; + if (!pnacl_path_validated_) { + DCHECK(proxy_); + proxy_->ValidatePnaclPath(); + return; + } + DictionaryValue naclInfo; PopulatePageInformation(&naclInfo); web_ui()->CallJavascriptFunction("nacl.returnNaClInfo", naclInfo); |