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" |
20 #include "components/nacl/common/nacl_host_messages.h" | 22 #include "components/nacl/common/nacl_host_messages.h" |
21 #include "components/nacl/common/nacl_messages.h" | 23 #include "components/nacl/common/nacl_messages.h" |
22 #include "components/nacl/common/nacl_nonsfi_util.h" | 24 #include "components/nacl/common/nacl_nonsfi_util.h" |
23 #include "components/nacl/common/nacl_switches.h" | 25 #include "components/nacl/common/nacl_switches.h" |
24 #include "components/nacl/common/nacl_types.h" | 26 #include "components/nacl/common/nacl_types.h" |
25 #include "components/nacl/renderer/file_downloader.h" | 27 #include "components/nacl/renderer/file_downloader.h" |
26 #include "components/nacl/renderer/histogram.h" | 28 #include "components/nacl/renderer/histogram.h" |
27 #include "components/nacl/renderer/json_manifest.h" | 29 #include "components/nacl/renderer/json_manifest.h" |
28 #include "components/nacl/renderer/manifest_downloader.h" | 30 #include "components/nacl/renderer/manifest_downloader.h" |
29 #include "components/nacl/renderer/manifest_service_channel.h" | 31 #include "components/nacl/renderer/manifest_service_channel.h" |
(...skipping 15 matching lines...) Expand all Loading... |
45 #include "net/http/http_util.h" | 47 #include "net/http/http_util.h" |
46 #include "ppapi/c/pp_bool.h" | 48 #include "ppapi/c/pp_bool.h" |
47 #include "ppapi/c/private/pp_file_handle.h" | 49 #include "ppapi/c/private/pp_file_handle.h" |
48 #include "ppapi/shared_impl/ppapi_globals.h" | 50 #include "ppapi/shared_impl/ppapi_globals.h" |
49 #include "ppapi/shared_impl/ppapi_permissions.h" | 51 #include "ppapi/shared_impl/ppapi_permissions.h" |
50 #include "ppapi/shared_impl/ppapi_preferences.h" | 52 #include "ppapi/shared_impl/ppapi_preferences.h" |
51 #include "ppapi/shared_impl/var.h" | 53 #include "ppapi/shared_impl/var.h" |
52 #include "ppapi/shared_impl/var_tracker.h" | 54 #include "ppapi/shared_impl/var_tracker.h" |
53 #include "ppapi/thunk/enter.h" | 55 #include "ppapi/thunk/enter.h" |
54 #include "third_party/WebKit/public/platform/WebURLLoader.h" | 56 #include "third_party/WebKit/public/platform/WebURLLoader.h" |
| 57 #include "third_party/WebKit/public/platform/WebURLResponse.h" |
55 #include "third_party/WebKit/public/web/WebDocument.h" | 58 #include "third_party/WebKit/public/web/WebDocument.h" |
56 #include "third_party/WebKit/public/web/WebElement.h" | 59 #include "third_party/WebKit/public/web/WebElement.h" |
57 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 60 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
58 #include "third_party/WebKit/public/web/WebPluginContainer.h" | 61 #include "third_party/WebKit/public/web/WebPluginContainer.h" |
59 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" | 62 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" |
60 #include "third_party/WebKit/public/web/WebURLLoaderOptions.h" | 63 #include "third_party/WebKit/public/web/WebURLLoaderOptions.h" |
61 #include "third_party/jsoncpp/source/include/json/reader.h" | 64 #include "third_party/jsoncpp/source/include/json/reader.h" |
62 #include "third_party/jsoncpp/source/include/json/value.h" | 65 #include "third_party/jsoncpp/source/include/json/value.h" |
63 | 66 |
64 namespace nacl { | 67 namespace nacl { |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 if(!sender->Send(new NaClHostMsg_NaClGetNumProcessors(&num_processors))) { | 583 if(!sender->Send(new NaClHostMsg_NaClGetNumProcessors(&num_processors))) { |
581 return 1; | 584 return 1; |
582 } | 585 } |
583 return num_processors; | 586 return num_processors; |
584 } | 587 } |
585 | 588 |
586 PP_Bool PPIsNonSFIModeEnabled() { | 589 PP_Bool PPIsNonSFIModeEnabled() { |
587 return PP_FromBool(IsNonSFIModeEnabled()); | 590 return PP_FromBool(IsNonSFIModeEnabled()); |
588 } | 591 } |
589 | 592 |
590 void GetNexeFdContinuation(scoped_refptr<ppapi::TrackedCallback> callback, | 593 void GetNexeFd(PP_Instance instance, |
591 PP_Bool* out_is_hit, | 594 const std::string& pexe_url, |
592 PP_FileHandle* out_handle, | 595 uint32_t opt_level, |
593 int32_t pp_error, | 596 const base::Time& last_modified_time, |
594 bool is_hit, | 597 const std::string& etag, |
595 PP_FileHandle handle) { | 598 bool has_no_store_header, |
596 if (pp_error == PP_OK) { | 599 base::Callback<void(int32_t, bool, PP_FileHandle)> callback) { |
597 *out_is_hit = PP_FromBool(is_hit); | 600 if (!InitializePnaclResourceHost()) { |
598 *out_handle = handle; | 601 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
| 602 FROM_HERE, |
| 603 base::Bind(callback, |
| 604 static_cast<int32_t>(PP_ERROR_FAILED), |
| 605 false, |
| 606 PP_kInvalidFileHandle)); |
| 607 return; |
599 } | 608 } |
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); | |
646 | 609 |
647 PnaclCacheInfo cache_info; | 610 PnaclCacheInfo cache_info; |
648 cache_info.pexe_url = GURL(pexe_url); | 611 cache_info.pexe_url = GURL(pexe_url); |
649 cache_info.abi_version = abi_version; | 612 // TODO(dschuff): Get this value from the pnacl json file after it |
| 613 // rolls in from NaCl. |
| 614 cache_info.abi_version = 1; |
650 cache_info.opt_level = opt_level; | 615 cache_info.opt_level = opt_level; |
651 cache_info.last_modified = last_modified_time; | 616 cache_info.last_modified = last_modified_time; |
652 cache_info.etag = etag; | 617 cache_info.etag = etag; |
653 cache_info.has_no_store_header = has_no_store_header; | 618 cache_info.has_no_store_header = has_no_store_header; |
654 cache_info.sandbox_isa = GetSandboxArch(); | 619 cache_info.sandbox_isa = GetSandboxArch(); |
655 cache_info.extra_flags = std::string(extra_flags); | 620 cache_info.extra_flags = GetCpuFeatures(); |
656 | 621 |
657 g_pnacl_resource_host.Get()->RequestNexeFd( | 622 g_pnacl_resource_host.Get()->RequestNexeFd( |
658 GetRoutingID(instance), | 623 GetRoutingID(instance), |
659 instance, | 624 instance, |
660 cache_info, | 625 cache_info, |
661 base::Bind(&GetNexeFdContinuation, enter.callback(), is_hit, handle)); | 626 callback); |
662 | |
663 return enter.SetResult(PP_OK_COMPLETIONPENDING); | |
664 } | 627 } |
665 | 628 |
666 void ReportTranslationFinished(PP_Instance instance, | 629 void ReportTranslationFinished(PP_Instance instance, |
667 PP_Bool success, | 630 PP_Bool success, |
668 int32_t opt_level, | 631 int32_t opt_level, |
669 int64_t pexe_size, | 632 int64_t pexe_size, |
670 int64_t compile_time_us) { | 633 int64_t compile_time_us) { |
671 if (success == PP_TRUE) { | 634 if (success == PP_TRUE) { |
672 static const int32_t kUnknownOptLevel = 4; | 635 static const int32_t kUnknownOptLevel = 4; |
673 if (opt_level < 0 || opt_level > 3) | 636 if (opt_level < 0 || opt_level > 3) |
(...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1556 DownloadFile(instance, url, | 1519 DownloadFile(instance, url, |
1557 base::Bind(&DidOpenManifestEntry, out_file_info, callback)); | 1520 base::Bind(&DidOpenManifestEntry, out_file_info, callback)); |
1558 } | 1521 } |
1559 | 1522 |
1560 void SetPNaClStartTime(PP_Instance instance) { | 1523 void SetPNaClStartTime(PP_Instance instance) { |
1561 NexeLoadManager* load_manager = GetNexeLoadManager(instance); | 1524 NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
1562 if (load_manager) | 1525 if (load_manager) |
1563 load_manager->set_pnacl_start_time(base::Time::Now()); | 1526 load_manager->set_pnacl_start_time(base::Time::Now()); |
1564 } | 1527 } |
1565 | 1528 |
| 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 |
1566 const PPB_NaCl_Private nacl_interface = { | 1683 const PPB_NaCl_Private nacl_interface = { |
1567 &LaunchSelLdr, | 1684 &LaunchSelLdr, |
1568 &StartPpapiProxy, | 1685 &StartPpapiProxy, |
1569 &UrandomFD, | 1686 &UrandomFD, |
1570 &Are3DInterfacesDisabled, | 1687 &Are3DInterfacesDisabled, |
1571 &BrokerDuplicateHandle, | 1688 &BrokerDuplicateHandle, |
1572 &GetReadExecPnaclFd, | 1689 &GetReadExecPnaclFd, |
1573 &CreateTemporaryFile, | 1690 &CreateTemporaryFile, |
1574 &GetNumberOfProcessors, | 1691 &GetNumberOfProcessors, |
1575 &PPIsNonSFIModeEnabled, | 1692 &PPIsNonSFIModeEnabled, |
1576 &GetNexeFd, | |
1577 &ReportTranslationFinished, | 1693 &ReportTranslationFinished, |
1578 &DispatchEvent, | 1694 &DispatchEvent, |
1579 &ReportLoadSuccess, | 1695 &ReportLoadSuccess, |
1580 &ReportLoadError, | 1696 &ReportLoadError, |
1581 &ReportLoadAbort, | 1697 &ReportLoadAbort, |
1582 &NexeDidCrash, | 1698 &NexeDidCrash, |
1583 &InstanceCreated, | 1699 &InstanceCreated, |
1584 &InstanceDestroyed, | 1700 &InstanceDestroyed, |
1585 &NaClDebugEnabledForURL, | 1701 &NaClDebugEnabledForURL, |
1586 &GetSandboxArch, | 1702 &GetSandboxArch, |
1587 &LogToConsole, | 1703 &LogToConsole, |
1588 &GetNaClReadyState, | 1704 &GetNaClReadyState, |
1589 &GetExitStatus, | 1705 &GetExitStatus, |
1590 &SetExitStatus, | 1706 &SetExitStatus, |
1591 &Vlog, | 1707 &Vlog, |
1592 &InitializePlugin, | 1708 &InitializePlugin, |
1593 &GetNexeSize, | 1709 &GetNexeSize, |
1594 &RequestNaClManifest, | 1710 &RequestNaClManifest, |
1595 &GetManifestBaseURL, | 1711 &GetManifestBaseURL, |
1596 &ProcessNaClManifest, | 1712 &ProcessNaClManifest, |
1597 &DevInterfacesEnabled, | 1713 &DevInterfacesEnabled, |
1598 &ManifestGetProgramURL, | 1714 &ManifestGetProgramURL, |
1599 &GetPNaClResourceInfo, | 1715 &GetPNaClResourceInfo, |
1600 &GetCpuFeatureAttrs, | 1716 &GetCpuFeatureAttrs, |
1601 &PostMessageToJavaScript, | 1717 &PostMessageToJavaScript, |
1602 &DownloadNexe, | 1718 &DownloadNexe, |
1603 &ReportSelLdrStatus, | 1719 &ReportSelLdrStatus, |
1604 &LogTranslateTime, | 1720 &LogTranslateTime, |
1605 &OpenManifestEntry, | 1721 &OpenManifestEntry, |
1606 &SetPNaClStartTime | 1722 &SetPNaClStartTime, |
| 1723 &StreamPexe |
1607 }; | 1724 }; |
1608 | 1725 |
1609 } // namespace | 1726 } // namespace |
1610 | 1727 |
1611 const PPB_NaCl_Private* GetNaClPrivateInterface() { | 1728 const PPB_NaCl_Private* GetNaClPrivateInterface() { |
1612 return &nacl_interface; | 1729 return &nacl_interface; |
1613 } | 1730 } |
1614 | 1731 |
1615 } // namespace nacl | 1732 } // namespace nacl |
OLD | NEW |