Index: chrome/browser/ui/webui/nacl_ui.cc |
diff --git a/chrome/browser/ui/webui/nacl_ui.cc b/chrome/browser/ui/webui/nacl_ui.cc |
index fd84893e8ea6f7a4d79da59dbc347b3aec6c2924..0c59cc69d240beb6d3d5898b1f9c92ad38d48884 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; |
Dan Beam
2013/05/17 00:19:57
opt nit: 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> { |
Dan Beam
2013/05/17 00:19:57
class NaClDOMHandlerProxy
: public base::RefCo
|
+ public: |
+ explicit NaClDOMHandlerProxy(NaClDOMHandler* handler); |
+ |
+ // A helper to check if PNaCl path exists. |
+ void ValidatePnaclPath(); |
+ |
+ void set_handler(NaClDOMHandler* handler) { |
Dan Beam
2013/05/17 00:19:57
void set_handler(NaClDOMHandler* handler) { handle
|
+ handler_ = handler; |
+ } |
+ |
+ private: |
+ // A helper callback that receives the result of checking if PNaCl path |
+ // exists. |
+ void ValidatePnaclPathCallback(bool is_valid); |
+ |
+ virtual ~NaClDOMHandlerProxy() {} |
Dan Beam
2013/05/17 00:19:57
put dtor second
|
+ friend class base::RefCountedThreadSafe<NaClDOMHandlerProxy>; |
Dan Beam
2013/05/17 00:19:57
put friend first
|
+ |
+ // The handler that requested checking PNaCl file path. |
+ NaClDOMHandler* handler_; |
Dan Beam
2013/05/17 00:19:57
NaclDomHandler* handler_; // weak.
(assuming thi
|
+ |
+ 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 |
Dan Beam
2013/05/17 00:19:57
nit: |is_valid|
|
+ // 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)) { |
Dan Beam
2013/05/17 00:19:57
nit: no curlies
|
+ is_valid = false; |
+ } |
+ ValidatePnaclPathCallback(is_valid); |
Dan Beam
2013/05/17 00:19:57
nit:
ValidatePnaclPathCallback(
got_path && !
|
+} |
+ |
+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)) { |
Dan Beam
2013/05/17 00:19:57
ALLOW_THIS_IN_INITIALIZER_LIST()
|
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); |