OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/nacl/renderer/ppb_nacl_private_impl.h" | 5 #include "components/nacl/renderer/ppb_nacl_private_impl.h" |
6 | 6 |
7 #include <numeric> | 7 #include <numeric> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/containers/scoped_ptr_hash_map.h" | 14 #include "base/containers/scoped_ptr_hash_map.h" |
15 #include "base/cpu.h" | 15 #include "base/cpu.h" |
16 #include "base/files/file.h" | 16 #include "base/files/file.h" |
17 #include "base/lazy_instance.h" | 17 #include "base/lazy_instance.h" |
18 #include "base/logging.h" | 18 #include "base/logging.h" |
19 #include "base/rand_util.h" | 19 #include "base/rand_util.h" |
20 #include "base/strings/string_split.h" | |
21 #include "base/strings/string_util.h" | |
22 #include "components/nacl/common/nacl_host_messages.h" | 20 #include "components/nacl/common/nacl_host_messages.h" |
23 #include "components/nacl/common/nacl_messages.h" | 21 #include "components/nacl/common/nacl_messages.h" |
24 #include "components/nacl/common/nacl_nonsfi_util.h" | 22 #include "components/nacl/common/nacl_nonsfi_util.h" |
25 #include "components/nacl/common/nacl_switches.h" | 23 #include "components/nacl/common/nacl_switches.h" |
26 #include "components/nacl/common/nacl_types.h" | 24 #include "components/nacl/common/nacl_types.h" |
27 #include "components/nacl/renderer/file_downloader.h" | 25 #include "components/nacl/renderer/file_downloader.h" |
28 #include "components/nacl/renderer/histogram.h" | 26 #include "components/nacl/renderer/histogram.h" |
29 #include "components/nacl/renderer/json_manifest.h" | 27 #include "components/nacl/renderer/json_manifest.h" |
30 #include "components/nacl/renderer/manifest_downloader.h" | 28 #include "components/nacl/renderer/manifest_downloader.h" |
31 #include "components/nacl/renderer/manifest_service_channel.h" | 29 #include "components/nacl/renderer/manifest_service_channel.h" |
(...skipping 15 matching lines...) Expand all Loading... |
47 #include "net/http/http_util.h" | 45 #include "net/http/http_util.h" |
48 #include "ppapi/c/pp_bool.h" | 46 #include "ppapi/c/pp_bool.h" |
49 #include "ppapi/c/private/pp_file_handle.h" | 47 #include "ppapi/c/private/pp_file_handle.h" |
50 #include "ppapi/shared_impl/ppapi_globals.h" | 48 #include "ppapi/shared_impl/ppapi_globals.h" |
51 #include "ppapi/shared_impl/ppapi_permissions.h" | 49 #include "ppapi/shared_impl/ppapi_permissions.h" |
52 #include "ppapi/shared_impl/ppapi_preferences.h" | 50 #include "ppapi/shared_impl/ppapi_preferences.h" |
53 #include "ppapi/shared_impl/var.h" | 51 #include "ppapi/shared_impl/var.h" |
54 #include "ppapi/shared_impl/var_tracker.h" | 52 #include "ppapi/shared_impl/var_tracker.h" |
55 #include "ppapi/thunk/enter.h" | 53 #include "ppapi/thunk/enter.h" |
56 #include "third_party/WebKit/public/platform/WebURLLoader.h" | 54 #include "third_party/WebKit/public/platform/WebURLLoader.h" |
57 #include "third_party/WebKit/public/platform/WebURLResponse.h" | |
58 #include "third_party/WebKit/public/web/WebDocument.h" | 55 #include "third_party/WebKit/public/web/WebDocument.h" |
59 #include "third_party/WebKit/public/web/WebElement.h" | 56 #include "third_party/WebKit/public/web/WebElement.h" |
60 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 57 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
61 #include "third_party/WebKit/public/web/WebPluginContainer.h" | 58 #include "third_party/WebKit/public/web/WebPluginContainer.h" |
62 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" | 59 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" |
63 #include "third_party/WebKit/public/web/WebURLLoaderOptions.h" | 60 #include "third_party/WebKit/public/web/WebURLLoaderOptions.h" |
64 #include "third_party/jsoncpp/source/include/json/reader.h" | 61 #include "third_party/jsoncpp/source/include/json/reader.h" |
65 #include "third_party/jsoncpp/source/include/json/value.h" | 62 #include "third_party/jsoncpp/source/include/json/value.h" |
66 | 63 |
67 namespace nacl { | 64 namespace nacl { |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 if(!sender->Send(new NaClHostMsg_NaClGetNumProcessors(&num_processors))) { | 580 if(!sender->Send(new NaClHostMsg_NaClGetNumProcessors(&num_processors))) { |
584 return 1; | 581 return 1; |
585 } | 582 } |
586 return num_processors; | 583 return num_processors; |
587 } | 584 } |
588 | 585 |
589 PP_Bool PPIsNonSFIModeEnabled() { | 586 PP_Bool PPIsNonSFIModeEnabled() { |
590 return PP_FromBool(IsNonSFIModeEnabled()); | 587 return PP_FromBool(IsNonSFIModeEnabled()); |
591 } | 588 } |
592 | 589 |
593 void GetNexeFd(PP_Instance instance, | 590 void GetNexeFdContinuation(scoped_refptr<ppapi::TrackedCallback> callback, |
594 const std::string& pexe_url, | 591 PP_Bool* out_is_hit, |
595 uint32_t opt_level, | 592 PP_FileHandle* out_handle, |
596 const base::Time& last_modified_time, | 593 int32_t pp_error, |
597 const std::string& etag, | 594 bool is_hit, |
598 bool has_no_store_header, | 595 PP_FileHandle handle) { |
599 base::Callback<void(int32_t, bool, PP_FileHandle)> callback) { | 596 if (pp_error == PP_OK) { |
600 if (!InitializePnaclResourceHost()) { | 597 *out_is_hit = PP_FromBool(is_hit); |
601 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( | 598 *out_handle = handle; |
602 FROM_HERE, | |
603 base::Bind(callback, | |
604 static_cast<int32_t>(PP_ERROR_FAILED), | |
605 false, | |
606 PP_kInvalidFileHandle)); | |
607 return; | |
608 } | 599 } |
| 600 callback->PostRun(pp_error); |
| 601 } |
| 602 |
| 603 int32_t GetNexeFd(PP_Instance instance, |
| 604 const char* pexe_url, |
| 605 uint32_t abi_version, |
| 606 uint32_t opt_level, |
| 607 const char* http_headers_param, |
| 608 const char* extra_flags, |
| 609 PP_Bool* is_hit, |
| 610 PP_FileHandle* handle, |
| 611 struct PP_CompletionCallback callback) { |
| 612 ppapi::thunk::EnterInstance enter(instance, callback); |
| 613 if (enter.failed()) |
| 614 return enter.retval(); |
| 615 if (!pexe_url || !is_hit || !handle) |
| 616 return enter.SetResult(PP_ERROR_BADARGUMENT); |
| 617 if (!InitializePnaclResourceHost()) |
| 618 return enter.SetResult(PP_ERROR_FAILED); |
| 619 |
| 620 std::string http_headers(http_headers_param); |
| 621 net::HttpUtil::HeadersIterator iter( |
| 622 http_headers.begin(), http_headers.end(), "\r\n"); |
| 623 |
| 624 std::string last_modified; |
| 625 std::string etag; |
| 626 bool has_no_store_header = false; |
| 627 while (iter.GetNext()) { |
| 628 if (StringToLowerASCII(iter.name()) == "last-modified") |
| 629 last_modified = iter.values(); |
| 630 if (StringToLowerASCII(iter.name()) == "etag") |
| 631 etag = iter.values(); |
| 632 if (StringToLowerASCII(iter.name()) == "cache-control") { |
| 633 net::HttpUtil::ValuesIterator values_iter( |
| 634 iter.values_begin(), iter.values_end(), ','); |
| 635 while (values_iter.GetNext()) { |
| 636 if (StringToLowerASCII(values_iter.value()) == "no-store") |
| 637 has_no_store_header = true; |
| 638 } |
| 639 } |
| 640 } |
| 641 |
| 642 base::Time last_modified_time; |
| 643 // If FromString fails, it doesn't touch last_modified_time and we just send |
| 644 // the default-constructed null value. |
| 645 base::Time::FromString(last_modified.c_str(), &last_modified_time); |
609 | 646 |
610 PnaclCacheInfo cache_info; | 647 PnaclCacheInfo cache_info; |
611 cache_info.pexe_url = GURL(pexe_url); | 648 cache_info.pexe_url = GURL(pexe_url); |
612 // TODO(dschuff): Get this value from the pnacl json file after it | 649 cache_info.abi_version = abi_version; |
613 // rolls in from NaCl. | |
614 cache_info.abi_version = 1; | |
615 cache_info.opt_level = opt_level; | 650 cache_info.opt_level = opt_level; |
616 cache_info.last_modified = last_modified_time; | 651 cache_info.last_modified = last_modified_time; |
617 cache_info.etag = etag; | 652 cache_info.etag = etag; |
618 cache_info.has_no_store_header = has_no_store_header; | 653 cache_info.has_no_store_header = has_no_store_header; |
619 cache_info.sandbox_isa = GetSandboxArch(); | 654 cache_info.sandbox_isa = GetSandboxArch(); |
620 cache_info.extra_flags = GetCpuFeatures(); | 655 cache_info.extra_flags = std::string(extra_flags); |
621 | 656 |
622 g_pnacl_resource_host.Get()->RequestNexeFd( | 657 g_pnacl_resource_host.Get()->RequestNexeFd( |
623 GetRoutingID(instance), | 658 GetRoutingID(instance), |
624 instance, | 659 instance, |
625 cache_info, | 660 cache_info, |
626 callback); | 661 base::Bind(&GetNexeFdContinuation, enter.callback(), is_hit, handle)); |
| 662 |
| 663 return enter.SetResult(PP_OK_COMPLETIONPENDING); |
627 } | 664 } |
628 | 665 |
629 void ReportTranslationFinished(PP_Instance instance, | 666 void ReportTranslationFinished(PP_Instance instance, |
630 PP_Bool success, | 667 PP_Bool success, |
631 int32_t opt_level, | 668 int32_t opt_level, |
632 int64_t pexe_size, | 669 int64_t pexe_size, |
633 int64_t compile_time_us) { | 670 int64_t compile_time_us) { |
634 if (success == PP_TRUE) { | 671 if (success == PP_TRUE) { |
635 static const int32_t kUnknownOptLevel = 4; | 672 static const int32_t kUnknownOptLevel = 4; |
636 if (opt_level < 0 || opt_level > 3) | 673 if (opt_level < 0 || opt_level > 3) |
(...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1519 DownloadFile(instance, url, | 1556 DownloadFile(instance, url, |
1520 base::Bind(&DidOpenManifestEntry, out_file_info, callback)); | 1557 base::Bind(&DidOpenManifestEntry, out_file_info, callback)); |
1521 } | 1558 } |
1522 | 1559 |
1523 void SetPNaClStartTime(PP_Instance instance) { | 1560 void SetPNaClStartTime(PP_Instance instance) { |
1524 NexeLoadManager* load_manager = GetNexeLoadManager(instance); | 1561 NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
1525 if (load_manager) | 1562 if (load_manager) |
1526 load_manager->set_pnacl_start_time(base::Time::Now()); | 1563 load_manager->set_pnacl_start_time(base::Time::Now()); |
1527 } | 1564 } |
1528 | 1565 |
1529 class PexeDownloader : public blink::WebURLLoaderClient { | |
1530 public: | |
1531 PexeDownloader(PP_Instance instance, | |
1532 scoped_ptr<blink::WebURLLoader> url_loader, | |
1533 const std::string& pexe_url, | |
1534 int32_t pexe_opt_level, | |
1535 const PPP_PexeStreamHandler* stream_handler, | |
1536 void* stream_handler_user_data) | |
1537 : instance_(instance), | |
1538 url_loader_(url_loader.Pass()), | |
1539 pexe_url_(pexe_url), | |
1540 pexe_opt_level_(pexe_opt_level), | |
1541 stream_handler_(stream_handler), | |
1542 stream_handler_user_data_(stream_handler_user_data), | |
1543 success_(false), | |
1544 expected_content_length_(-1), | |
1545 weak_factory_(this) { } | |
1546 | |
1547 void Load(const blink::WebURLRequest& request) { | |
1548 url_loader_->loadAsynchronously(request, this); | |
1549 } | |
1550 | |
1551 private: | |
1552 virtual void didReceiveResponse(blink::WebURLLoader* loader, | |
1553 const blink::WebURLResponse& response) { | |
1554 success_ = (response.httpStatusCode() == 200); | |
1555 if (!success_) | |
1556 return; | |
1557 | |
1558 expected_content_length_ = response.expectedContentLength(); | |
1559 | |
1560 // Defer loading after receiving headers. This is because we may already | |
1561 // have a cached translated nexe, so check for that now. | |
1562 url_loader_->setDefersLoading(true); | |
1563 | |
1564 std::string etag = response.httpHeaderField("etag").utf8(); | |
1565 std::string last_modified = | |
1566 response.httpHeaderField("last-modified").utf8(); | |
1567 base::Time last_modified_time; | |
1568 base::Time::FromString(last_modified.c_str(), &last_modified_time); | |
1569 | |
1570 bool has_no_store_header = false; | |
1571 std::string cache_control = | |
1572 response.httpHeaderField("cache-control").utf8(); | |
1573 | |
1574 std::vector<std::string> values; | |
1575 base::SplitString(cache_control, ',', &values); | |
1576 for (std::vector<std::string>::const_iterator it = values.begin(); | |
1577 it != values.end(); | |
1578 ++it) { | |
1579 if (StringToLowerASCII(*it) == "no-store") | |
1580 has_no_store_header = true; | |
1581 } | |
1582 | |
1583 GetNexeFd(instance_, | |
1584 pexe_url_, | |
1585 pexe_opt_level_, | |
1586 last_modified_time, | |
1587 etag, | |
1588 has_no_store_header, | |
1589 base::Bind(&PexeDownloader::didGetNexeFd, | |
1590 weak_factory_.GetWeakPtr())); | |
1591 } | |
1592 | |
1593 virtual void didGetNexeFd(int32_t pp_error, | |
1594 bool cache_hit, | |
1595 PP_FileHandle file_handle) { | |
1596 if (cache_hit) { | |
1597 stream_handler_->DidCacheHit(stream_handler_user_data_, file_handle); | |
1598 | |
1599 // We delete the PexeDownloader at this point since we successfully got a | |
1600 // cached, translated nexe. | |
1601 delete this; | |
1602 return; | |
1603 } | |
1604 stream_handler_->DidCacheMiss(stream_handler_user_data_, | |
1605 expected_content_length_); | |
1606 | |
1607 // No translated nexe was found in the cache, so we should download the | |
1608 // file to start streaming it. | |
1609 url_loader_->setDefersLoading(false); | |
1610 } | |
1611 | |
1612 virtual void didReceiveData(blink::WebURLLoader* loader, | |
1613 const char* data, | |
1614 int data_length, | |
1615 int encoded_data_length) { | |
1616 // Stream the data we received to the stream callback. | |
1617 stream_handler_->DidStreamData(stream_handler_user_data_, | |
1618 data, | |
1619 data_length); | |
1620 } | |
1621 | |
1622 virtual void didFinishLoading(blink::WebURLLoader* loader, | |
1623 double finish_time, | |
1624 int64_t total_encoded_data_length) { | |
1625 int32_t result = success_ ? PP_OK : PP_ERROR_FAILED; | |
1626 stream_handler_->DidFinishStream(stream_handler_user_data_, result); | |
1627 delete this; | |
1628 } | |
1629 | |
1630 virtual void didFail(blink::WebURLLoader* loader, | |
1631 const blink::WebURLError& error) { | |
1632 success_ = false; | |
1633 } | |
1634 | |
1635 PP_Instance instance_; | |
1636 scoped_ptr<blink::WebURLLoader> url_loader_; | |
1637 std::string pexe_url_; | |
1638 int32_t pexe_opt_level_; | |
1639 const PPP_PexeStreamHandler* stream_handler_; | |
1640 void* stream_handler_user_data_; | |
1641 bool success_; | |
1642 int64_t expected_content_length_; | |
1643 base::WeakPtrFactory<PexeDownloader> weak_factory_; | |
1644 }; | |
1645 | |
1646 void StreamPexe(PP_Instance instance, | |
1647 const char* pexe_url, | |
1648 int32_t opt_level, | |
1649 const PPP_PexeStreamHandler* handler, | |
1650 void* handler_user_data) { | |
1651 content::PepperPluginInstance* plugin_instance = | |
1652 content::PepperPluginInstance::Get(instance); | |
1653 if (!plugin_instance) { | |
1654 base::MessageLoop::current()->PostTask( | |
1655 FROM_HERE, | |
1656 base::Bind(handler->DidFinishStream, | |
1657 handler_user_data, | |
1658 static_cast<int32_t>(PP_ERROR_FAILED))); | |
1659 return; | |
1660 } | |
1661 | |
1662 GURL gurl(pexe_url); | |
1663 const blink::WebDocument& document = | |
1664 plugin_instance->GetContainer()->element().document(); | |
1665 scoped_ptr<blink::WebURLLoader> url_loader( | |
1666 CreateWebURLLoader(document, gurl)); | |
1667 PexeDownloader* downloader = new PexeDownloader(instance, | |
1668 url_loader.Pass(), | |
1669 pexe_url, | |
1670 opt_level, | |
1671 handler, | |
1672 handler_user_data); | |
1673 | |
1674 blink::WebURLRequest url_request = CreateWebURLRequest(document, gurl); | |
1675 // Mark the request as requesting a PNaCl bitcode file, | |
1676 // so that component updater can detect this user action. | |
1677 url_request.addHTTPHeaderField( | |
1678 blink::WebString::fromUTF8("Accept"), | |
1679 blink::WebString::fromUTF8("application/x-pnacl, */*")); | |
1680 downloader->Load(url_request); | |
1681 } | |
1682 | |
1683 const PPB_NaCl_Private nacl_interface = { | 1566 const PPB_NaCl_Private nacl_interface = { |
1684 &LaunchSelLdr, | 1567 &LaunchSelLdr, |
1685 &StartPpapiProxy, | 1568 &StartPpapiProxy, |
1686 &UrandomFD, | 1569 &UrandomFD, |
1687 &Are3DInterfacesDisabled, | 1570 &Are3DInterfacesDisabled, |
1688 &BrokerDuplicateHandle, | 1571 &BrokerDuplicateHandle, |
1689 &GetReadExecPnaclFd, | 1572 &GetReadExecPnaclFd, |
1690 &CreateTemporaryFile, | 1573 &CreateTemporaryFile, |
1691 &GetNumberOfProcessors, | 1574 &GetNumberOfProcessors, |
1692 &PPIsNonSFIModeEnabled, | 1575 &PPIsNonSFIModeEnabled, |
| 1576 &GetNexeFd, |
1693 &ReportTranslationFinished, | 1577 &ReportTranslationFinished, |
1694 &DispatchEvent, | 1578 &DispatchEvent, |
1695 &ReportLoadSuccess, | 1579 &ReportLoadSuccess, |
1696 &ReportLoadError, | 1580 &ReportLoadError, |
1697 &ReportLoadAbort, | 1581 &ReportLoadAbort, |
1698 &NexeDidCrash, | 1582 &NexeDidCrash, |
1699 &InstanceCreated, | 1583 &InstanceCreated, |
1700 &InstanceDestroyed, | 1584 &InstanceDestroyed, |
1701 &NaClDebugEnabledForURL, | 1585 &NaClDebugEnabledForURL, |
1702 &GetSandboxArch, | 1586 &GetSandboxArch, |
1703 &LogToConsole, | 1587 &LogToConsole, |
1704 &GetNaClReadyState, | 1588 &GetNaClReadyState, |
1705 &GetExitStatus, | 1589 &GetExitStatus, |
1706 &SetExitStatus, | 1590 &SetExitStatus, |
1707 &Vlog, | 1591 &Vlog, |
1708 &InitializePlugin, | 1592 &InitializePlugin, |
1709 &GetNexeSize, | 1593 &GetNexeSize, |
1710 &RequestNaClManifest, | 1594 &RequestNaClManifest, |
1711 &GetManifestBaseURL, | 1595 &GetManifestBaseURL, |
1712 &ProcessNaClManifest, | 1596 &ProcessNaClManifest, |
1713 &DevInterfacesEnabled, | 1597 &DevInterfacesEnabled, |
1714 &ManifestGetProgramURL, | 1598 &ManifestGetProgramURL, |
1715 &GetPNaClResourceInfo, | 1599 &GetPNaClResourceInfo, |
1716 &GetCpuFeatureAttrs, | 1600 &GetCpuFeatureAttrs, |
1717 &PostMessageToJavaScript, | 1601 &PostMessageToJavaScript, |
1718 &DownloadNexe, | 1602 &DownloadNexe, |
1719 &ReportSelLdrStatus, | 1603 &ReportSelLdrStatus, |
1720 &LogTranslateTime, | 1604 &LogTranslateTime, |
1721 &OpenManifestEntry, | 1605 &OpenManifestEntry, |
1722 &SetPNaClStartTime, | 1606 &SetPNaClStartTime |
1723 &StreamPexe | |
1724 }; | 1607 }; |
1725 | 1608 |
1726 } // namespace | 1609 } // namespace |
1727 | 1610 |
1728 const PPB_NaCl_Private* GetNaClPrivateInterface() { | 1611 const PPB_NaCl_Private* GetNaClPrivateInterface() { |
1729 return &nacl_interface; | 1612 return &nacl_interface; |
1730 } | 1613 } |
1731 | 1614 |
1732 } // namespace nacl | 1615 } // namespace nacl |
OLD | NEW |