Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(641)

Unified Diff: common/xml_parser.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « common/xml_parser.h ('k') | common/xml_parser_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: common/xml_parser.cc
diff --git a/common/xml_parser.cc b/common/xml_parser.cc
deleted file mode 100644
index 22c9eb12abce8428e20631ba3886713ae4d1eca7..0000000000000000000000000000000000000000
--- a/common/xml_parser.cc
+++ /dev/null
@@ -1,1457 +0,0 @@
-// Copyright 2007-2010 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-
-#include "omaha/common/xml_parser.h"
-#include <stdlib.h>
-#include <vector>
-#include "base/basictypes.h"
-#include "omaha/base/constants.h"
-#include "omaha/base/error.h"
-#include "omaha/base/string.h"
-#include "omaha/base/utils.h"
-#include "omaha/base/xml_utils.h"
-#include "omaha/common/config_manager.h"
-#include "omaha/common/goopdate_utils.h"
-#include "omaha/common/update_request.h"
-#include "omaha/common/update_response.h"
-#include "omaha/common/xml_const.h"
-
-namespace omaha {
-
-namespace xml {
-
-namespace {
-
-// Helper structure similar with an std::pair but without a constructor.
-// Instance of it can be stored in arrays.
-template <typename Type1, typename Type2>
-struct Tuple {
- Type1 first;
- Type2 second;
-};
-
-// Converts a string to the SuccessfulInstallAction enum.
-HRESULT ConvertStringToSuccessfulInstallAction(
- const CString& str,
- SuccessfulInstallAction* successful_install_action) {
- ASSERT1(successful_install_action);
-
- const Tuple<const TCHAR*, SuccessfulInstallAction> tuples[] = {
- { xml::value::kSuccessActionDefault,
- SUCCESS_ACTION_DEFAULT },
-
- { xml::value::kSuccessActionExitSilently,
- SUCCESS_ACTION_EXIT_SILENTLY },
-
- { xml::value::kSuccessActionExitSilentlyOnLaunchCmd,
- SUCCESS_ACTION_EXIT_SILENTLY_ON_LAUNCH_CMD },
- };
-
- if (str.IsEmpty()) {
- *successful_install_action = SUCCESS_ACTION_DEFAULT;
- return S_OK;
- }
-
- for (size_t i = 0; i != arraysize(tuples); ++i) {
- if (str.CompareNoCase(tuples[i].first) == 0) {
- *successful_install_action = tuples[i].second;
- return S_OK;
- }
- }
-
- // Using the default action allows Omaha to be forward-compatible with
- // new SuccessActions, meaning older versions will not fail if a config
- // uses a new action.
- ASSERT(false, (_T("[Unrecognized success action][%s]"), str));
- *successful_install_action = SUCCESS_ACTION_DEFAULT;
- return S_OK;
-}
-
-HRESULT ConvertStringToInstallEvent(
- const CString& str,
- InstallAction::InstallEvent* install_event) {
- ASSERT1(install_event);
-
- const Tuple<const TCHAR*, InstallAction::InstallEvent> tuples[] = {
- {xml::value::kPreinstall, InstallAction::kPreInstall},
- {xml::value::kInstall, InstallAction::kInstall},
- {xml::value::kUpdate, InstallAction::kUpdate},
- {xml::value::kPostinstall, InstallAction::kPostInstall},
- };
-
- for (size_t i = 0; i != arraysize(tuples); ++i) {
- if (str.CompareNoCase(tuples[i].first) == 0) {
- *install_event = tuples[i].second;
- return S_OK;
- }
- }
-
- return E_INVALIDARG;
-}
-
-// Returns S_OK if each child element of the node is any of the elements
-// provided as an argument. This is useful to detect if the element contains
-// only known children.
-// TODO(omaha): implement.
-HRESULT AreChildrenAnyOf(IXMLDOMNode* node,
- const std::vector<const TCHAR*>& element_names) {
- UNREFERENCED_PARAMETER(node);
- UNREFERENCED_PARAMETER(element_names);
-
- return S_OK;
-}
-
-// TODO(omaha): implement.
-HRESULT HasNoChildren(IXMLDOMNode* node) {
- UNREFERENCED_PARAMETER(node);
- return S_OK;
-}
-
-// Verify that the protocol version is understood. We accept
-// all version numbers where major version is the same as kExpectedVersion
-// which are greater than or equal to kExpectedVersion. In other words,
-// we handle future minor version number increases which should be
-// compatible.
-HRESULT VerifyProtocolCompatibility(const CString& actual_version,
- const CString& expected_version) {
- if (_tcscmp(actual_version, expected_version) != 0) {
- const double version = String_StringToDouble(actual_version);
- const double expected = String_StringToDouble(expected_version);
- if (expected > version) {
- return GOOPDATEXML_E_XMLVERSION;
- }
- const int version_major = static_cast<int>(version);
- const int expected_major = static_cast<int>(expected);
- if (version_major != expected_major) {
- return GOOPDATEXML_E_XMLVERSION;
- }
- }
- return S_OK;
-}
-
-} // namespace
-
-CString ConvertProcessorArchitectureToString(DWORD arch) {
- switch (arch) {
- case PROCESSOR_ARCHITECTURE_INTEL:
- return xml::value::kArchIntel;
-
- case PROCESSOR_ARCHITECTURE_AMD64:
- return xml::value::kArchAmd64;
-
- default:
- ASSERT1(false);
- return xml::value::kArchUnknown;
- };
-}
-
-// The ElementHandler classes should also be in an anonymous namespace but
-// the base class cannot be because it is used in the header file.
-
-// Defines the base class of a hierarchy that deals with validating and
-// parsing of a single node element in the dom. The implementation uses
-// the template method design pattern.
-class ElementHandler {
- public:
- ElementHandler() {}
- virtual ~ElementHandler() {}
-
- HRESULT Handle(IXMLDOMNode* node, response::Response* response) {
- ASSERT1(node);
- ASSERT1(response);
-
- HRESULT hr = Validate(node);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = Parse(node, response);
- if (FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
- }
-
- private:
- // Validates a node and returns S_OK in case of success.
- virtual HRESULT Validate(IXMLDOMNode* node) {
- UNREFERENCED_PARAMETER(node);
- return S_OK;
- }
-
- // Parses the node and stores its values in the response.
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- UNREFERENCED_PARAMETER(node);
- UNREFERENCED_PARAMETER(response);
- return S_OK;
- }
-
- DISALLOW_COPY_AND_ASSIGN(ElementHandler);
-};
-
-
-// Parses 'response'.
-class ResponseElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new ResponseElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- HRESULT hr = ReadStringAttribute(node,
- xml::attribute::kProtocol,
- &response->protocol);
- if (FAILED(hr)) {
- return hr;
- }
- hr = VerifyProtocolCompatibility(response->protocol, xml::value::kVersion3);
- if (FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
- }
-};
-
-// Parses 'app'.
-class AppElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new AppElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- response::App app;
-
- HRESULT hr = ReadStringAttribute(node, xml::attribute::kAppId, &app.appid);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = ReadStringAttribute(node, xml::attribute::kStatus, &app.status);
- if (FAILED(hr)) {
- return hr;
- }
-
- // At present, the server may omit the following optional attributes if the
- // contents would be empty strings. Guard these reads appropriately.
- // TODO(omaha3): If we adapt the server to send an empty string for these
- // attributes, we can remove these checks.
- if (HasAttribute(node, xml::attribute::kExperiments)) {
- hr = ReadStringAttribute(node,
- xml::attribute::kExperiments,
- &app.experiments);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- response->apps.push_back(app);
- return S_OK;
- }
-};
-
-
-// Parses 'updatecheck'.
-class UpdateCheckElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new UpdateCheckElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- response::UpdateCheck& update_check = response->apps.back().update_check;
-
- ReadStringAttribute(node,
- xml::attribute::kTTToken,
- &update_check.tt_token);
-
- ReadStringAttribute(node,
- xml::attribute::kErrorUrl,
- &update_check.error_url);
-
- return ReadStringAttribute(node,
- xml::attribute::kStatus,
- &update_check.status);
- }
-};
-
-
-// Parses 'urls'.
-class UrlsElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new UrlsElementHandler; }
-};
-
-
-// Parses 'url'.
-class UrlElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new UrlElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- CString url;
- HRESULT hr = ReadStringAttribute(node, xml::attribute::kCodebase, &url);
- if (FAILED(hr)) {
- return hr;
- }
-
- response::UpdateCheck& update_check = response->apps.back().update_check;
- update_check.urls.push_back(url);
-
- return S_OK;
- }
-};
-
-
-// Parses 'manifest'.
-class ManifestElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new ManifestElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- InstallManifest& install_manifest =
- response->apps.back().update_check.install_manifest;
- // TODO(omaha3): Uncomment when version becomes a required value for
- // version 2 configs.
- /*return*/ ReadStringAttribute(node,
- xml::attribute::kVersion,
- &install_manifest.version);
- return S_OK;
- }
-};
-
-
-// Parses 'packages'.
-class PackagesElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new PackagesElementHandler; }
-};
-
-
-
-// Parses 'package'.
-class PackageElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new PackageElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- InstallPackage install_package;
-
- HRESULT hr = ReadStringAttribute(node,
- xml::attribute::kName,
- &install_package.name);
- if (FAILED(hr)) {
- return hr;
- }
-
- install_package.is_required = true;
- hr = ReadBooleanAttribute(node,
- xml::attribute::kRequired,
- &install_package.is_required);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = ReadIntAttribute(node, xml::attribute::kSize, &install_package.size);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = ReadStringAttribute(node,
- xml::attribute::kHash,
- &install_package.hash);
- if (FAILED(hr)) {
- return hr;
- }
-
- InstallManifest& install_manifest =
- response->apps.back().update_check.install_manifest;
- install_manifest.packages.push_back(install_package);
-
- return S_OK;
- }
-};
-
-// Parses 'actions'.
-class ActionsElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new ActionsElementHandler; }
-};
-
-
-// Parses 'action'.
-class ActionElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new ActionElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- InstallAction install_action;
-
- CString event;
- HRESULT hr = ReadStringAttribute(node, xml::attribute::kEvent, &event);
- if (FAILED(hr)) {
- return hr;
- }
- hr = ConvertStringToInstallEvent(event, &install_action.install_event);
- if (FAILED(hr)) {
- return hr;
- }
-
- ReadStringAttribute(node,
- xml::attribute::kRun,
- &install_action.program_to_run);
- ReadStringAttribute(node,
- xml::attribute::kArguments,
- &install_action.program_arguments);
-
- ReadStringAttribute(node,
- xml::attribute::kSuccessUrl,
- &install_action.success_url);
-
- ReadBooleanAttribute(node,
- xml::attribute::kTerminateAllBrowsers,
- &install_action.terminate_all_browsers);
-
- CString success_action;
- ReadStringAttribute(node,
- xml::attribute::kSuccessAction,
- &success_action);
- ConvertStringToSuccessfulInstallAction(success_action,
- &install_action.success_action);
-
- InstallManifest& install_manifest =
- response->apps.back().update_check.install_manifest;
- install_manifest.install_actions.push_back(install_action);
-
- return S_OK;
- }
-};
-
-
-// Parses 'data'.
-class DataElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new DataElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- response->apps.back().data.push_back(response::Data());
- response::Data& data = response->apps.back().data.back();
-
- HRESULT hr = ReadStringAttribute(node,
- xml::attribute::kStatus,
- &data.status);
- if (FAILED(hr)) {
- return hr;
- }
-
- CString data_name;
- hr = ReadStringAttribute(node, xml::attribute::kName, &data_name);
- if (FAILED(hr)) {
- return hr;
- }
-
- if (xml::value::kInstallData != data_name) {
- return E_UNEXPECTED;
- }
-
- hr = ReadStringAttribute(node,
- xml::attribute::kIndex,
- &data.install_data_index);
- if (FAILED(hr)) {
- return hr;
- }
-
- if (data.status != kResponseStatusOkValue) {
- // There is no data, so do not try to read it.
- return S_OK;
- }
-
- return ReadStringValue(node, &data.install_data);
- }
-};
-
-
-// Parses 'ping'.
-class PingElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new PingElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- response::Ping& ping = response->apps.back().ping;
- ReadStringAttribute(node, xml::attribute::kStatus, &ping.status);
- ASSERT1(ping.status == kResponseStatusOkValue);
- return S_OK;
- }
-};
-
-
-// Parses 'event'.
-class EventElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new EventElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- response::Event event;
- ReadStringAttribute(node, xml::attribute::kStatus, &event.status);
- ASSERT1(event.status == kResponseStatusOkValue);
- response::App& app = response->apps.back();
- app.events.push_back(event);
- return S_OK;
- }
-};
-
-// Parses 'daystart'.
-class DayStartElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new DayStartElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- ReadIntAttribute(node,
- xml::attribute::kElapsedSeconds,
- &response->day_start.elapsed_seconds);
- return S_OK;
- }
-};
-
-namespace v2 {
-
-namespace element {
-
-const TCHAR* const kGUpdate = _T("gupdate");
-
-} // namespace element
-
-namespace attributev2 {
-
-// Some v2 offline manifests were incorrectly authored as 'Version' with a
-// capital 'V'.
-const TCHAR* const kVersionProperCased = _T("Version");
-
-} // namespace attribute
-
-namespace value {
-
-const TCHAR* const kVersion2 = _T("2.0");
-
-} // namespace value
-
-// Parses Omaha v2 'gupdate'.
-class GUpdateElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new GUpdateElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- HRESULT hr = ReadStringAttribute(node,
- xml::attribute::kProtocol,
- &response->protocol);
- if (FAILED(hr)) {
- return hr;
- }
- return VerifyProtocolCompatibility(response->protocol,
- value::kVersion2);
- }
-};
-
-// Parses Omaha v2 'updatecheck'.
-class UpdateCheckElementHandler : public ElementHandler {
- public:
- static ElementHandler* Create() { return new UpdateCheckElementHandler; }
-
- private:
- virtual HRESULT Parse(IXMLDOMNode* node, response::Response* response) {
- response::UpdateCheck& update_check = response->apps.back().update_check;
-
- HRESULT hr = ReadStringAttribute(node,
- xml::attribute::kStatus,
- &update_check.status);
- if (FAILED(hr)) {
- return hr;
- }
-
- if (update_check.status.CompareNoCase(kResponseStatusOkValue)) {
- return S_OK;
- }
-
- InstallManifest& install_manifest = update_check.install_manifest;
- if (FAILED(ReadStringAttribute(node,
- xml::attribute::kVersion,
- &install_manifest.version))) {
- ReadStringAttribute(node,
- v2::attributev2::kVersionProperCased,
- &install_manifest.version);
- }
-
- CString url;
- hr = ReadStringAttribute(node, xml::attribute::kCodebase, &url);
- if (FAILED(hr)) {
- return hr;
- }
-
- int start_file_name_idx = url.ReverseFind(_T('/'));
- if (start_file_name_idx <= 0) {
- return GOOPDATEDOWNLOAD_E_INVALID_PATH;
- }
- CString base_url = url.Left(start_file_name_idx + 1);
- update_check.urls.push_back(base_url);
-
- CString package_name = url.Right(url.GetLength() - start_file_name_idx - 1);
- if (package_name.IsEmpty()) {
- return GOOPDATEDOWNLOAD_E_FILE_NAME_EMPTY;
- }
-
- InstallPackage install_package;
- install_package.name = package_name;
- install_package.is_required = true;
- hr = ReadIntAttribute(node, xml::attribute::kSize, &install_package.size);
- if (FAILED(hr)) {
- return hr;
- }
- hr = ReadStringAttribute(node,
- xml::attribute::kHash,
- &install_package.hash);
- if (FAILED(hr)) {
- return hr;
- }
-
- install_manifest.packages.push_back(install_package);
-
- InstallAction install_action;
- install_action.install_event = InstallAction::kInstall;
- install_action.program_to_run = package_name;
- ReadStringAttribute(node,
- xml::attribute::kArguments,
- &install_action.program_arguments);
-
- install_manifest.install_actions.push_back(install_action);
-
- InstallAction post_install_action;
- if (SUCCEEDED(ParsePostInstallActions(node, &post_install_action))) {
- install_manifest.install_actions.push_back(post_install_action);
- }
-
- return S_OK;
- }
-
- HRESULT ParsePostInstallActions(IXMLDOMNode* node,
- InstallAction* post_install_action) {
- InstallAction install_action;
- CString success_action;
- if (FAILED(ReadStringAttribute(node,
- xml::attribute::kSuccessAction,
- &success_action)) &&
- FAILED(ReadStringAttribute(node,
- xml::attribute::kSuccessUrl,
- &install_action.success_url)) &&
- FAILED(ReadBooleanAttribute(node,
- xml::attribute::kTerminateAllBrowsers,
- &install_action.terminate_all_browsers))) {
- return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
- }
-
- install_action.install_event = InstallAction::kPostInstall;
- ReadStringAttribute(node, xml::attribute::kSuccessAction, &success_action);
- ConvertStringToSuccessfulInstallAction(success_action,
- &install_action.success_action);
- ReadStringAttribute(node,
- xml::attribute::kSuccessUrl,
- &install_action.success_url);
- ReadBooleanAttribute(node,
- xml::attribute::kTerminateAllBrowsers,
- &install_action.terminate_all_browsers);
- *post_install_action = install_action;
- return S_OK;
- }
-};
-
-} // namespace v2
-
-XmlParser::XmlParser() {}
-
-void XmlParser::InitializeElementHandlers() {
- const Tuple<const TCHAR*, ElementHandler* (*)()> tuples[] = {
- {xml::element::kAction, &ActionElementHandler::Create},
- {xml::element::kActions, &ActionsElementHandler::Create},
- {xml::element::kApp, &AppElementHandler::Create},
- {xml::element::kData, &DataElementHandler::Create},
- {xml::element::kDayStart, &DayStartElementHandler::Create},
- {xml::element::kEvent, &EventElementHandler::Create},
- {xml::element::kManifest, &ManifestElementHandler::Create},
- {xml::element::kPackage, &PackageElementHandler::Create},
- {xml::element::kPackages, &PackagesElementHandler::Create},
- {xml::element::kPing, &PingElementHandler::Create},
- {xml::element::kResponse, &ResponseElementHandler::Create},
- {xml::element::kUpdateCheck, &UpdateCheckElementHandler::Create},
- {xml::element::kUrl, &UrlElementHandler::Create},
- {xml::element::kUrls, &UrlsElementHandler::Create},
- };
-
- for (size_t i = 0; i != arraysize(tuples); ++i) {
- VERIFY1(element_handler_factory_.Register(tuples[i].first,
- tuples[i].second));
- }
-}
-
-// The AppElementHandler and the DataElementHandler are shared, because the
-// format is identical between Omaha v2 and Omaha v3. We should make copies of
-// the shared classes if these elements diverge between v2 and v3. The worst
-// case scenario is that we break v2 compatibility if we do not do a
-// copy-on-write, which might be acceptable.
-void XmlParser::InitializeLegacyElementHandlers() {
- const Tuple<const TCHAR*, ElementHandler* (*)()> tuples[] = {
- {xml::element::kApp, &AppElementHandler::Create},
- {xml::element::kData, &DataElementHandler::Create},
- {v2::element::kGUpdate, &v2::GUpdateElementHandler::Create},
- {xml::element::kUpdateCheck, &v2::UpdateCheckElementHandler::Create},
- };
-
- for (size_t i = 0; i != arraysize(tuples); ++i) {
- VERIFY1(element_handler_factory_.Register(tuples[i].first,
- tuples[i].second));
- }
-}
-
-HRESULT XmlParser::SerializeRequest(const UpdateRequest& update_request,
- CString* buffer) {
- ASSERT1(buffer);
-
- XmlParser xml_parser;
-
- HRESULT hr = xml_parser.BuildDom(update_request.request());
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = xml_parser.GetXml(buffer);
- if (FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT XmlParser::BuildDom(const request::Request& request) {
- CORE_LOG(L3, (_T("[XmlParser::BuildDom]")));
- HRESULT hr = CoCreateSafeDOMDocument(&document_);
- if (FAILED(hr)) {
- return hr;
- }
-
- request_ = &request;
-
- hr = BuildRequestElement();
- if (FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
-}
-
-// Extract the string out of the DOM, and add the initial processing
-// instruction. The xml property of the document converts to the document from
-// its original encoding to Unicode. As a result, the xml directive and the
-// desired encoding must be explicitely set here.
-HRESULT XmlParser::GetXml(CString* buffer) {
- CORE_LOG(L3, (_T("[XmlParser::GetXml]")));
-
- ASSERT1(buffer);
-
- CComBSTR xml_body;
- HRESULT hr = document_->get_xml(&xml_body);
- if (FAILED(hr)) {
- return hr;
- }
-
- *buffer = kXmlDirective;
- *buffer += xml_body;
-
- // The xml string contains a CR LF pair at the end.
- buffer->TrimRight(_T("\r\n"));
-
- return S_OK;
-}
-
-
-HRESULT XmlParser::BuildRequestElement() {
- CORE_LOG(L3, (_T("[XmlParser::BuildRequestElement]")));
-
- CComPtr<IXMLDOMNode> element;
- HRESULT hr = CreateElementNode(xml::element::kRequest, _T(""), &element);
- if (FAILED(hr)) {
- return hr;
- }
-
- ASSERT1(request_);
-
- // Add attributes to the top element:
- // * protocol - protocol version
- // * version - Omaha version
- // * ismachine - is machine Omaha
- // * installsource - install source
- // * originurl - origin url, primarily set by Update3Web plugins
- // * testsource - test source
- // * requestid - unique request ID
- // * periodoverridesec - override value for update check frequency
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kProtocol,
- request_->protocol_version);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kVersion,
- request_->omaha_version);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kIsMachine,
- request_->is_machine ? _T("1") : _T("0"));
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kSessionId,
- request_->session_id);
- if (FAILED(hr)) {
- return hr;
- }
-
- if (!request_->uid.IsEmpty()) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kUserId,
- request_->uid);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- if (!request_->install_source.IsEmpty()) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kInstallSource,
- request_->install_source);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- if (!request_->origin_url.IsEmpty()) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kOriginURL,
- request_->origin_url);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- if (!request_->test_source.IsEmpty()) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kTestSource,
- request_->test_source);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- if (!request_->request_id.IsEmpty()) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kRequestId,
- request_->request_id);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- if (request_->check_period_sec != -1) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kPeriodOverrideSec,
- itostr(request_->check_period_sec));
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- hr = BuildOsElement(element);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Add the app element sequence to the request.
- hr = BuildAppElement(element);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Add the request node to the document root.
- CComPtr<IXMLDOMElement> element_node;
- hr = element->QueryInterface(&element_node);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = document_->putref_documentElement(element_node);
- if (FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT XmlParser::BuildOsElement(IXMLDOMNode* parent_node) {
- CORE_LOG(L3, (_T("[XmlParser::BuildOsElement]")));
-
- ASSERT1(parent_node);
- ASSERT1(request_);
-
- CComPtr<IXMLDOMNode> element;
- HRESULT hr = CreateElementNode(xml::element::kOs, _T(""), &element);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kPlatform,
- request_->os.platform);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kVersion,
- request_->os.version);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kServicePack,
- request_->os.service_pack);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kArch,
- request_->os.arch);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = parent_node->appendChild(element, NULL);
- if (FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
-}
-
-// Create and add request's to the requests node.
-HRESULT XmlParser::BuildAppElement(IXMLDOMNode* parent_node) {
- CORE_LOG(L3, (_T("[XmlParser::BuildAppElement]")));
-
- ASSERT1(parent_node);
- ASSERT1(request_);
-
- for (size_t i = 0; i < request_->apps.size(); ++i) {
- const request::App& app = request_->apps[i];
-
- CComPtr<IXMLDOMNode> element;
- HRESULT hr = CreateElementNode(xml::element::kApp, _T(""), &element);
- if (FAILED(hr)) {
- return hr;
- }
-
- ASSERT1(IsGuid(app.app_id));
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kAppId,
- app.app_id);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kVersion,
- app.version);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kNextVersion,
- app.next_version);
- if (FAILED(hr)) {
- return hr;
- }
-
- if (!app.ap.IsEmpty()) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kAdditionalParameters,
- app.ap);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kLang,
- app.lang);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kBrandCode,
- app.brand_code);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kClientId,
- app.client_id);
- if (FAILED(hr)) {
- return hr;
- }
-
- // TODO(omaha3): Determine whether or not the server is able to accept an
- // empty string here. If so, remove this IsEmpty() check, and always emit.
- if (!app.experiments.IsEmpty()) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kExperiments,
- app.experiments);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- // 0 seconds indicates unknown install time. A new install uses -1 days.
- if (app.install_time_diff_sec) {
- const int installed_full_days =
- static_cast<int>(app.install_time_diff_sec) / kSecondsPerDay;
- ASSERT1(installed_full_days >= 0 || installed_full_days == -1);
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kInstalledAgeDays,
- itostr(installed_full_days));
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- if (!app.iid.IsEmpty() && app.iid != GuidToString(GUID_NULL)) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kInstallationId,
- app.iid);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- hr = BuildUpdateCheckElement(app, element);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = BuildPingRequestElement(app, element);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = BuildDataElement(app, element);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = BuildDidRunElement(app, element);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = parent_node->appendChild(element, NULL);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- return S_OK;
-}
-
-HRESULT XmlParser::BuildUpdateCheckElement(const request::App& app,
- IXMLDOMNode* parent_node) {
- CORE_LOG(L3, (_T("[XmlParser::BuildUpdateCheckElement]")));
- ASSERT1(parent_node);
-
- // Create a DOM element only if the update check member is valid.
- if (!app.update_check.is_valid) {
- return S_OK;
- }
-
- CComPtr<IXMLDOMNode> element;
- HRESULT hr = CreateElementNode(xml::element::kUpdateCheck, _T(""), &element);
- if (FAILED(hr)) {
- return hr;
- }
-
- if (app.update_check.is_update_disabled) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kUpdateDisabled,
- xml::value::kTrue);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- if (!app.update_check.tt_token.IsEmpty()) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kTTToken,
- app.update_check.tt_token);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- hr = parent_node->appendChild(element, NULL);
- if (FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
-}
-
-// Ping elements are called "event" elements for legacy reasons.
-HRESULT XmlParser::BuildPingRequestElement(const request::App& app,
- IXMLDOMNode* parent_node) {
- CORE_LOG(L3, (_T("[XmlParser::BuildPingRequestElement]")));
- ASSERT1(parent_node);
-
- // Create a DOM element only if there is are ping_events.
- if (app.ping_events.empty()) {
- return S_OK;
- }
-
- PingEventVector::const_iterator it;
- for (it = app.ping_events.begin(); it != app.ping_events.end(); ++it) {
- const PingEventPtr ping_event = *it;
- CComPtr<IXMLDOMNode> element;
- HRESULT hr = CreateElementNode(xml::element::kEvent, _T(""), &element);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = ping_event->ToXml(element);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = parent_node->appendChild(element, NULL);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- return S_OK;
-}
-
-HRESULT XmlParser::BuildDataElement(const request::App& app,
- IXMLDOMNode* parent_node) {
- CORE_LOG(L3, (_T("[XmlParser::BuildDataElement]")));
- ASSERT1(parent_node);
-
- // Create a DOM element only if there is a data object.
- if (app.data.install_data_index.IsEmpty()) {
- return S_OK;
- }
-
- ASSERT1(app.update_check.is_valid);
-
- CComPtr<IXMLDOMNode> element;
- HRESULT hr = CreateElementNode(xml::element::kData, _T(""), &element);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kName,
- xml::value::kInstallData);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kIndex,
- app.data.install_data_index);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = parent_node->appendChild(element, NULL);
- if (FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT XmlParser::BuildDidRunElement(const request::App& app,
- IXMLDOMNode* parent_node) {
- CORE_LOG(L3, (_T("[XmlParser::BuildDidRunElement]")));
- ASSERT1(parent_node);
-
- bool was_active = app.ping.active == ACTIVE_RUN;
- bool need_active = app.ping.active != ACTIVE_UNKNOWN;
- bool has_sent_a_today = app.ping.days_since_last_active_ping == 0;
- bool need_a = was_active && !has_sent_a_today;
- bool need_r = app.ping.days_since_last_roll_call != 0;
-
- // Create a DOM element only if the didrun object has actual state.
- if (!need_active && !need_a && !need_r) {
- return S_OK;
- }
-
- ASSERT1(app.update_check.is_valid);
-
- CComPtr<IXMLDOMNode> element;
- HRESULT hr = CreateElementNode(xml::element::kPing, _T(""), &element);
- if (FAILED(hr)) {
- return hr;
- }
-
- // TODO(omaha): Remove "active" attribute after transition.
- if (need_active) {
- const TCHAR* active_str(was_active ? _T("1") : _T("0"));
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kActive,
- active_str);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- if (need_a) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kDaysSinceLastActivePing,
- itostr(app.ping.days_since_last_active_ping));
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- if (need_r) {
- hr = AddXMLAttributeNode(element,
- kXmlNamespace,
- xml::attribute::kDaysSinceLastRollCall,
- itostr(app.ping.days_since_last_roll_call));
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- hr = parent_node->appendChild(element, NULL);
- if (FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT XmlParser::CreateElementNode(const TCHAR* name,
- const TCHAR* value,
- IXMLDOMNode** element) {
- ASSERT1(name);
- ASSERT1(value);
- ASSERT1(element);
-
- // When there is a namespace, the element names get o: prepended to avoid a
- // size explosion where the namespace uri gets automatically added to every
- // element by msxml.
- CString namespace_qualified_name;
- namespace_qualified_name.Format(kXmlNamespace ? _T("o:%s") : _T("%s"),
- name);
- ASSERT1(document_);
- HRESULT hr = CreateXMLNode(document_,
- NODE_ELEMENT,
- namespace_qualified_name,
- kXmlNamespace,
- value,
- element);
- return hr;
-}
-
-
-HRESULT XmlParser::DeserializeResponse(const std::vector<uint8>& buffer,
- UpdateResponse* update_response) {
- ASSERT1(update_response);
-
- XmlParser xml_parser;
- HRESULT hr = LoadXMLFromRawData(buffer, false, &xml_parser.document_);
- if (FAILED(hr)) {
- return hr;
- }
-
- xml_parser.response_ = &update_response->response_;
-
- hr = xml_parser.Parse();
- if (FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT XmlParser::Parse() {
- CORE_LOG(L3, (_T("[XmlParser::Parse]")));
- ASSERT1(response_);
-
- CComPtr<IXMLDOMElement> root_node;
- HRESULT hr = document_->get_documentElement(&root_node);
- if (FAILED(hr)) {
- return hr;
- }
- if (!root_node) {
- return GOOPDATEXML_E_PARSE_ERROR;
- }
-
- CComBSTR root_name;
- hr = root_node->get_baseName(&root_name);
- if (FAILED(hr)) {
- return hr;
- }
-
- if (root_name == xml::element::kResponse) {
- InitializeElementHandlers();
- return TraverseDOM(root_node);
- }
-
- if (root_name == v2::element::kGUpdate) {
- InitializeLegacyElementHandlers();
- return TraverseDOM(root_node);
- }
-
- return GOOPDATEXML_E_RESPONSENODE;
-}
-
-HRESULT XmlParser::TraverseDOM(IXMLDOMNode* node) {
- CORE_LOG(L5, (_T("[XmlParser::TraverseDOM]")));
- ASSERT1(node);
-
- HRESULT hr = VisitElement(node);
- if (FAILED(hr)) {
- return hr;
- }
-
- CComPtr<IXMLDOMNodeList> children_list;
- hr = node->get_childNodes(&children_list);
- if (FAILED(hr)) {
- return hr;
- }
-
- long num_children = 0; // NOLINT
- hr = children_list->get_length(&num_children);
- if (FAILED(hr)) {
- return hr;
- }
-
- for (int i = 0; i < num_children; ++i) {
- CComPtr<IXMLDOMNode> child_node;
- hr = children_list->get_item(i, &child_node);
- if (FAILED(hr)) {
- return hr;
- }
-
- DOMNodeType type = NODE_INVALID;
- hr = child_node->get_nodeType(&type);
- if (FAILED(hr)) {
- return hr;
- }
-
- ASSERT1(type == NODE_TEXT || type == NODE_ELEMENT || type == NODE_COMMENT);
-
- if (type == NODE_ELEMENT) {
- hr = TraverseDOM(child_node);
- if (FAILED(hr)) {
- return hr;
- }
- }
- }
-
- return S_OK;
-}
-
-HRESULT XmlParser::VisitElement(IXMLDOMNode* node) {
- XMLFQName node_name;
- HRESULT hr = GetXMLFQName(node, &node_name);
- if (FAILED(hr)) {
- CORE_LOG(LE, (_T("[GetXMLFQName failed][0x%x]"), hr));
- return hr;
- }
-
- CORE_LOG(L4, (_T("[element name][%s:%s]"), node_name.uri, node_name.base));
-
- // Ignore elements not understood.
- ElementHandler* element_handler =
- element_handler_factory_.CreateObject(node_name.base);
- if (element_handler) {
- return element_handler->Handle(node, response_);
- } else {
- CORE_LOG(LW, (_T("[VisitElement: don't know how to handle %s:%s]"),
- node_name.uri, node_name.base));
- }
- return S_OK;
-}
-
-} // namespace xml
-
-} // namespace omaha
-
« no previous file with comments | « common/xml_parser.h ('k') | common/xml_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698