LCOV - code coverage report
Current view: top level - dom/xul/templates - nsXULTemplateQueryProcessorStorage.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 243 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "prprf.h"
       7             : 
       8             : #include "nsIDOMNodeList.h"
       9             : #include "nsUnicharUtils.h"
      10             : 
      11             : #include "nsArrayUtils.h"
      12             : #include "nsVariant.h"
      13             : #include "nsAppDirectoryServiceDefs.h"
      14             : 
      15             : #include "nsIURI.h"
      16             : #include "nsIFileChannel.h"
      17             : #include "nsIFile.h"
      18             : #include "nsGkAtoms.h"
      19             : #include "nsContentUtils.h"
      20             : 
      21             : #include "nsXULTemplateBuilder.h"
      22             : #include "nsXULTemplateResultStorage.h"
      23             : #include "nsXULContentUtils.h"
      24             : #include "nsXULSortService.h"
      25             : 
      26             : #include "mozIStorageService.h"
      27             : #include "nsIChannel.h"
      28             : #include "nsIDocument.h"
      29             : #include "nsNetUtil.h"
      30             : #include "nsTemplateMatch.h"
      31             : 
      32             : //----------------------------------------------------------------------
      33             : //
      34             : // nsXULTemplateResultSetStorage
      35             : //
      36             : 
      37           0 : NS_IMPL_ISUPPORTS(nsXULTemplateResultSetStorage, nsISimpleEnumerator)
      38             : 
      39             : 
      40           0 : nsXULTemplateResultSetStorage::nsXULTemplateResultSetStorage(mozIStorageStatement* aStatement)
      41           0 :         : mStatement(aStatement)
      42             : {
      43             :     uint32_t count;
      44           0 :     nsresult rv = aStatement->GetColumnCount(&count);
      45           0 :     if (NS_FAILED(rv)) {
      46           0 :         mStatement = nullptr;
      47           0 :         return;
      48             :     }
      49           0 :     for (uint32_t c = 0; c < count; c++) {
      50           0 :         nsAutoCString name;
      51           0 :         rv = aStatement->GetColumnName(c, name);
      52           0 :         if (NS_SUCCEEDED(rv)) {
      53           0 :             nsCOMPtr<nsIAtom> columnName = NS_Atomize(NS_LITERAL_CSTRING("?") + name);
      54           0 :             mColumnNames.AppendObject(columnName);
      55             :         }
      56             :     }
      57             : }
      58             : 
      59             : NS_IMETHODIMP
      60           0 : nsXULTemplateResultSetStorage::HasMoreElements(bool *aResult)
      61             : {
      62           0 :     if (!mStatement) {
      63           0 :         *aResult = false;
      64           0 :         return NS_OK;
      65             :     }
      66             : 
      67           0 :     nsresult rv = mStatement->ExecuteStep(aResult);
      68           0 :     NS_ENSURE_SUCCESS(rv, rv);
      69             :     // Because the nsXULTemplateResultSetStorage is owned by many nsXULTemplateResultStorage objects,
      70             :     // it could live longer than it needed to get results.
      71             :     // So we destroy the statement to free resources when all results are fetched
      72           0 :     if (!*aResult) {
      73           0 :         mStatement = nullptr;
      74             :     }
      75           0 :     return NS_OK;
      76             : }
      77             : 
      78             : NS_IMETHODIMP
      79           0 : nsXULTemplateResultSetStorage::GetNext(nsISupports **aResult)
      80             : {
      81             :     nsXULTemplateResultStorage* result =
      82           0 :         new nsXULTemplateResultStorage(this);
      83           0 :     *aResult = result;
      84           0 :     NS_ADDREF(result);
      85           0 :     return NS_OK;
      86             : }
      87             : 
      88             : 
      89             : int32_t
      90           0 : nsXULTemplateResultSetStorage::GetColumnIndex(nsIAtom* aColumnName)
      91             : {
      92           0 :     int32_t count = mColumnNames.Count();
      93           0 :     for (int32_t c = 0; c < count; c++) {
      94           0 :         if (mColumnNames[c] == aColumnName)
      95           0 :             return c;
      96             :     }
      97             : 
      98           0 :     return -1;
      99             : }
     100             : 
     101             : void
     102           0 : nsXULTemplateResultSetStorage::FillColumnValues(nsCOMArray<nsIVariant>& aArray)
     103             : {
     104           0 :     if (!mStatement)
     105           0 :         return;
     106             : 
     107           0 :     int32_t count = mColumnNames.Count();
     108             : 
     109           0 :     for (int32_t c = 0; c < count; c++) {
     110           0 :         RefPtr<nsVariant> value = new nsVariant();
     111             : 
     112             :         int32_t type;
     113           0 :         mStatement->GetTypeOfIndex(c, &type);
     114             : 
     115           0 :         if (type == mStatement->VALUE_TYPE_INTEGER) {
     116           0 :             int64_t val = mStatement->AsInt64(c);
     117           0 :             value->SetAsInt64(val);
     118             :         }
     119           0 :         else if (type == mStatement->VALUE_TYPE_FLOAT) {
     120           0 :             double val = mStatement->AsDouble(c);
     121           0 :             value->SetAsDouble(val);
     122             :         }
     123             :         else {
     124           0 :             nsAutoString val;
     125           0 :             nsresult rv = mStatement->GetString(c, val);
     126           0 :             if (NS_FAILED(rv))
     127           0 :                 value->SetAsAString(EmptyString());
     128             :             else
     129           0 :                 value->SetAsAString(val);
     130             :         }
     131           0 :         aArray.AppendObject(value);
     132             :     }
     133             : }
     134             : 
     135             : 
     136             : 
     137             : //----------------------------------------------------------------------
     138             : //
     139             : // nsXULTemplateQueryProcessorStorage
     140             : //
     141             : 
     142           0 : NS_IMPL_ISUPPORTS(nsXULTemplateQueryProcessorStorage,
     143             :                   nsIXULTemplateQueryProcessor)
     144             : 
     145             : 
     146           0 : nsXULTemplateQueryProcessorStorage::nsXULTemplateQueryProcessorStorage()
     147           0 :     : mGenerationStarted(false)
     148             : {
     149           0 : }
     150             : 
     151             : NS_IMETHODIMP
     152           0 : nsXULTemplateQueryProcessorStorage::GetDatasource(nsIArray* aDataSources,
     153             :                                                   nsIDOMNode* aRootNode,
     154             :                                                   bool aIsTrusted,
     155             :                                                   nsIXULTemplateBuilder* aBuilder,
     156             :                                                   bool* aShouldDelayBuilding,
     157             :                                                   nsISupports** aReturn)
     158             : {
     159           0 :     *aReturn = nullptr;
     160           0 :     *aShouldDelayBuilding = false;
     161             : 
     162           0 :     if (!aIsTrusted) {
     163           0 :         return NS_OK;
     164             :     }
     165             : 
     166             :     uint32_t length;
     167           0 :     nsresult rv = aDataSources->GetLength(&length);
     168           0 :     NS_ENSURE_SUCCESS(rv, rv);
     169             : 
     170           0 :     if (length == 0) {
     171           0 :         return NS_OK;
     172             :     }
     173             : 
     174             :     // We get only the first uri. This query processor supports
     175             :     // only one database at a time.
     176           0 :     nsCOMPtr<nsIURI> uri;
     177           0 :     uri = do_QueryElementAt(aDataSources, 0);
     178             : 
     179           0 :     if (!uri) {
     180             :         // No uri in the list of datasources
     181           0 :         return NS_OK;
     182             :     }
     183             : 
     184             :     nsCOMPtr<mozIStorageService> storage =
     185           0 :         do_GetService("@mozilla.org/storage/service;1", &rv);
     186           0 :     NS_ENSURE_SUCCESS(rv, rv);
     187             : 
     188           0 :     nsCOMPtr<nsIFile> databaseFile;
     189           0 :     nsAutoCString scheme;
     190           0 :     rv = uri->GetScheme(scheme);
     191           0 :     NS_ENSURE_SUCCESS(rv, rv);
     192             : 
     193           0 :     if (scheme.EqualsLiteral("profile")) {
     194             : 
     195           0 :         nsAutoCString path;
     196           0 :         rv = uri->GetPath(path);
     197           0 :         NS_ENSURE_SUCCESS(rv, rv);
     198             : 
     199           0 :         if (path.IsEmpty()) {
     200           0 :             return NS_ERROR_FAILURE;
     201             :         }
     202             : 
     203           0 :         rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
     204           0 :                                              getter_AddRefs(databaseFile));
     205           0 :         NS_ENSURE_SUCCESS(rv, rv);
     206             : 
     207           0 :         rv = databaseFile->AppendNative(path);
     208           0 :         NS_ENSURE_SUCCESS(rv, rv);
     209             :     }
     210             :     else {
     211           0 :         nsCOMPtr<nsIChannel> channel;
     212           0 :         nsCOMPtr<nsINode> node = do_QueryInterface(aRootNode);
     213             : 
     214             :         // The following channel is never openend, so it does not matter what
     215             :         // securityFlags we pass; let's follow the principle of least privilege.
     216           0 :         rv = NS_NewChannel(getter_AddRefs(channel),
     217             :                            uri,
     218             :                            node,
     219             :                            nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
     220             :                            nsIContentPolicy::TYPE_OTHER);
     221           0 :         NS_ENSURE_SUCCESS(rv, rv);
     222             : 
     223           0 :         nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel, &rv);
     224           0 :         if (NS_FAILED(rv)) { // if it fails, not a file url
     225           0 :             nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_BAD_URI);
     226           0 :             return rv;
     227             :         }
     228             : 
     229           0 :         rv = fileChannel->GetFile(getter_AddRefs(databaseFile));
     230           0 :         NS_ENSURE_SUCCESS(rv, rv);
     231             :     }
     232             : 
     233             :     // ok now we have an URI of a sqlite file
     234           0 :     nsCOMPtr<mozIStorageConnection> connection;
     235           0 :     rv = storage->OpenDatabase(databaseFile, getter_AddRefs(connection));
     236           0 :     if (NS_FAILED(rv)) {
     237           0 :         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_CANNOT_OPEN_DATABASE);
     238           0 :         return rv;
     239             :     }
     240             : 
     241           0 :     connection.forget(aReturn);
     242           0 :     return NS_OK;
     243             : }
     244             : 
     245             : 
     246             : 
     247             : NS_IMETHODIMP
     248           0 : nsXULTemplateQueryProcessorStorage::InitializeForBuilding(nsISupports* aDatasource,
     249             :                                                           nsIXULTemplateBuilder* aBuilder,
     250             :                                                           nsIDOMNode* aRootNode)
     251             : {
     252           0 :     NS_ENSURE_STATE(!mGenerationStarted);
     253             : 
     254           0 :     mStorageConnection = do_QueryInterface(aDatasource);
     255           0 :     if (!mStorageConnection)
     256           0 :         return NS_ERROR_INVALID_ARG;
     257             : 
     258             :     bool ready;
     259           0 :     mStorageConnection->GetConnectionReady(&ready);
     260           0 :     if (!ready)
     261           0 :       return NS_ERROR_UNEXPECTED;
     262             : 
     263           0 :     return NS_OK;
     264             : }
     265             : 
     266             : NS_IMETHODIMP
     267           0 : nsXULTemplateQueryProcessorStorage::Done()
     268             : {
     269           0 :     mGenerationStarted = false;
     270           0 :     return NS_OK;
     271             : }
     272             : 
     273             : NS_IMETHODIMP
     274           0 : nsXULTemplateQueryProcessorStorage::CompileQuery(nsIXULTemplateBuilder* aBuilder,
     275             :                                                  nsIDOMNode* aQueryNode,
     276             :                                                  nsIAtom* aRefVariable,
     277             :                                                  nsIAtom* aMemberVariable,
     278             :                                                  nsISupports** aReturn)
     279             : {
     280           0 :     nsCOMPtr<nsIDOMNodeList> childNodes;
     281           0 :     aQueryNode->GetChildNodes(getter_AddRefs(childNodes));
     282             : 
     283             :     uint32_t length;
     284           0 :     childNodes->GetLength(&length);
     285             : 
     286           0 :     nsCOMPtr<mozIStorageStatement> statement;
     287           0 :     nsCOMPtr<nsIContent> queryContent = do_QueryInterface(aQueryNode);
     288           0 :     nsAutoString sqlQuery;
     289             : 
     290             :     // Let's get all text nodes (which should be the query)
     291           0 :     if (!nsContentUtils::GetNodeTextContent(queryContent, false, sqlQuery, fallible)) {
     292           0 :       return NS_ERROR_OUT_OF_MEMORY;
     293             :     }
     294             : 
     295           0 :     nsresult rv = mStorageConnection->CreateStatement(NS_ConvertUTF16toUTF8(sqlQuery),
     296           0 :                                                               getter_AddRefs(statement));
     297           0 :     if (NS_FAILED(rv)) {
     298           0 :         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_BAD_QUERY);
     299           0 :         return rv;
     300             :     }
     301             : 
     302           0 :     uint32_t parameterCount = 0;
     303           0 :     for (nsIContent* child = queryContent->GetFirstChild();
     304           0 :          child;
     305           0 :          child = child->GetNextSibling()) {
     306             : 
     307           0 :         if (child->NodeInfo()->Equals(nsGkAtoms::param, kNameSpaceID_XUL)) {
     308           0 :             nsAutoString value;
     309           0 :             if (!nsContentUtils::GetNodeTextContent(child, false, value, fallible)) {
     310           0 :               return NS_ERROR_OUT_OF_MEMORY;
     311             :             }
     312             : 
     313           0 :             uint32_t index = parameterCount;
     314           0 :             nsAutoString name, indexValue;
     315             : 
     316           0 :             if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name)) {
     317           0 :                 rv = statement->GetParameterIndex(NS_ConvertUTF16toUTF8(name),
     318           0 :                                                   &index);
     319           0 :                 if (NS_FAILED(rv)) {
     320           0 :                     nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_UNKNOWN_QUERY_PARAMETER);
     321           0 :                     return rv;
     322             :                 }
     323           0 :                 parameterCount++;
     324             :             }
     325           0 :             else if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::index, indexValue)) {
     326           0 :                 PR_sscanf(NS_ConvertUTF16toUTF8(indexValue).get(),"%d",&index);
     327           0 :                 if (index > 0)
     328           0 :                     index--;
     329             :             }
     330             :             else {
     331           0 :                 parameterCount++;
     332             :             }
     333             : 
     334             :             static nsIContent::AttrValuesArray sTypeValues[] =
     335             :                 { &nsGkAtoms::int32, &nsGkAtoms::integer, &nsGkAtoms::int64,
     336             :                   &nsGkAtoms::null, &nsGkAtoms::double_, &nsGkAtoms::string, nullptr };
     337             : 
     338           0 :             int32_t typeError = 1;
     339           0 :             int32_t typeValue = child->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type,
     340           0 :                                                        sTypeValues, eCaseMatters);
     341           0 :             rv = NS_ERROR_ILLEGAL_VALUE;
     342           0 :             int32_t valInt32 = 0;
     343           0 :             int64_t valInt64 = 0;
     344           0 :             double valFloat = 0;
     345             : 
     346           0 :             switch (typeValue) {
     347             :               case 0:
     348             :               case 1:
     349           0 :                 typeError = PR_sscanf(NS_ConvertUTF16toUTF8(value).get(),"%d",&valInt32);
     350           0 :                 if (typeError > 0)
     351           0 :                     rv = statement->BindInt32ByIndex(index, valInt32);
     352           0 :                 break;
     353             :               case 2:
     354           0 :                 typeError = PR_sscanf(NS_ConvertUTF16toUTF8(value).get(),"%lld",&valInt64);
     355           0 :                 if (typeError > 0)
     356           0 :                     rv = statement->BindInt64ByIndex(index, valInt64);
     357           0 :                 break;
     358             :               case 3:
     359           0 :                 rv = statement->BindNullByIndex(index);
     360           0 :                 break;
     361             :               case 4:
     362           0 :                 typeError = PR_sscanf(NS_ConvertUTF16toUTF8(value).get(),"%lf",&valFloat);
     363           0 :                 if (typeError > 0)
     364           0 :                     rv = statement->BindDoubleByIndex(index, valFloat);
     365           0 :                 break;
     366             :               case 5:
     367             :               case nsIContent::ATTR_MISSING:
     368           0 :                 rv = statement->BindStringByIndex(index, value);
     369           0 :                 break;
     370             :               default:
     371           0 :                 typeError = 0;
     372             :             }
     373             : 
     374           0 :             if (typeError <= 0) {
     375           0 :                 nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_WRONG_TYPE_QUERY_PARAMETER);
     376           0 :                 return rv;
     377             :             }
     378             : 
     379           0 :             if (NS_FAILED(rv)) {
     380           0 :                 nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_QUERY_PARAMETER_NOT_BOUND);
     381           0 :                 return rv;
     382             :             }
     383             :         }
     384             :     }
     385             : 
     386           0 :     *aReturn = statement;
     387           0 :     NS_IF_ADDREF(*aReturn);
     388             : 
     389           0 :     return NS_OK;
     390             : }
     391             : 
     392             : NS_IMETHODIMP
     393           0 : nsXULTemplateQueryProcessorStorage::GenerateResults(nsISupports* aDatasource,
     394             :                                                     nsIXULTemplateResult* aRef,
     395             :                                                     nsISupports* aQuery,
     396             :                                                     nsISimpleEnumerator** aResults)
     397             : {
     398           0 :     mGenerationStarted = true;
     399             : 
     400           0 :     nsCOMPtr<mozIStorageStatement> statement = do_QueryInterface(aQuery);
     401           0 :     if (!statement)
     402           0 :         return NS_ERROR_FAILURE;
     403             : 
     404             :     nsXULTemplateResultSetStorage* results =
     405           0 :         new nsXULTemplateResultSetStorage(statement);
     406           0 :     *aResults = results;
     407           0 :     NS_ADDREF(*aResults);
     408             : 
     409           0 :     return NS_OK;
     410             : }
     411             : 
     412             : NS_IMETHODIMP
     413           0 : nsXULTemplateQueryProcessorStorage::AddBinding(nsIDOMNode* aRuleNode,
     414             :                                                nsIAtom* aVar,
     415             :                                                nsIAtom* aRef,
     416             :                                                const nsAString& aExpr)
     417             : {
     418           0 :     return NS_OK;
     419             : }
     420             : 
     421             : NS_IMETHODIMP
     422           0 : nsXULTemplateQueryProcessorStorage::TranslateRef(nsISupports* aDatasource,
     423             :                                                  const nsAString& aRefString,
     424             :                                                  nsIXULTemplateResult** aRef)
     425             : {
     426             :     nsXULTemplateResultStorage* result =
     427           0 :         new nsXULTemplateResultStorage(nullptr);
     428           0 :     *aRef = result;
     429           0 :     NS_ADDREF(*aRef);
     430           0 :     return NS_OK;
     431             : }
     432             : 
     433             : 
     434             : NS_IMETHODIMP
     435           0 : nsXULTemplateQueryProcessorStorage::CompareResults(nsIXULTemplateResult* aLeft,
     436             :                                                    nsIXULTemplateResult* aRight,
     437             :                                                    nsIAtom* aVar,
     438             :                                                    uint32_t aSortHints,
     439             :                                                    int32_t* aResult)
     440             : {
     441           0 :     *aResult = 0;
     442           0 :     if (!aVar)
     443           0 :       return NS_OK;
     444             : 
     445             :     // We're going to see if values are integers or float, to perform
     446             :     // a suitable comparison
     447           0 :     nsCOMPtr<nsISupports> leftValue, rightValue;
     448           0 :     if (aLeft)
     449           0 :       aLeft->GetBindingObjectFor(aVar, getter_AddRefs(leftValue));
     450           0 :     if (aRight)
     451           0 :       aRight->GetBindingObjectFor(aVar, getter_AddRefs(rightValue));
     452             : 
     453           0 :     if (leftValue && rightValue) {
     454           0 :         nsCOMPtr<nsIVariant> vLeftValue = do_QueryInterface(leftValue);
     455           0 :         nsCOMPtr<nsIVariant> vRightValue = do_QueryInterface(rightValue);
     456             : 
     457           0 :         if (vLeftValue && vRightValue) {
     458             :             nsresult rv1, rv2;
     459             :             uint16_t vtypeL, vtypeR;
     460           0 :             vLeftValue->GetDataType(&vtypeL);
     461           0 :             vRightValue->GetDataType(&vtypeR);
     462             : 
     463           0 :             if (vtypeL == vtypeR) {
     464           0 :                 if (vtypeL == nsIDataType::VTYPE_INT64) {
     465             :                     int64_t leftValue, rightValue;
     466           0 :                     rv1 = vLeftValue->GetAsInt64(&leftValue);
     467           0 :                     rv2 = vRightValue->GetAsInt64(&rightValue);
     468           0 :                     if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
     469           0 :                         if (leftValue > rightValue)
     470           0 :                             *aResult = 1;
     471           0 :                         else if (leftValue < rightValue)
     472           0 :                             *aResult = -1;
     473           0 :                         return NS_OK;
     474             :                     }
     475             :                 }
     476           0 :                 else if (vtypeL == nsIDataType::VTYPE_DOUBLE) {
     477             :                     double leftValue, rightValue;
     478           0 :                     rv1 = vLeftValue->GetAsDouble(&leftValue);
     479           0 :                     rv2 = vRightValue->GetAsDouble(&rightValue);
     480           0 :                     if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
     481           0 :                         if (leftValue > rightValue)
     482           0 :                             *aResult = 1;
     483           0 :                         else if (leftValue < rightValue)
     484           0 :                             *aResult = -1;
     485           0 :                         return NS_OK;
     486             :                     }
     487             :                 }
     488             :             }
     489             :         }
     490             :     }
     491             : 
     492             :     // Values are not integers or floats, so we just compare them as simple strings
     493           0 :     nsAutoString leftVal;
     494           0 :     if (aLeft)
     495           0 :         aLeft->GetBindingFor(aVar, leftVal);
     496             : 
     497           0 :     nsAutoString rightVal;
     498           0 :     if (aRight)
     499           0 :         aRight->GetBindingFor(aVar, rightVal);
     500             : 
     501           0 :     *aResult = XULSortServiceImpl::CompareValues(leftVal, rightVal, aSortHints);
     502           0 :     return NS_OK;
     503             : }

Generated by: LCOV version 1.13